From 661e32835993849253f695ebefd3363b8a0a054c Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 21 Dec 2024 10:27:43 +0800 Subject: [PATCH 01/14] perf(script): update install script file, add REGISTER_INSTALL_PREFIX compile flag to gflag --- install.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/install.py b/install.py index 6f30169..f87676f 100644 --- a/install.py +++ b/install.py @@ -54,7 +54,10 @@ def _clone_github_repo(self, repo_url, repo_name, *args): for arg in args: command += " " + arg print("clone: {}".format(command)) - subprocess.run(command, shell=True) + result = subprocess.run(command, shell=True) + if result.returncode != 0: + print("clone failed: {}".format(repo_url)) + raise Exception("clone failed: {}".format(repo_url)) def _clone_setup(self): self._clone_github_repo( @@ -134,8 +137,10 @@ def _clone_gfamily(self): self._cmd("mkdir -p build") os.chdir("build") self._cmd( - "cmake -DCMAKE_CXX_FLAGS='-fPIC' -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( - self._install_prefix)) + "cmake -DCMAKE_CXX_FLAGS='-fPIC' -DREGISTER_INSTALL_PREFIX=OFF -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( + self._install_prefix + ) + ) self._cmd("make install -j$(nproc)") os.chdir(self._current_path) From 1f2be077ce4c42adb931e35f8dd447b90ac0f1f4 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 21 Dec 2024 10:28:11 +0800 Subject: [PATCH 02/14] docs: update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 10a47da..4536135 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ cd CyberRT > install ```shell -sudo python3 install.py -# sudo python3 install.py --platform --install_prefix +python3 install.py +# python3 install.py --platform --install_prefix ``` > export path From 7a248763e22b76f83adaa0008edc20f18f67c1d8 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sun, 22 Dec 2024 15:03:34 +0800 Subject: [PATCH 03/14] perf(proto): remove protobuf source files --- .gitignore | 5 + cyber/examples/proto/examples.pb.cc | 1070 ------------------------- cyber/examples/proto/examples.pb.h | 1114 -------------------------- cyber/examples/proto/examples_pb2.py | 192 ----- cyber/proto/.gitignore | 3 - modules/common_msgs/.gitignore | 3 - 6 files changed, 5 insertions(+), 2382 deletions(-) delete mode 100644 cyber/examples/proto/examples.pb.cc delete mode 100644 cyber/examples/proto/examples.pb.h delete mode 100644 cyber/examples/proto/examples_pb2.py delete mode 100644 cyber/proto/.gitignore delete mode 100644 modules/common_msgs/.gitignore diff --git a/.gitignore b/.gitignore index 47b0ac4..b8bff28 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,11 @@ *.log .DS_Store +# protobuf source file +*.pb.cc +*.pb.h +*_pb2.py + build/ cmake-build* third_party/ diff --git a/cyber/examples/proto/examples.pb.cc b/cyber/examples/proto/examples.pb.cc deleted file mode 100644 index 6f589a3..0000000 --- a/cyber/examples/proto/examples.pb.cc +++ /dev/null @@ -1,1070 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: cyber/examples/proto/examples.proto - -#include "cyber/examples/proto/examples.pb.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include -namespace apollo { -namespace cyber { -namespace examples { -namespace proto { -class SamplesTest1DefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _SamplesTest1_default_instance_; -class ChatterDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Chatter_default_instance_; -class DriverDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Driver_default_instance_; -} // namespace proto -} // namespace examples -} // namespace cyber -} // namespace apollo -static void InitDefaultsscc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::apollo::cyber::examples::proto::_Chatter_default_instance_; - new (ptr) ::apollo::cyber::examples::proto::Chatter(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto}, {}}; - -static void InitDefaultsscc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::apollo::cyber::examples::proto::_Driver_default_instance_; - new (ptr) ::apollo::cyber::examples::proto::Driver(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto}, {}}; - -static void InitDefaultsscc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::apollo::cyber::examples::proto::_SamplesTest1_default_instance_; - new (ptr) ::apollo::cyber::examples::proto::SamplesTest1(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto}, {}}; - -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_cyber_2fexamples_2fproto_2fexamples_2eproto[3]; -static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_cyber_2fexamples_2fproto_2fexamples_2eproto = nullptr; -static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_cyber_2fexamples_2fproto_2fexamples_2eproto = nullptr; - -const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::SamplesTest1, _has_bits_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::SamplesTest1, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::SamplesTest1, class_name_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::SamplesTest1, case_name_), - 0, - 1, - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, _has_bits_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, timestamp_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, lidar_timestamp_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, seq_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Chatter, content_), - 1, - 2, - 3, - 0, - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Driver, _has_bits_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Driver, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Driver, content_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Driver, msg_id_), - PROTOBUF_FIELD_OFFSET(::apollo::cyber::examples::proto::Driver, timestamp_), - 0, - 1, - 2, -}; -static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - { 0, 7, sizeof(::apollo::cyber::examples::proto::SamplesTest1)}, - { 9, 18, sizeof(::apollo::cyber::examples::proto::Chatter)}, - { 22, 30, sizeof(::apollo::cyber::examples::proto::Driver)}, -}; - -static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { - reinterpret_cast(&::apollo::cyber::examples::proto::_SamplesTest1_default_instance_), - reinterpret_cast(&::apollo::cyber::examples::proto::_Chatter_default_instance_), - reinterpret_cast(&::apollo::cyber::examples::proto::_Driver_default_instance_), -}; - -const char descriptor_table_protodef_cyber_2fexamples_2fproto_2fexamples_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = - "\n#cyber/examples/proto/examples.proto\022\033a" - "pollo.cyber.examples.proto\"5\n\014SamplesTes" - "t1\022\022\n\nclass_name\030\001 \001(\t\022\021\n\tcase_name\030\002 \001(" - "\t\"S\n\007Chatter\022\021\n\ttimestamp\030\001 \001(\004\022\027\n\017lidar" - "_timestamp\030\002 \001(\004\022\013\n\003seq\030\003 \001(\004\022\017\n\007content" - "\030\004 \001(\014\"<\n\006Driver\022\017\n\007content\030\001 \001(\t\022\016\n\006msg" - "_id\030\002 \001(\004\022\021\n\ttimestamp\030\003 \001(\004" - ; -static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_deps[1] = { -}; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_sccs[3] = { - &scc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto.base, - &scc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto.base, - &scc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto.base, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_once; -const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto = { - false, false, descriptor_table_protodef_cyber_2fexamples_2fproto_2fexamples_2eproto, "cyber/examples/proto/examples.proto", 268, - &descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_once, descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_sccs, descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto_deps, 3, 0, - schemas, file_default_instances, TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto::offsets, - file_level_metadata_cyber_2fexamples_2fproto_2fexamples_2eproto, 3, file_level_enum_descriptors_cyber_2fexamples_2fproto_2fexamples_2eproto, file_level_service_descriptors_cyber_2fexamples_2fproto_2fexamples_2eproto, -}; - -// Force running AddDescriptors() at dynamic initialization time. -static bool dynamic_init_dummy_cyber_2fexamples_2fproto_2fexamples_2eproto = (static_cast(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto)), true); -namespace apollo { -namespace cyber { -namespace examples { -namespace proto { - -// =================================================================== - -class SamplesTest1::_Internal { - public: - using HasBits = decltype(std::declval()._has_bits_); - static void set_has_class_name(HasBits* has_bits) { - (*has_bits)[0] |= 1u; - } - static void set_has_case_name(HasBits* has_bits) { - (*has_bits)[0] |= 2u; - } -}; - -SamplesTest1::SamplesTest1(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:apollo.cyber.examples.proto.SamplesTest1) -} -SamplesTest1::SamplesTest1(const SamplesTest1& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - _has_bits_(from._has_bits_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - class_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - if (from._internal_has_class_name()) { - class_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_class_name(), - GetArena()); - } - case_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - if (from._internal_has_case_name()) { - case_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_case_name(), - GetArena()); - } - // @@protoc_insertion_point(copy_constructor:apollo.cyber.examples.proto.SamplesTest1) -} - -void SamplesTest1::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - class_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - case_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); -} - -SamplesTest1::~SamplesTest1() { - // @@protoc_insertion_point(destructor:apollo.cyber.examples.proto.SamplesTest1) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void SamplesTest1::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - class_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - case_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); -} - -void SamplesTest1::ArenaDtor(void* object) { - SamplesTest1* _this = reinterpret_cast< SamplesTest1* >(object); - (void)_this; -} -void SamplesTest1::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void SamplesTest1::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const SamplesTest1& SamplesTest1::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SamplesTest1_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - return *internal_default_instance(); -} - - -void SamplesTest1::Clear() { -// @@protoc_insertion_point(message_clear_start:apollo.cyber.examples.proto.SamplesTest1) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - if (cached_has_bits & 0x00000001u) { - class_name_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x00000002u) { - case_name_.ClearNonDefaultToEmpty(); - } - } - _has_bits_.Clear(); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* SamplesTest1::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - _Internal::HasBits has_bits{}; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // optional string class_name = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { - auto str = _internal_mutable_class_name(); - ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); - #ifndef NDEBUG - ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "apollo.cyber.examples.proto.SamplesTest1.class_name"); - #endif // !NDEBUG - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional string case_name = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { - auto str = _internal_mutable_case_name(); - ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); - #ifndef NDEBUG - ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "apollo.cyber.examples.proto.SamplesTest1.case_name"); - #endif // !NDEBUG - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - _has_bits_.Or(has_bits); - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* SamplesTest1::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:apollo.cyber.examples.proto.SamplesTest1) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string class_name = 1; - if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_class_name().data(), static_cast(this->_internal_class_name().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "apollo.cyber.examples.proto.SamplesTest1.class_name"); - target = stream->WriteStringMaybeAliased( - 1, this->_internal_class_name(), target); - } - - // optional string case_name = 2; - if (cached_has_bits & 0x00000002u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_case_name().data(), static_cast(this->_internal_case_name().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "apollo.cyber.examples.proto.SamplesTest1.case_name"); - target = stream->WriteStringMaybeAliased( - 2, this->_internal_case_name(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:apollo.cyber.examples.proto.SamplesTest1) - return target; -} - -size_t SamplesTest1::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:apollo.cyber.examples.proto.SamplesTest1) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string class_name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_class_name()); - } - - // optional string case_name = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_case_name()); - } - - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void SamplesTest1::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:apollo.cyber.examples.proto.SamplesTest1) - GOOGLE_DCHECK_NE(&from, this); - const SamplesTest1* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:apollo.cyber.examples.proto.SamplesTest1) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:apollo.cyber.examples.proto.SamplesTest1) - MergeFrom(*source); - } -} - -void SamplesTest1::MergeFrom(const SamplesTest1& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:apollo.cyber.examples.proto.SamplesTest1) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - if (cached_has_bits & 0x00000001u) { - _internal_set_class_name(from._internal_class_name()); - } - if (cached_has_bits & 0x00000002u) { - _internal_set_case_name(from._internal_case_name()); - } - } -} - -void SamplesTest1::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:apollo.cyber.examples.proto.SamplesTest1) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void SamplesTest1::CopyFrom(const SamplesTest1& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:apollo.cyber.examples.proto.SamplesTest1) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool SamplesTest1::IsInitialized() const { - return true; -} - -void SamplesTest1::InternalSwap(SamplesTest1* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - swap(_has_bits_[0], other->_has_bits_[0]); - class_name_.Swap(&other->class_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - case_name_.Swap(&other->case_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); -} - -::PROTOBUF_NAMESPACE_ID::Metadata SamplesTest1::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -class Chatter::_Internal { - public: - using HasBits = decltype(std::declval()._has_bits_); - static void set_has_timestamp(HasBits* has_bits) { - (*has_bits)[0] |= 2u; - } - static void set_has_lidar_timestamp(HasBits* has_bits) { - (*has_bits)[0] |= 4u; - } - static void set_has_seq(HasBits* has_bits) { - (*has_bits)[0] |= 8u; - } - static void set_has_content(HasBits* has_bits) { - (*has_bits)[0] |= 1u; - } -}; - -Chatter::Chatter(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:apollo.cyber.examples.proto.Chatter) -} -Chatter::Chatter(const Chatter& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - _has_bits_(from._has_bits_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - if (from._internal_has_content()) { - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(), - GetArena()); - } - ::memcpy(×tamp_, &from.timestamp_, - static_cast(reinterpret_cast(&seq_) - - reinterpret_cast(×tamp_)) + sizeof(seq_)); - // @@protoc_insertion_point(copy_constructor:apollo.cyber.examples.proto.Chatter) -} - -void Chatter::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - ::memset(reinterpret_cast(this) + static_cast( - reinterpret_cast(×tamp_) - reinterpret_cast(this)), - 0, static_cast(reinterpret_cast(&seq_) - - reinterpret_cast(×tamp_)) + sizeof(seq_)); -} - -Chatter::~Chatter() { - // @@protoc_insertion_point(destructor:apollo.cyber.examples.proto.Chatter) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Chatter::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); -} - -void Chatter::ArenaDtor(void* object) { - Chatter* _this = reinterpret_cast< Chatter* >(object); - (void)_this; -} -void Chatter::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Chatter::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Chatter& Chatter::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Chatter_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - return *internal_default_instance(); -} - - -void Chatter::Clear() { -// @@protoc_insertion_point(message_clear_start:apollo.cyber.examples.proto.Chatter) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - content_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x0000000eu) { - ::memset(×tamp_, 0, static_cast( - reinterpret_cast(&seq_) - - reinterpret_cast(×tamp_)) + sizeof(seq_)); - } - _has_bits_.Clear(); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Chatter::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - _Internal::HasBits has_bits{}; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // optional uint64 timestamp = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { - _Internal::set_has_timestamp(&has_bits); - timestamp_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional uint64 lidar_timestamp = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { - _Internal::set_has_lidar_timestamp(&has_bits); - lidar_timestamp_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional uint64 seq = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { - _Internal::set_has_seq(&has_bits); - seq_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional bytes content = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { - auto str = _internal_mutable_content(); - ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - _has_bits_.Or(has_bits); - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Chatter::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:apollo.cyber.examples.proto.Chatter) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional uint64 timestamp = 1; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(1, this->_internal_timestamp(), target); - } - - // optional uint64 lidar_timestamp = 2; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->_internal_lidar_timestamp(), target); - } - - // optional uint64 seq = 3; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(3, this->_internal_seq(), target); - } - - // optional bytes content = 4; - if (cached_has_bits & 0x00000001u) { - target = stream->WriteBytesMaybeAliased( - 4, this->_internal_content(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:apollo.cyber.examples.proto.Chatter) - return target; -} - -size_t Chatter::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:apollo.cyber.examples.proto.Chatter) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional bytes content = 4; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( - this->_internal_content()); - } - - // optional uint64 timestamp = 1; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( - this->_internal_timestamp()); - } - - // optional uint64 lidar_timestamp = 2; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( - this->_internal_lidar_timestamp()); - } - - // optional uint64 seq = 3; - if (cached_has_bits & 0x00000008u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( - this->_internal_seq()); - } - - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Chatter::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:apollo.cyber.examples.proto.Chatter) - GOOGLE_DCHECK_NE(&from, this); - const Chatter* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:apollo.cyber.examples.proto.Chatter) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:apollo.cyber.examples.proto.Chatter) - MergeFrom(*source); - } -} - -void Chatter::MergeFrom(const Chatter& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:apollo.cyber.examples.proto.Chatter) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - if (cached_has_bits & 0x00000001u) { - _internal_set_content(from._internal_content()); - } - if (cached_has_bits & 0x00000002u) { - timestamp_ = from.timestamp_; - } - if (cached_has_bits & 0x00000004u) { - lidar_timestamp_ = from.lidar_timestamp_; - } - if (cached_has_bits & 0x00000008u) { - seq_ = from.seq_; - } - _has_bits_[0] |= cached_has_bits; - } -} - -void Chatter::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:apollo.cyber.examples.proto.Chatter) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Chatter::CopyFrom(const Chatter& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:apollo.cyber.examples.proto.Chatter) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Chatter::IsInitialized() const { - return true; -} - -void Chatter::InternalSwap(Chatter* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - swap(_has_bits_[0], other->_has_bits_[0]); - content_.Swap(&other->content_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Chatter, seq_) - + sizeof(Chatter::seq_) - - PROTOBUF_FIELD_OFFSET(Chatter, timestamp_)>( - reinterpret_cast(×tamp_), - reinterpret_cast(&other->timestamp_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Chatter::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -class Driver::_Internal { - public: - using HasBits = decltype(std::declval()._has_bits_); - static void set_has_content(HasBits* has_bits) { - (*has_bits)[0] |= 1u; - } - static void set_has_msg_id(HasBits* has_bits) { - (*has_bits)[0] |= 2u; - } - static void set_has_timestamp(HasBits* has_bits) { - (*has_bits)[0] |= 4u; - } -}; - -Driver::Driver(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:apollo.cyber.examples.proto.Driver) -} -Driver::Driver(const Driver& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - _has_bits_(from._has_bits_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - if (from._internal_has_content()) { - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(), - GetArena()); - } - ::memcpy(&msg_id_, &from.msg_id_, - static_cast(reinterpret_cast(×tamp_) - - reinterpret_cast(&msg_id_)) + sizeof(timestamp_)); - // @@protoc_insertion_point(copy_constructor:apollo.cyber.examples.proto.Driver) -} - -void Driver::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); - ::memset(reinterpret_cast(this) + static_cast( - reinterpret_cast(&msg_id_) - reinterpret_cast(this)), - 0, static_cast(reinterpret_cast(×tamp_) - - reinterpret_cast(&msg_id_)) + sizeof(timestamp_)); -} - -Driver::~Driver() { - // @@protoc_insertion_point(destructor:apollo.cyber.examples.proto.Driver) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Driver::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - content_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); -} - -void Driver::ArenaDtor(void* object) { - Driver* _this = reinterpret_cast< Driver* >(object); - (void)_this; -} -void Driver::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Driver::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Driver& Driver::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Driver_cyber_2fexamples_2fproto_2fexamples_2eproto.base); - return *internal_default_instance(); -} - - -void Driver::Clear() { -// @@protoc_insertion_point(message_clear_start:apollo.cyber.examples.proto.Driver) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - content_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x00000006u) { - ::memset(&msg_id_, 0, static_cast( - reinterpret_cast(×tamp_) - - reinterpret_cast(&msg_id_)) + sizeof(timestamp_)); - } - _has_bits_.Clear(); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Driver::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - _Internal::HasBits has_bits{}; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // optional string content = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { - auto str = _internal_mutable_content(); - ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); - #ifndef NDEBUG - ::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "apollo.cyber.examples.proto.Driver.content"); - #endif // !NDEBUG - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional uint64 msg_id = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { - _Internal::set_has_msg_id(&has_bits); - msg_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // optional uint64 timestamp = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { - _Internal::set_has_timestamp(&has_bits); - timestamp_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - _has_bits_.Or(has_bits); - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Driver::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:apollo.cyber.examples.proto.Driver) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - // optional string content = 1; - if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_content().data(), static_cast(this->_internal_content().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "apollo.cyber.examples.proto.Driver.content"); - target = stream->WriteStringMaybeAliased( - 1, this->_internal_content(), target); - } - - // optional uint64 msg_id = 2; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->_internal_msg_id(), target); - } - - // optional uint64 timestamp = 3; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(3, this->_internal_timestamp(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:apollo.cyber.examples.proto.Driver) - return target; -} - -size_t Driver::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:apollo.cyber.examples.proto.Driver) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional string content = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_content()); - } - - // optional uint64 msg_id = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( - this->_internal_msg_id()); - } - - // optional uint64 timestamp = 3; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( - this->_internal_timestamp()); - } - - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Driver::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:apollo.cyber.examples.proto.Driver) - GOOGLE_DCHECK_NE(&from, this); - const Driver* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:apollo.cyber.examples.proto.Driver) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:apollo.cyber.examples.proto.Driver) - MergeFrom(*source); - } -} - -void Driver::MergeFrom(const Driver& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:apollo.cyber.examples.proto.Driver) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - if (cached_has_bits & 0x00000001u) { - _internal_set_content(from._internal_content()); - } - if (cached_has_bits & 0x00000002u) { - msg_id_ = from.msg_id_; - } - if (cached_has_bits & 0x00000004u) { - timestamp_ = from.timestamp_; - } - _has_bits_[0] |= cached_has_bits; - } -} - -void Driver::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:apollo.cyber.examples.proto.Driver) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Driver::CopyFrom(const Driver& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:apollo.cyber.examples.proto.Driver) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Driver::IsInitialized() const { - return true; -} - -void Driver::InternalSwap(Driver* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - swap(_has_bits_[0], other->_has_bits_[0]); - content_.Swap(&other->content_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Driver, timestamp_) - + sizeof(Driver::timestamp_) - - PROTOBUF_FIELD_OFFSET(Driver, msg_id_)>( - reinterpret_cast(&msg_id_), - reinterpret_cast(&other->msg_id_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Driver::GetMetadata() const { - return GetMetadataStatic(); -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace proto -} // namespace examples -} // namespace cyber -} // namespace apollo -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::apollo::cyber::examples::proto::SamplesTest1* Arena::CreateMaybeMessage< ::apollo::cyber::examples::proto::SamplesTest1 >(Arena* arena) { - return Arena::CreateMessageInternal< ::apollo::cyber::examples::proto::SamplesTest1 >(arena); -} -template<> PROTOBUF_NOINLINE ::apollo::cyber::examples::proto::Chatter* Arena::CreateMaybeMessage< ::apollo::cyber::examples::proto::Chatter >(Arena* arena) { - return Arena::CreateMessageInternal< ::apollo::cyber::examples::proto::Chatter >(arena); -} -template<> PROTOBUF_NOINLINE ::apollo::cyber::examples::proto::Driver* Arena::CreateMaybeMessage< ::apollo::cyber::examples::proto::Driver >(Arena* arena) { - return Arena::CreateMessageInternal< ::apollo::cyber::examples::proto::Driver >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/cyber/examples/proto/examples.pb.h b/cyber/examples/proto/examples.pb.h deleted file mode 100644 index a1c9c80..0000000 --- a/cyber/examples/proto/examples.pb.h +++ /dev/null @@ -1,1114 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: cyber/examples/proto/examples.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_cyber_2fexamples_2fproto_2fexamples_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_cyber_2fexamples_2fproto_2fexamples_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3014000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3014000 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_cyber_2fexamples_2fproto_2fexamples_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto { - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; - static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; - static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; -}; -extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto; -namespace apollo { -namespace cyber { -namespace examples { -namespace proto { -class Chatter; -class ChatterDefaultTypeInternal; -extern ChatterDefaultTypeInternal _Chatter_default_instance_; -class Driver; -class DriverDefaultTypeInternal; -extern DriverDefaultTypeInternal _Driver_default_instance_; -class SamplesTest1; -class SamplesTest1DefaultTypeInternal; -extern SamplesTest1DefaultTypeInternal _SamplesTest1_default_instance_; -} // namespace proto -} // namespace examples -} // namespace cyber -} // namespace apollo -PROTOBUF_NAMESPACE_OPEN -template<> ::apollo::cyber::examples::proto::Chatter* Arena::CreateMaybeMessage<::apollo::cyber::examples::proto::Chatter>(Arena*); -template<> ::apollo::cyber::examples::proto::Driver* Arena::CreateMaybeMessage<::apollo::cyber::examples::proto::Driver>(Arena*); -template<> ::apollo::cyber::examples::proto::SamplesTest1* Arena::CreateMaybeMessage<::apollo::cyber::examples::proto::SamplesTest1>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace apollo { -namespace cyber { -namespace examples { -namespace proto { - -// =================================================================== - -class SamplesTest1 PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:apollo.cyber.examples.proto.SamplesTest1) */ { - public: - inline SamplesTest1() : SamplesTest1(nullptr) {} - virtual ~SamplesTest1(); - - SamplesTest1(const SamplesTest1& from); - SamplesTest1(SamplesTest1&& from) noexcept - : SamplesTest1() { - *this = ::std::move(from); - } - - inline SamplesTest1& operator=(const SamplesTest1& from) { - CopyFrom(from); - return *this; - } - inline SamplesTest1& operator=(SamplesTest1&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); - } - inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const SamplesTest1& default_instance(); - - static inline const SamplesTest1* internal_default_instance() { - return reinterpret_cast( - &_SamplesTest1_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(SamplesTest1& a, SamplesTest1& b) { - a.Swap(&b); - } - inline void Swap(SamplesTest1* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(SamplesTest1* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline SamplesTest1* New() const final { - return CreateMaybeMessage(nullptr); - } - - SamplesTest1* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const SamplesTest1& from); - void MergeFrom(const SamplesTest1& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(SamplesTest1* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "apollo.cyber.examples.proto.SamplesTest1"; - } - protected: - explicit SamplesTest1(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto); - return ::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kClassNameFieldNumber = 1, - kCaseNameFieldNumber = 2, - }; - // optional string class_name = 1; - bool has_class_name() const; - private: - bool _internal_has_class_name() const; - public: - void clear_class_name(); - const std::string& class_name() const; - void set_class_name(const std::string& value); - void set_class_name(std::string&& value); - void set_class_name(const char* value); - void set_class_name(const char* value, size_t size); - std::string* mutable_class_name(); - std::string* release_class_name(); - void set_allocated_class_name(std::string* class_name); - private: - const std::string& _internal_class_name() const; - void _internal_set_class_name(const std::string& value); - std::string* _internal_mutable_class_name(); - public: - - // optional string case_name = 2; - bool has_case_name() const; - private: - bool _internal_has_case_name() const; - public: - void clear_case_name(); - const std::string& case_name() const; - void set_case_name(const std::string& value); - void set_case_name(std::string&& value); - void set_case_name(const char* value); - void set_case_name(const char* value, size_t size); - std::string* mutable_case_name(); - std::string* release_case_name(); - void set_allocated_case_name(std::string* case_name); - private: - const std::string& _internal_case_name() const; - void _internal_set_case_name(const std::string& value); - std::string* _internal_mutable_case_name(); - public: - - // @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.SamplesTest1) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr class_name_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr case_name_; - friend struct ::TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto; -}; -// ------------------------------------------------------------------- - -class Chatter PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:apollo.cyber.examples.proto.Chatter) */ { - public: - inline Chatter() : Chatter(nullptr) {} - virtual ~Chatter(); - - Chatter(const Chatter& from); - Chatter(Chatter&& from) noexcept - : Chatter() { - *this = ::std::move(from); - } - - inline Chatter& operator=(const Chatter& from) { - CopyFrom(from); - return *this; - } - inline Chatter& operator=(Chatter&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); - } - inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Chatter& default_instance(); - - static inline const Chatter* internal_default_instance() { - return reinterpret_cast( - &_Chatter_default_instance_); - } - static constexpr int kIndexInFileMessages = - 1; - - friend void swap(Chatter& a, Chatter& b) { - a.Swap(&b); - } - inline void Swap(Chatter* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Chatter* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Chatter* New() const final { - return CreateMaybeMessage(nullptr); - } - - Chatter* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Chatter& from); - void MergeFrom(const Chatter& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Chatter* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "apollo.cyber.examples.proto.Chatter"; - } - protected: - explicit Chatter(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto); - return ::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kContentFieldNumber = 4, - kTimestampFieldNumber = 1, - kLidarTimestampFieldNumber = 2, - kSeqFieldNumber = 3, - }; - // optional bytes content = 4; - bool has_content() const; - private: - bool _internal_has_content() const; - public: - void clear_content(); - const std::string& content() const; - void set_content(const std::string& value); - void set_content(std::string&& value); - void set_content(const char* value); - void set_content(const void* value, size_t size); - std::string* mutable_content(); - std::string* release_content(); - void set_allocated_content(std::string* content); - private: - const std::string& _internal_content() const; - void _internal_set_content(const std::string& value); - std::string* _internal_mutable_content(); - public: - - // optional uint64 timestamp = 1; - bool has_timestamp() const; - private: - bool _internal_has_timestamp() const; - public: - void clear_timestamp(); - ::PROTOBUF_NAMESPACE_ID::uint64 timestamp() const; - void set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - private: - ::PROTOBUF_NAMESPACE_ID::uint64 _internal_timestamp() const; - void _internal_set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - public: - - // optional uint64 lidar_timestamp = 2; - bool has_lidar_timestamp() const; - private: - bool _internal_has_lidar_timestamp() const; - public: - void clear_lidar_timestamp(); - ::PROTOBUF_NAMESPACE_ID::uint64 lidar_timestamp() const; - void set_lidar_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - private: - ::PROTOBUF_NAMESPACE_ID::uint64 _internal_lidar_timestamp() const; - void _internal_set_lidar_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - public: - - // optional uint64 seq = 3; - bool has_seq() const; - private: - bool _internal_has_seq() const; - public: - void clear_seq(); - ::PROTOBUF_NAMESPACE_ID::uint64 seq() const; - void set_seq(::PROTOBUF_NAMESPACE_ID::uint64 value); - private: - ::PROTOBUF_NAMESPACE_ID::uint64 _internal_seq() const; - void _internal_set_seq(::PROTOBUF_NAMESPACE_ID::uint64 value); - public: - - // @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.Chatter) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_; - ::PROTOBUF_NAMESPACE_ID::uint64 timestamp_; - ::PROTOBUF_NAMESPACE_ID::uint64 lidar_timestamp_; - ::PROTOBUF_NAMESPACE_ID::uint64 seq_; - friend struct ::TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto; -}; -// ------------------------------------------------------------------- - -class Driver PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:apollo.cyber.examples.proto.Driver) */ { - public: - inline Driver() : Driver(nullptr) {} - virtual ~Driver(); - - Driver(const Driver& from); - Driver(Driver&& from) noexcept - : Driver() { - *this = ::std::move(from); - } - - inline Driver& operator=(const Driver& from) { - CopyFrom(from); - return *this; - } - inline Driver& operator=(Driver&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - inline const ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet& unknown_fields() const { - return _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance); - } - inline ::PROTOBUF_NAMESPACE_ID::UnknownFieldSet* mutable_unknown_fields() { - return _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Driver& default_instance(); - - static inline const Driver* internal_default_instance() { - return reinterpret_cast( - &_Driver_default_instance_); - } - static constexpr int kIndexInFileMessages = - 2; - - friend void swap(Driver& a, Driver& b) { - a.Swap(&b); - } - inline void Swap(Driver* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Driver* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Driver* New() const final { - return CreateMaybeMessage(nullptr); - } - - Driver* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Driver& from); - void MergeFrom(const Driver& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Driver* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "apollo.cyber.examples.proto.Driver"; - } - protected: - explicit Driver(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto); - return ::descriptor_table_cyber_2fexamples_2fproto_2fexamples_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kContentFieldNumber = 1, - kMsgIdFieldNumber = 2, - kTimestampFieldNumber = 3, - }; - // optional string content = 1; - bool has_content() const; - private: - bool _internal_has_content() const; - public: - void clear_content(); - const std::string& content() const; - void set_content(const std::string& value); - void set_content(std::string&& value); - void set_content(const char* value); - void set_content(const char* value, size_t size); - std::string* mutable_content(); - std::string* release_content(); - void set_allocated_content(std::string* content); - private: - const std::string& _internal_content() const; - void _internal_set_content(const std::string& value); - std::string* _internal_mutable_content(); - public: - - // optional uint64 msg_id = 2; - bool has_msg_id() const; - private: - bool _internal_has_msg_id() const; - public: - void clear_msg_id(); - ::PROTOBUF_NAMESPACE_ID::uint64 msg_id() const; - void set_msg_id(::PROTOBUF_NAMESPACE_ID::uint64 value); - private: - ::PROTOBUF_NAMESPACE_ID::uint64 _internal_msg_id() const; - void _internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::uint64 value); - public: - - // optional uint64 timestamp = 3; - bool has_timestamp() const; - private: - bool _internal_has_timestamp() const; - public: - void clear_timestamp(); - ::PROTOBUF_NAMESPACE_ID::uint64 timestamp() const; - void set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - private: - ::PROTOBUF_NAMESPACE_ID::uint64 _internal_timestamp() const; - void _internal_set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value); - public: - - // @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.Driver) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr content_; - ::PROTOBUF_NAMESPACE_ID::uint64 msg_id_; - ::PROTOBUF_NAMESPACE_ID::uint64 timestamp_; - friend struct ::TableStruct_cyber_2fexamples_2fproto_2fexamples_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// SamplesTest1 - -// optional string class_name = 1; -inline bool SamplesTest1::_internal_has_class_name() const { - bool value = (_has_bits_[0] & 0x00000001u) != 0; - return value; -} -inline bool SamplesTest1::has_class_name() const { - return _internal_has_class_name(); -} -inline void SamplesTest1::clear_class_name() { - class_name_.ClearToEmpty(); - _has_bits_[0] &= ~0x00000001u; -} -inline const std::string& SamplesTest1::class_name() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.SamplesTest1.class_name) - return _internal_class_name(); -} -inline void SamplesTest1::set_class_name(const std::string& value) { - _internal_set_class_name(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.SamplesTest1.class_name) -} -inline std::string* SamplesTest1::mutable_class_name() { - // @@protoc_insertion_point(field_mutable:apollo.cyber.examples.proto.SamplesTest1.class_name) - return _internal_mutable_class_name(); -} -inline const std::string& SamplesTest1::_internal_class_name() const { - return class_name_.Get(); -} -inline void SamplesTest1::_internal_set_class_name(const std::string& value) { - _has_bits_[0] |= 0x00000001u; - class_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); -} -inline void SamplesTest1::set_class_name(std::string&& value) { - _has_bits_[0] |= 0x00000001u; - class_name_.Set( - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); - // @@protoc_insertion_point(field_set_rvalue:apollo.cyber.examples.proto.SamplesTest1.class_name) -} -inline void SamplesTest1::set_class_name(const char* value) { - GOOGLE_DCHECK(value != nullptr); - _has_bits_[0] |= 0x00000001u; - class_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); - // @@protoc_insertion_point(field_set_char:apollo.cyber.examples.proto.SamplesTest1.class_name) -} -inline void SamplesTest1::set_class_name(const char* value, - size_t size) { - _has_bits_[0] |= 0x00000001u; - class_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( - reinterpret_cast(value), size), GetArena()); - // @@protoc_insertion_point(field_set_pointer:apollo.cyber.examples.proto.SamplesTest1.class_name) -} -inline std::string* SamplesTest1::_internal_mutable_class_name() { - _has_bits_[0] |= 0x00000001u; - return class_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); -} -inline std::string* SamplesTest1::release_class_name() { - // @@protoc_insertion_point(field_release:apollo.cyber.examples.proto.SamplesTest1.class_name) - if (!_internal_has_class_name()) { - return nullptr; - } - _has_bits_[0] &= ~0x00000001u; - return class_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); -} -inline void SamplesTest1::set_allocated_class_name(std::string* class_name) { - if (class_name != nullptr) { - _has_bits_[0] |= 0x00000001u; - } else { - _has_bits_[0] &= ~0x00000001u; - } - class_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), class_name, - GetArena()); - // @@protoc_insertion_point(field_set_allocated:apollo.cyber.examples.proto.SamplesTest1.class_name) -} - -// optional string case_name = 2; -inline bool SamplesTest1::_internal_has_case_name() const { - bool value = (_has_bits_[0] & 0x00000002u) != 0; - return value; -} -inline bool SamplesTest1::has_case_name() const { - return _internal_has_case_name(); -} -inline void SamplesTest1::clear_case_name() { - case_name_.ClearToEmpty(); - _has_bits_[0] &= ~0x00000002u; -} -inline const std::string& SamplesTest1::case_name() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.SamplesTest1.case_name) - return _internal_case_name(); -} -inline void SamplesTest1::set_case_name(const std::string& value) { - _internal_set_case_name(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.SamplesTest1.case_name) -} -inline std::string* SamplesTest1::mutable_case_name() { - // @@protoc_insertion_point(field_mutable:apollo.cyber.examples.proto.SamplesTest1.case_name) - return _internal_mutable_case_name(); -} -inline const std::string& SamplesTest1::_internal_case_name() const { - return case_name_.Get(); -} -inline void SamplesTest1::_internal_set_case_name(const std::string& value) { - _has_bits_[0] |= 0x00000002u; - case_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); -} -inline void SamplesTest1::set_case_name(std::string&& value) { - _has_bits_[0] |= 0x00000002u; - case_name_.Set( - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); - // @@protoc_insertion_point(field_set_rvalue:apollo.cyber.examples.proto.SamplesTest1.case_name) -} -inline void SamplesTest1::set_case_name(const char* value) { - GOOGLE_DCHECK(value != nullptr); - _has_bits_[0] |= 0x00000002u; - case_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); - // @@protoc_insertion_point(field_set_char:apollo.cyber.examples.proto.SamplesTest1.case_name) -} -inline void SamplesTest1::set_case_name(const char* value, - size_t size) { - _has_bits_[0] |= 0x00000002u; - case_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( - reinterpret_cast(value), size), GetArena()); - // @@protoc_insertion_point(field_set_pointer:apollo.cyber.examples.proto.SamplesTest1.case_name) -} -inline std::string* SamplesTest1::_internal_mutable_case_name() { - _has_bits_[0] |= 0x00000002u; - return case_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); -} -inline std::string* SamplesTest1::release_case_name() { - // @@protoc_insertion_point(field_release:apollo.cyber.examples.proto.SamplesTest1.case_name) - if (!_internal_has_case_name()) { - return nullptr; - } - _has_bits_[0] &= ~0x00000002u; - return case_name_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); -} -inline void SamplesTest1::set_allocated_case_name(std::string* case_name) { - if (case_name != nullptr) { - _has_bits_[0] |= 0x00000002u; - } else { - _has_bits_[0] &= ~0x00000002u; - } - case_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), case_name, - GetArena()); - // @@protoc_insertion_point(field_set_allocated:apollo.cyber.examples.proto.SamplesTest1.case_name) -} - -// ------------------------------------------------------------------- - -// Chatter - -// optional uint64 timestamp = 1; -inline bool Chatter::_internal_has_timestamp() const { - bool value = (_has_bits_[0] & 0x00000002u) != 0; - return value; -} -inline bool Chatter::has_timestamp() const { - return _internal_has_timestamp(); -} -inline void Chatter::clear_timestamp() { - timestamp_ = PROTOBUF_ULONGLONG(0); - _has_bits_[0] &= ~0x00000002u; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::_internal_timestamp() const { - return timestamp_; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::timestamp() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Chatter.timestamp) - return _internal_timestamp(); -} -inline void Chatter::_internal_set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _has_bits_[0] |= 0x00000002u; - timestamp_ = value; -} -inline void Chatter::set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _internal_set_timestamp(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Chatter.timestamp) -} - -// optional uint64 lidar_timestamp = 2; -inline bool Chatter::_internal_has_lidar_timestamp() const { - bool value = (_has_bits_[0] & 0x00000004u) != 0; - return value; -} -inline bool Chatter::has_lidar_timestamp() const { - return _internal_has_lidar_timestamp(); -} -inline void Chatter::clear_lidar_timestamp() { - lidar_timestamp_ = PROTOBUF_ULONGLONG(0); - _has_bits_[0] &= ~0x00000004u; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::_internal_lidar_timestamp() const { - return lidar_timestamp_; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::lidar_timestamp() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Chatter.lidar_timestamp) - return _internal_lidar_timestamp(); -} -inline void Chatter::_internal_set_lidar_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _has_bits_[0] |= 0x00000004u; - lidar_timestamp_ = value; -} -inline void Chatter::set_lidar_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _internal_set_lidar_timestamp(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Chatter.lidar_timestamp) -} - -// optional uint64 seq = 3; -inline bool Chatter::_internal_has_seq() const { - bool value = (_has_bits_[0] & 0x00000008u) != 0; - return value; -} -inline bool Chatter::has_seq() const { - return _internal_has_seq(); -} -inline void Chatter::clear_seq() { - seq_ = PROTOBUF_ULONGLONG(0); - _has_bits_[0] &= ~0x00000008u; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::_internal_seq() const { - return seq_; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Chatter::seq() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Chatter.seq) - return _internal_seq(); -} -inline void Chatter::_internal_set_seq(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _has_bits_[0] |= 0x00000008u; - seq_ = value; -} -inline void Chatter::set_seq(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _internal_set_seq(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Chatter.seq) -} - -// optional bytes content = 4; -inline bool Chatter::_internal_has_content() const { - bool value = (_has_bits_[0] & 0x00000001u) != 0; - return value; -} -inline bool Chatter::has_content() const { - return _internal_has_content(); -} -inline void Chatter::clear_content() { - content_.ClearToEmpty(); - _has_bits_[0] &= ~0x00000001u; -} -inline const std::string& Chatter::content() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Chatter.content) - return _internal_content(); -} -inline void Chatter::set_content(const std::string& value) { - _internal_set_content(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Chatter.content) -} -inline std::string* Chatter::mutable_content() { - // @@protoc_insertion_point(field_mutable:apollo.cyber.examples.proto.Chatter.content) - return _internal_mutable_content(); -} -inline const std::string& Chatter::_internal_content() const { - return content_.Get(); -} -inline void Chatter::_internal_set_content(const std::string& value) { - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); -} -inline void Chatter::set_content(std::string&& value) { - _has_bits_[0] |= 0x00000001u; - content_.Set( - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); - // @@protoc_insertion_point(field_set_rvalue:apollo.cyber.examples.proto.Chatter.content) -} -inline void Chatter::set_content(const char* value) { - GOOGLE_DCHECK(value != nullptr); - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); - // @@protoc_insertion_point(field_set_char:apollo.cyber.examples.proto.Chatter.content) -} -inline void Chatter::set_content(const void* value, - size_t size) { - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( - reinterpret_cast(value), size), GetArena()); - // @@protoc_insertion_point(field_set_pointer:apollo.cyber.examples.proto.Chatter.content) -} -inline std::string* Chatter::_internal_mutable_content() { - _has_bits_[0] |= 0x00000001u; - return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); -} -inline std::string* Chatter::release_content() { - // @@protoc_insertion_point(field_release:apollo.cyber.examples.proto.Chatter.content) - if (!_internal_has_content()) { - return nullptr; - } - _has_bits_[0] &= ~0x00000001u; - return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); -} -inline void Chatter::set_allocated_content(std::string* content) { - if (content != nullptr) { - _has_bits_[0] |= 0x00000001u; - } else { - _has_bits_[0] &= ~0x00000001u; - } - content_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), content, - GetArena()); - // @@protoc_insertion_point(field_set_allocated:apollo.cyber.examples.proto.Chatter.content) -} - -// ------------------------------------------------------------------- - -// Driver - -// optional string content = 1; -inline bool Driver::_internal_has_content() const { - bool value = (_has_bits_[0] & 0x00000001u) != 0; - return value; -} -inline bool Driver::has_content() const { - return _internal_has_content(); -} -inline void Driver::clear_content() { - content_.ClearToEmpty(); - _has_bits_[0] &= ~0x00000001u; -} -inline const std::string& Driver::content() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Driver.content) - return _internal_content(); -} -inline void Driver::set_content(const std::string& value) { - _internal_set_content(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Driver.content) -} -inline std::string* Driver::mutable_content() { - // @@protoc_insertion_point(field_mutable:apollo.cyber.examples.proto.Driver.content) - return _internal_mutable_content(); -} -inline const std::string& Driver::_internal_content() const { - return content_.Get(); -} -inline void Driver::_internal_set_content(const std::string& value) { - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); -} -inline void Driver::set_content(std::string&& value) { - _has_bits_[0] |= 0x00000001u; - content_.Set( - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); - // @@protoc_insertion_point(field_set_rvalue:apollo.cyber.examples.proto.Driver.content) -} -inline void Driver::set_content(const char* value) { - GOOGLE_DCHECK(value != nullptr); - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); - // @@protoc_insertion_point(field_set_char:apollo.cyber.examples.proto.Driver.content) -} -inline void Driver::set_content(const char* value, - size_t size) { - _has_bits_[0] |= 0x00000001u; - content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( - reinterpret_cast(value), size), GetArena()); - // @@protoc_insertion_point(field_set_pointer:apollo.cyber.examples.proto.Driver.content) -} -inline std::string* Driver::_internal_mutable_content() { - _has_bits_[0] |= 0x00000001u; - return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); -} -inline std::string* Driver::release_content() { - // @@protoc_insertion_point(field_release:apollo.cyber.examples.proto.Driver.content) - if (!_internal_has_content()) { - return nullptr; - } - _has_bits_[0] &= ~0x00000001u; - return content_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); -} -inline void Driver::set_allocated_content(std::string* content) { - if (content != nullptr) { - _has_bits_[0] |= 0x00000001u; - } else { - _has_bits_[0] &= ~0x00000001u; - } - content_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), content, - GetArena()); - // @@protoc_insertion_point(field_set_allocated:apollo.cyber.examples.proto.Driver.content) -} - -// optional uint64 msg_id = 2; -inline bool Driver::_internal_has_msg_id() const { - bool value = (_has_bits_[0] & 0x00000002u) != 0; - return value; -} -inline bool Driver::has_msg_id() const { - return _internal_has_msg_id(); -} -inline void Driver::clear_msg_id() { - msg_id_ = PROTOBUF_ULONGLONG(0); - _has_bits_[0] &= ~0x00000002u; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Driver::_internal_msg_id() const { - return msg_id_; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Driver::msg_id() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Driver.msg_id) - return _internal_msg_id(); -} -inline void Driver::_internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _has_bits_[0] |= 0x00000002u; - msg_id_ = value; -} -inline void Driver::set_msg_id(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _internal_set_msg_id(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Driver.msg_id) -} - -// optional uint64 timestamp = 3; -inline bool Driver::_internal_has_timestamp() const { - bool value = (_has_bits_[0] & 0x00000004u) != 0; - return value; -} -inline bool Driver::has_timestamp() const { - return _internal_has_timestamp(); -} -inline void Driver::clear_timestamp() { - timestamp_ = PROTOBUF_ULONGLONG(0); - _has_bits_[0] &= ~0x00000004u; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Driver::_internal_timestamp() const { - return timestamp_; -} -inline ::PROTOBUF_NAMESPACE_ID::uint64 Driver::timestamp() const { - // @@protoc_insertion_point(field_get:apollo.cyber.examples.proto.Driver.timestamp) - return _internal_timestamp(); -} -inline void Driver::_internal_set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _has_bits_[0] |= 0x00000004u; - timestamp_ = value; -} -inline void Driver::set_timestamp(::PROTOBUF_NAMESPACE_ID::uint64 value) { - _internal_set_timestamp(value); - // @@protoc_insertion_point(field_set:apollo.cyber.examples.proto.Driver.timestamp) -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ -// ------------------------------------------------------------------- - -// ------------------------------------------------------------------- - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace proto -} // namespace examples -} // namespace cyber -} // namespace apollo - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_cyber_2fexamples_2fproto_2fexamples_2eproto diff --git a/cyber/examples/proto/examples_pb2.py b/cyber/examples/proto/examples_pb2.py deleted file mode 100644 index d1f0624..0000000 --- a/cyber/examples/proto/examples_pb2.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: cyber/examples/proto/examples.proto -"""Generated protocol buffer code.""" -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='cyber/examples/proto/examples.proto', - package='apollo.cyber.examples.proto', - syntax='proto2', - serialized_options=None, - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n#cyber/examples/proto/examples.proto\x12\x1b\x61pollo.cyber.examples.proto\"5\n\x0cSamplesTest1\x12\x12\n\nclass_name\x18\x01 \x01(\t\x12\x11\n\tcase_name\x18\x02 \x01(\t\"S\n\x07\x43hatter\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x17\n\x0flidar_timestamp\x18\x02 \x01(\x04\x12\x0b\n\x03seq\x18\x03 \x01(\x04\x12\x0f\n\x07\x63ontent\x18\x04 \x01(\x0c\"<\n\x06\x44river\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x0e\n\x06msg_id\x18\x02 \x01(\x04\x12\x11\n\ttimestamp\x18\x03 \x01(\x04' -) - - - - -_SAMPLESTEST1 = _descriptor.Descriptor( - name='SamplesTest1', - full_name='apollo.cyber.examples.proto.SamplesTest1', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='class_name', full_name='apollo.cyber.examples.proto.SamplesTest1.class_name', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='case_name', full_name='apollo.cyber.examples.proto.SamplesTest1.case_name', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=68, - serialized_end=121, -) - - -_CHATTER = _descriptor.Descriptor( - name='Chatter', - full_name='apollo.cyber.examples.proto.Chatter', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='timestamp', full_name='apollo.cyber.examples.proto.Chatter.timestamp', index=0, - number=1, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='lidar_timestamp', full_name='apollo.cyber.examples.proto.Chatter.lidar_timestamp', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='seq', full_name='apollo.cyber.examples.proto.Chatter.seq', index=2, - number=3, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='content', full_name='apollo.cyber.examples.proto.Chatter.content', index=3, - number=4, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=123, - serialized_end=206, -) - - -_DRIVER = _descriptor.Descriptor( - name='Driver', - full_name='apollo.cyber.examples.proto.Driver', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='content', full_name='apollo.cyber.examples.proto.Driver.content', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='msg_id', full_name='apollo.cyber.examples.proto.Driver.msg_id', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - _descriptor.FieldDescriptor( - name='timestamp', full_name='apollo.cyber.examples.proto.Driver.timestamp', index=2, - number=3, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=208, - serialized_end=268, -) - -DESCRIPTOR.message_types_by_name['SamplesTest1'] = _SAMPLESTEST1 -DESCRIPTOR.message_types_by_name['Chatter'] = _CHATTER -DESCRIPTOR.message_types_by_name['Driver'] = _DRIVER -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -SamplesTest1 = _reflection.GeneratedProtocolMessageType('SamplesTest1', (_message.Message,), { - 'DESCRIPTOR' : _SAMPLESTEST1, - '__module__' : 'cyber.examples.proto.examples_pb2' - # @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.SamplesTest1) - }) -_sym_db.RegisterMessage(SamplesTest1) - -Chatter = _reflection.GeneratedProtocolMessageType('Chatter', (_message.Message,), { - 'DESCRIPTOR' : _CHATTER, - '__module__' : 'cyber.examples.proto.examples_pb2' - # @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.Chatter) - }) -_sym_db.RegisterMessage(Chatter) - -Driver = _reflection.GeneratedProtocolMessageType('Driver', (_message.Message,), { - 'DESCRIPTOR' : _DRIVER, - '__module__' : 'cyber.examples.proto.examples_pb2' - # @@protoc_insertion_point(class_scope:apollo.cyber.examples.proto.Driver) - }) -_sym_db.RegisterMessage(Driver) - - -# @@protoc_insertion_point(module_scope) diff --git a/cyber/proto/.gitignore b/cyber/proto/.gitignore deleted file mode 100644 index 9ee9fc2..0000000 --- a/cyber/proto/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.pb.cc -*.pb.h -*_pb2.py diff --git a/modules/common_msgs/.gitignore b/modules/common_msgs/.gitignore deleted file mode 100644 index 9ee9fc2..0000000 --- a/modules/common_msgs/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.pb.cc -*.pb.h -*_pb2.py From be0bece887ba950643055f5332fe8e01ee2d2368 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Mon, 9 Dec 2024 16:39:49 +0800 Subject: [PATCH 04/14] feat(cyber): update cyber for v10 --- cyber/BUILD | 2 +- cyber/base/BUILD | 5 +- cyber/base/arena_queue.h | 262 ++++++ cyber/base/macros.h | 2 + cyber/base/pthread_rw_lock.h | 73 ++ cyber/benchmark/BUILD | 51 ++ cyber/benchmark/benchmark_msg.proto | 8 + cyber/benchmark/cyber_benchmark.py | 337 ++++++++ cyber/benchmark/cyber_benchmark_reader.cc | 179 ++++ cyber/benchmark/cyber_benchmark_writer.cc | 362 ++++++++ cyber/common/BUILD | 13 +- cyber/common/file.cc | 34 + cyber/common/file.h | 10 + cyber/common/file_test.cc | 6 +- cyber/common/global_data.cc | 45 + cyber/common/global_data.h | 8 + cyber/component/component.h | 145 +++- cyber/component/timer_component.cc | 15 +- cyber/conf/cyber.pb.conf | 23 + cyber/context/BUILD | 1 + cyber/cyberfile.xml | 13 +- .../common_component_example/common.launch | 2 + cyber/examples/service.cc | 2 +- cyber/init.cc | 36 +- cyber/init.h | 5 +- cyber/mainboard/BUILD | 7 +- cyber/mainboard/mainboard.cc | 68 +- cyber/mainboard/module_argument.cc | 61 +- cyber/mainboard/module_argument.h | 10 + cyber/message/BUILD | 11 +- cyber/message/arena_manager_base.h | 62 ++ cyber/message/arena_message_wrapper.h | 145 ++++ cyber/message/message_traits.h | 46 + cyber/message/protobuf_traits.h | 23 + cyber/message/raw_message.h | 9 + cyber/message/raw_message_traits.h | 11 + cyber/node/BUILD | 2 + cyber/node/node.cc | 5 - cyber/node/node.h | 4 +- cyber/node/reader.h | 24 + cyber/node/reader_base.h | 2 +- cyber/node/writer.h | 23 + cyber/node/writer_base.h | 7 + cyber/parameter/BUILD | 2 +- cyber/parameter/parameter_client.h | 2 +- cyber/proto/BUILD | 11 +- cyber/proto/simple.proto | 12 + cyber/proto/transport_conf.proto | 15 + cyber/python/cyber_py3/cyber.py | 2 +- cyber/python/cyber_py3/cyber_time.py | 2 +- cyber/python/cyber_py3/cyber_timer.py | 2 +- cyber/python/cyber_py3/parameter.py | 2 +- cyber/python/cyber_py3/record.py | 2 +- cyber/python/cyber_py3/test/BUILD | 29 +- cyber/python/internal/BUILD | 2 +- cyber/python/internal/py_cyber.cc | 62 +- cyber/python/internal/py_cyber.h | 1 + cyber/record/file/record_file_writer.cc | 4 +- cyber/record/file/record_file_writer.h | 1 + cyber/record/header_builder.h | 2 +- cyber/ros_bridge/BUILD | 59 ++ cyber/ros_bridge/common/bridge_argument.cc | 112 +++ cyber/ros_bridge/common/bridge_argument.h | 57 ++ cyber/ros_bridge/common/macros.h | 26 + cyber/ros_bridge/common/ros_bridge_gflags.cc | 32 + cyber/ros_bridge/common/ros_bridge_gflags.h | 33 + cyber/ros_bridge/common/utils.h | 34 + cyber/ros_bridge/conf/ros_bridge_conf.pb.txt | 19 + .../converter_base/convert_apollo_double.h | 384 +++++++++ .../converter_base/convert_apollo_quadruple.h | 503 +++++++++++ .../converter_base/convert_apollo_single.h | 325 ++++++++ .../converter_base/convert_apollo_triple.h | 450 ++++++++++ .../converter_base/convert_ros_base.h | 63 ++ .../converter_base/convert_ros_double.h | 452 ++++++++++ .../converter_base/convert_ros_quadruple.h | 551 ++++++++++++ .../converter_base/convert_ros_single.h | 364 ++++++++ .../converter_base/convert_ros_triple.h | 509 +++++++++++ .../converter_base/converter_base.h | 77 ++ .../converter_base/converter_interface.h | 29 + .../converter_base/message_converter.h | 149 ++++ cyber/ros_bridge/converters/BUILD | 3 + .../converters/common_plugins/BUILD | 3 + .../common_plugins/gnss_msg_converter/BUILD | 104 +++ .../conf/heading_msg_fusion.pb.txt | 4 + .../conf/imu_msg_converter.pb.txt | 4 + .../conf/nav_msg_converter.pb.txt | 5 + .../conf/odometry_msg_converter.pb.txt | 3 + .../conf/odometry_parser.pb.txt | 5 + .../gnss_msg_converter/heading_msg_fusion.cc | 97 +++ .../gnss_msg_converter/heading_msg_fusion.h | 86 ++ .../heading_msg_plugins.xml | 3 + .../gnss_msg_converter/imu_msg_converter.cc | 85 ++ .../gnss_msg_converter/imu_msg_converter.h | 77 ++ .../gnss_msg_converter/imu_plugins.xml | 3 + .../gnss_msg_converter/nav_msg_converter.cc | 78 ++ .../gnss_msg_converter/nav_msg_converter.h | 77 ++ .../gnss_msg_converter/nav_plugins.xml | 3 + .../odometry_msg_converter.cc | 66 ++ .../odometry_msg_converter.h | 74 ++ .../odometry_msg_plugins.xml | 3 + .../gnss_msg_converter/odometry_parser.cc | 140 ++++ .../gnss_msg_converter/odometry_parser.h | 152 ++++ .../gnss_msg_converter/odometry_plugins.xml | 3 + .../gnss_msg_converter/quaternion_math.h | 50 ++ .../localization_msg_converter/BUILD | 33 + .../conf/localization_estimate.pb.txt | 4 + .../localization_estimate.cc | 86 ++ .../localization_estimate.h | 76 ++ .../localization_estimate.xml | 3 + .../pointcloud_msg_converter/BUILD | 32 + .../conf/default.pb.txt | 3 + .../lidar_pointcloud.cc | 230 +++++ .../lidar_pointcloud.h | 83 ++ .../pointcloud_msg_converter/plugins.xml | 3 + .../examples/apollo_ros_converter/BUILD | 34 + .../apollo_ros_converter.cc | 34 + .../apollo_ros_converter.h | 69 ++ .../apollo_ros_converter/conf/default.pb.txt | 2 + .../examples/apollo_ros_converter/plugins.xml | 3 + .../examples/ros_apollo_converter/BUILD | 34 + .../ros_apollo_converter/conf/default.pb.txt | 2 + .../examples/ros_apollo_converter/plugins.xml | 3 + .../ros_apollo_converter.cc | 33 + .../ros_apollo_converter.h | 66 ++ cyber/ros_bridge/proto/BUILD | 16 + cyber/ros_bridge/proto/converter_conf.proto | 15 + cyber/ros_bridge/proto/ros_bridge_conf.proto | 13 + cyber/ros_bridge/ros_bridge.cc | 99 +++ cyber/service_discovery/BUILD | 6 +- .../communication/participant_listener.cc | 17 +- .../communication/participant_listener.h | 16 +- .../communication/subscriber_listener.cc | 40 +- .../communication/subscriber_listener.h | 29 +- .../specific_manager/channel_manager.cc | 5 +- .../specific_manager/channel_manager.h | 1 + .../specific_manager/channel_manager_test.cc | 4 +- .../specific_manager/manager.cc | 57 +- .../specific_manager/manager.h | 39 +- .../specific_manager/node_manager.cc | 1 - .../specific_manager/service_manager.cc | 2 - cyber/service_discovery/topology_manager.cc | 60 +- cyber/service_discovery/topology_manager.h | 12 +- cyber/setup.bash | 9 +- cyber/statistics/BUILD | 19 + cyber/statistics/statistics.cc | 130 +++ cyber/statistics/statistics.h | 314 +++++++ cyber/tools/cyber_launch/cyber_launch.py | 122 ++- .../cyber_monitor/general_channel_message.cc | 4 +- .../cyber_monitor/general_channel_message.h | 5 + cyber/tools/cyber_monitor/main.cc | 12 +- cyber/tools/cyber_performance/BUILD | 13 + .../cyber_performance.launch | 11 + .../cyber_performance/cyber_performance.py | 789 ++++++++++++++++++ cyber/tools/cyber_recorder/BUILD | 8 +- cyber/tools/cyber_recorder/main.cc | 102 ++- cyber/transport/BUILD | 129 ++- cyber/transport/common/common_type.h | 36 + cyber/transport/dispatcher/dispatcher.h | 3 +- cyber/transport/dispatcher/intra_dispatcher.h | 12 +- cyber/transport/dispatcher/rtps_dispatcher.cc | 37 +- cyber/transport/dispatcher/rtps_dispatcher.h | 51 +- cyber/transport/dispatcher/shm_dispatcher.cc | 114 ++- cyber/transport/dispatcher/shm_dispatcher.h | 309 ++++++- .../dispatcher/shm_dispatcher_test.cc | 1 - .../dispatcher/subscriber_listener.cc | 76 ++ .../subscriber_listener.h} | 45 +- cyber/transport/message/listener_handler.h | 1 + cyber/transport/message/message_info.cc | 32 +- cyber/transport/message/message_info.h | 4 + cyber/transport/qos/qos_filler.cc | 339 ++++++++ cyber/transport/qos/qos_filler.h | 62 ++ cyber/transport/receiver/shm_receiver.h | 22 + cyber/transport/rtps/attributes_filler.cc | 12 +- cyber/transport/rtps/attributes_filler.h | 2 + cyber/transport/rtps/participant.cc | 221 +++-- cyber/transport/rtps/participant.h | 68 +- cyber/transport/rtps/publisher.cc | 136 +++ cyber/transport/rtps/publisher.h | 73 ++ cyber/transport/rtps/rtps_test.cc | 183 ++-- cyber/transport/rtps/sub_listener.cc | 77 -- cyber/transport/rtps/subscriber.cc | 113 +++ cyber/transport/rtps/subscriber.h | 75 ++ cyber/transport/rtps/underlay_message.cc | 41 +- cyber/transport/rtps/underlay_message.h | 44 +- cyber/transport/rtps/underlay_message_type.cc | 101 ++- cyber/transport/rtps/underlay_message_type.h | 26 +- .../transport/shm/arena_address_allocator.cc | 458 ++++++++++ cyber/transport/shm/arena_address_allocator.h | 121 +++ cyber/transport/shm/posix_segment.cc | 95 ++- cyber/transport/shm/protobuf_arena_manager.cc | 564 +++++++++++++ cyber/transport/shm/protobuf_arena_manager.h | 319 +++++++ cyber/transport/shm/readable_info.cc | 31 +- cyber/transport/shm/readable_info.h | 14 +- cyber/transport/shm/segment.cc | 155 +++- cyber/transport/shm/segment.h | 23 + cyber/transport/shm/shm_conf.cc | 8 +- cyber/transport/shm/shm_conf.h | 4 + cyber/transport/shm/state.h | 6 + cyber/transport/shm/xsi_segment.cc | 93 ++- .../transmitter/hybrid_transmitter.h | 26 +- .../transport/transmitter/intra_transmitter.h | 22 + .../transport/transmitter/rtps_transmitter.h | 63 +- cyber/transport/transmitter/shm_transmitter.h | 228 ++++- cyber/transport/transmitter/transmitter.h | 20 +- cyber/transport/transport.cc | 9 +- 205 files changed, 14284 insertions(+), 891 deletions(-) create mode 100644 cyber/base/arena_queue.h create mode 100644 cyber/base/pthread_rw_lock.h create mode 100644 cyber/benchmark/BUILD create mode 100644 cyber/benchmark/benchmark_msg.proto create mode 100644 cyber/benchmark/cyber_benchmark.py create mode 100644 cyber/benchmark/cyber_benchmark_reader.cc create mode 100644 cyber/benchmark/cyber_benchmark_writer.cc create mode 100644 cyber/message/arena_manager_base.h create mode 100644 cyber/message/arena_message_wrapper.h create mode 100644 cyber/proto/simple.proto create mode 100644 cyber/ros_bridge/BUILD create mode 100644 cyber/ros_bridge/common/bridge_argument.cc create mode 100644 cyber/ros_bridge/common/bridge_argument.h create mode 100644 cyber/ros_bridge/common/macros.h create mode 100644 cyber/ros_bridge/common/ros_bridge_gflags.cc create mode 100644 cyber/ros_bridge/common/ros_bridge_gflags.h create mode 100644 cyber/ros_bridge/common/utils.h create mode 100644 cyber/ros_bridge/conf/ros_bridge_conf.pb.txt create mode 100644 cyber/ros_bridge/converter_base/convert_apollo_double.h create mode 100644 cyber/ros_bridge/converter_base/convert_apollo_quadruple.h create mode 100644 cyber/ros_bridge/converter_base/convert_apollo_single.h create mode 100644 cyber/ros_bridge/converter_base/convert_apollo_triple.h create mode 100644 cyber/ros_bridge/converter_base/convert_ros_base.h create mode 100644 cyber/ros_bridge/converter_base/convert_ros_double.h create mode 100644 cyber/ros_bridge/converter_base/convert_ros_quadruple.h create mode 100644 cyber/ros_bridge/converter_base/convert_ros_single.h create mode 100644 cyber/ros_bridge/converter_base/convert_ros_triple.h create mode 100644 cyber/ros_bridge/converter_base/converter_base.h create mode 100644 cyber/ros_bridge/converter_base/converter_interface.h create mode 100644 cyber/ros_bridge/converter_base/message_converter.h create mode 100644 cyber/ros_bridge/converters/BUILD create mode 100644 cyber/ros_bridge/converters/common_plugins/BUILD create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h create mode 100755 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml create mode 100644 cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h create mode 100755 cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD create mode 100755 cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h create mode 100755 cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml create mode 100755 cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD create mode 100755 cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt create mode 100755 cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc create mode 100755 cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h create mode 100755 cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml create mode 100644 cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD create mode 100644 cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc create mode 100644 cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h create mode 100644 cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt create mode 100644 cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml create mode 100644 cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD create mode 100644 cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt create mode 100644 cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml create mode 100644 cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc create mode 100644 cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h create mode 100644 cyber/ros_bridge/proto/BUILD create mode 100644 cyber/ros_bridge/proto/converter_conf.proto create mode 100644 cyber/ros_bridge/proto/ros_bridge_conf.proto create mode 100644 cyber/ros_bridge/ros_bridge.cc create mode 100644 cyber/statistics/BUILD create mode 100644 cyber/statistics/statistics.cc create mode 100644 cyber/statistics/statistics.h create mode 100644 cyber/tools/cyber_performance/BUILD create mode 100755 cyber/tools/cyber_performance/cyber_performance.launch create mode 100644 cyber/tools/cyber_performance/cyber_performance.py create mode 100644 cyber/transport/common/common_type.h create mode 100644 cyber/transport/dispatcher/subscriber_listener.cc rename cyber/transport/{rtps/sub_listener.h => dispatcher/subscriber_listener.h} (54%) create mode 100644 cyber/transport/qos/qos_filler.cc create mode 100644 cyber/transport/qos/qos_filler.h create mode 100644 cyber/transport/rtps/publisher.cc create mode 100644 cyber/transport/rtps/publisher.h delete mode 100644 cyber/transport/rtps/sub_listener.cc create mode 100644 cyber/transport/rtps/subscriber.cc create mode 100644 cyber/transport/rtps/subscriber.h create mode 100644 cyber/transport/shm/arena_address_allocator.cc create mode 100644 cyber/transport/shm/arena_address_allocator.h create mode 100644 cyber/transport/shm/protobuf_arena_manager.cc create mode 100644 cyber/transport/shm/protobuf_arena_manager.h diff --git a/cyber/BUILD b/cyber/BUILD index 7f52f29..85ee119 100755 --- a/cyber/BUILD +++ b/cyber/BUILD @@ -62,7 +62,7 @@ apollo_cc_library( "//cyber/transport:cyber_transport", "@com_github_google_glog//:glog", "@com_google_protobuf//:protobuf", - "@fastrtps", + "@fastdds", ], ) diff --git a/cyber/base/BUILD b/cyber/base/BUILD index 5d59d8d..d7d163f 100644 --- a/cyber/base/BUILD +++ b/cyber/base/BUILD @@ -1,11 +1,12 @@ load("//tools:cpplint.bzl", "cpplint") -load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_library", "apollo_cc_test") +load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") package(default_visibility = ["//visibility:public"]) apollo_cc_library( name = "cyber_base", hdrs = [ + "arena_queue.h", "atomic_hash_map.h", "atomic_rw_lock.h", "bounded_queue.h", @@ -13,6 +14,7 @@ apollo_cc_library( "for_each.h", "macros.h", "object_pool.h", + "pthread_rw_lock.h", "reentrant_rw_lock.h", "rw_lock_guard.h", "signal.h", @@ -97,4 +99,5 @@ apollo_cc_test( ) apollo_package() + cpplint() diff --git a/cyber/base/arena_queue.h b/cyber/base/arena_queue.h new file mode 100644 index 0000000..5abdb50 --- /dev/null +++ b/cyber/base/arena_queue.h @@ -0,0 +1,262 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_BASE_ARENA_QUEUE_H_ +#define CYBER_BASE_ARENA_QUEUE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cyber/base/macros.h" +#include "cyber/base/wait_strategy.h" + +namespace apollo { +namespace cyber { +namespace base { + +template +class ArenaQueue { + public: + using value_type = T; + using size_type = uint64_t; + + public: + ArenaQueue() {} + ArenaQueue& operator=(const ArenaQueue& other) = delete; + ArenaQueue(const ArenaQueue& other) = delete; + ~ArenaQueue(); + bool Init(uint64_t size); + bool Init(uint64_t size, google::protobuf::Arena* arena); + + T* AddBack(); + T* PopFront(); + T* GetBack(); + T* GetFront(); + + uint64_t Size(); + bool Empty(); + uint64_t Head() { return head_.load(); } + uint64_t Tail() { return tail_.load(); } + uint64_t Commit() { return commit_.load(); } + bool NextIndex(uint64_t& index) { + if (Empty()) { + return false; + } + if (arena_) { + if (GetIndex(index) < Tail() - 1) { + index = GetIndex(index + 1); + return true; + } + return false; + } else { + if (index < Size() - 1) { + index = index + 1; + return true; + } + return false; + } + } + bool GetHeadIndex(uint64_t& index) { + if (Empty()) { + return false; + } + if (arena_) { + index = GetIndex(head_ + 1); + return true; + } else { + index = 0; + return true; + } + } + bool GetTailIndex(uint64_t& index) { + if (Empty()) { + return false; + } + if (arena_) { + index = GetIndex(tail_ - 1); + return true; + } else { + index = Size() - 1; + return true; + } + } + bool GetEleByIndex(uint64_t i, T*& ptr) { + if (Empty()) { + return false; + } + if (arena_) { + ptr = pool_[GetIndex(i)]; + return true; + } else { + if (i > Size() - 1) { + return false; + } + ptr = &normal_queue[i]; + return true; + } + } + bool IsArenaEnable() { return arena_; } + + private: + uint64_t GetIndex(uint64_t num); + + alignas(CACHELINE_SIZE) std::atomic head_ = {0}; + alignas(CACHELINE_SIZE) std::atomic tail_ = {1}; + alignas(CACHELINE_SIZE) std::atomic commit_ = {1}; + + uint64_t pool_size_ = 0; + std::vector pool_; + bool arena_; + std::deque normal_queue; +}; + +template +ArenaQueue::~ArenaQueue() {} + +template +inline bool ArenaQueue::Init(uint64_t size) { + arena_ = false; + return true; +} + +template +inline bool ArenaQueue::Init(uint64_t size, google::protobuf::Arena* arena) { + pool_size_ = size + 2; + if (pool_.size() == pool_size_) { + return true; + } + pool_.clear(); + for (uint64_t i = 0; i < pool_size_; ++i) { + pool_.push_back(google::protobuf::Arena::CreateMessage(arena)); + } + arena_ = true; + return true; +} + +template +T* ArenaQueue::GetBack() { + if (Empty()) { + return nullptr; + } + if (arena_) { + return pool_[GetIndex(tail_ - 1)]; + } else { + return &normal_queue.back(); + } +} + +template +T* ArenaQueue::GetFront() { + if (Empty()) { + return nullptr; + } + if (arena_) { + return pool_[GetIndex(head_ + 1)]; + } else { + return &normal_queue.front(); + } +} + +template +T* ArenaQueue::AddBack() { + if (arena_) { + uint64_t new_tail = 0; + uint64_t old_commit = 0; + uint64_t old_tail = tail_.load(std::memory_order_acquire); + do { + new_tail = old_tail + 1; + if (GetIndex(new_tail) == + GetIndex(head_.load(std::memory_order_acquire))) { + return nullptr; + } + } while (!tail_.compare_exchange_weak(old_tail, new_tail, + std::memory_order_acq_rel, + std::memory_order_relaxed)); + do { + old_commit = old_tail; + } while (cyber_unlikely(!commit_.compare_exchange_weak( + old_commit, new_tail, std::memory_order_acq_rel, + std::memory_order_relaxed))); + return pool_[GetIndex(old_tail)]; + } else { + T instance; + normal_queue.push_back(instance); + return &normal_queue.back(); + } +} + +template +T* ArenaQueue::PopFront() { + if (Empty()) { + return nullptr; + } + if (arena_) { + uint64_t new_head = 0; + uint64_t old_head = head_.load(std::memory_order_acquire); + do { + new_head = old_head + 1; + if (new_head == commit_.load(std::memory_order_acquire)) { + return nullptr; + } + } while (!head_.compare_exchange_weak(old_head, new_head, + std::memory_order_acq_rel, + std::memory_order_relaxed)); + return pool_[GetIndex(new_head)]; + } else { + normal_queue.pop_front(); + return nullptr; + } +} + +template +inline uint64_t ArenaQueue::Size() { + if (arena_) { + return tail_ - head_ - 1; + } else { + return normal_queue.size(); + } +} + +template +inline bool ArenaQueue::Empty() { + if (arena_) { + return Size() == 0; + } else { + return normal_queue.empty(); + } +} + +template +inline uint64_t ArenaQueue::GetIndex(uint64_t num) { + return num - (num / pool_size_) * pool_size_; // faster than % +} + +} // namespace base +} // namespace cyber +} // namespace apollo + +#endif // CYBER_BASE_ARENA_QUEUE_H_ diff --git a/cyber/base/macros.h b/cyber/base/macros.h index 7a58b94..96442a3 100644 --- a/cyber/base/macros.h +++ b/cyber/base/macros.h @@ -20,6 +20,8 @@ #include #include +#define eprosima eprosima_wrap + #if __GNUC__ >= 3 #define cyber_likely(x) (__builtin_expect((x), 1)) #define cyber_unlikely(x) (__builtin_expect((x), 0)) diff --git a/cyber/base/pthread_rw_lock.h b/cyber/base/pthread_rw_lock.h new file mode 100644 index 0000000..bb2c6b0 --- /dev/null +++ b/cyber/base/pthread_rw_lock.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_BASE_PTHREAD_RW_LOCK_H_ +#define CYBER_BASE_PTHREAD_RW_LOCK_H_ + +#include + +#include "cyber/base/rw_lock_guard.h" + +namespace apollo { +namespace cyber { +namespace base { + +class PthreadRWLock { + friend class ReadLockGuard; + friend class WriteLockGuard; + + public: + explicit PthreadRWLock(bool writer) { + pthread_rwlockattr_init(&rwlock_attr_); + if (writer) { + pthread_rwlockattr_setkind_np( + &rwlock_attr_, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + } + pthread_rwlockattr_setpshared(&rwlock_attr_, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(&rwlock_, &rwlock_attr_); + } + PthreadRWLock() : PthreadRWLock(true) {} + + ~PthreadRWLock() { + pthread_rwlock_destroy(&rwlock_); + pthread_rwlockattr_destroy(&rwlock_attr_); + } + + void ReadLock(); + void ReadUnlock(); + + void WriteLock(); + void WriteUnlock(); + + private: + PthreadRWLock(const PthreadRWLock& other) = delete; + PthreadRWLock& operator=(const PthreadRWLock& other) = delete; + pthread_rwlock_t rwlock_; + pthread_rwlockattr_t rwlock_attr_; +}; + +inline void PthreadRWLock::ReadLock() { pthread_rwlock_rdlock(&rwlock_); } + +inline void PthreadRWLock::ReadUnlock() { pthread_rwlock_unlock(&rwlock_); } + +inline void PthreadRWLock::WriteLock() { pthread_rwlock_wrlock(&rwlock_); } + +inline void PthreadRWLock::WriteUnlock() { pthread_rwlock_unlock(&rwlock_); } + +} // namespace base +} // namespace cyber +} // namespace apollo + +#endif diff --git a/cyber/benchmark/BUILD b/cyber/benchmark/BUILD new file mode 100644 index 0000000..5090dc6 --- /dev/null +++ b/cyber/benchmark/BUILD @@ -0,0 +1,51 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools/proto:proto.bzl", "proto_library", "apollo_py_binary") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_binary") + +package(default_visibility = ["//visibility:public"]) + +apollo_py_binary( + name = "cyber_benchmark", + srcs = ["cyber_benchmark.py"], +) + +apollo_cc_binary( + name = "cyber_benchmark_reader", + srcs = [ + "cyber_benchmark_reader.cc", + ], + linkopts = [ + "-pthread", + "-lprofiler", + "-ltcmalloc", + ], + deps = [ + "//cyber", + ":benchmark_msg_proto", + ], +) + +apollo_cc_binary( + name = "cyber_benchmark_writer", + srcs = [ + "cyber_benchmark_writer.cc", + ], + linkopts = [ + "-pthread", + "-lprofiler", + "-ltcmalloc", + ], + deps = [ + "//cyber", + "//cyber/time:cyber_time", + ":benchmark_msg_proto", + ], +) + +proto_library( + name = "benchmark_msg_proto", + srcs = ["benchmark_msg.proto"], +) + +apollo_package() +cpplint() \ No newline at end of file diff --git a/cyber/benchmark/benchmark_msg.proto b/cyber/benchmark/benchmark_msg.proto new file mode 100644 index 0000000..6757684 --- /dev/null +++ b/cyber/benchmark/benchmark_msg.proto @@ -0,0 +1,8 @@ +syntax = "proto2"; + +package apollo.cyber.benchmark; + +message BenchmarkMsg { + repeated uint32 data = 1; + optional bytes data_bytes = 2; +} \ No newline at end of file diff --git a/cyber/benchmark/cyber_benchmark.py b/cyber/benchmark/cyber_benchmark.py new file mode 100644 index 0000000..7f676d3 --- /dev/null +++ b/cyber/benchmark/cyber_benchmark.py @@ -0,0 +1,337 @@ +""" +cyber benchmark +""" +#!/usr/bin/env python3 +# **************************************************************************** +# Copyright 2024 The Apollo Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# **************************************************************************** + +import os +import re +import sys +import json +import time +import numpy as np +import argparse +import atexit +import signal +import logging +import itertools +import subprocess +import threading +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler + + +""" +colorful logging +""" +BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = list(range(8)) +RESET_SEQ = "\033[0m" +COLOR_SEQ = "\033[1;%dm" +BOLD_SEQ = "\033[1m" + +COLORS = { + 'INFO': GREEN, + 'WARNING': YELLOW, + 'DEBUG': BLUE, + 'ERROR': RED, + 'CRITICAL': YELLOW +} + +logger = logging.Logger(__name__) +reader_nums = -1 + +class Benchmark(FileSystemEventHandler): + """ + benchmark class definition + """ + def __init__(self, params): + self.params = params + self.directory_to_watch = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "dumps") + self.preformance_to_write = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "data") + self.performances = {} + self.performance_key = None + self.debounce_period = 1 + self.last_sample_time = 0 + self.base_key = { + "cyber_benchmark_cpu_usage_latency": "cpu_usage", + "cyber_benchmark_mem_resident_usage_latency": "mem_usage", + } + self.latency_key = {} + self.data_fd = open( + "transport_performance_{}".format(int(time.time())), "w+") + + def on_any_event(self, event): + """ + monitor the files associated with performance + """ + if event.is_directory: + return None + + elif event.event_type == 'created' or event.event_type == 'modified': + if "cyber_benchmark_reader" not in event.src_path.split('/')[-1] or \ + not event.src_path.split('/')[-1].endswith("latency.data"): + return None + if self.performance_key is None: + return None + + current = time.time() + if current - self.last_sample_time < 1: + return None + + self.last_sample_time = current + + latancy_data_path = event.src_path + try: + with open(latancy_data_path, "r") as f: + for l in f.readlines(): + k, v = l.strip().split(" : ")[0], l.strip().split(" : ")[1] + if k in self.latency_key: + if self.latency_key[k] not in self.performances[self.performance_key]: + self.performances[self.performance_key][self.latency_key[k]] = [] + self.performances[ + self.performance_key][self.latency_key[k]].append(int(v)) + except: + return None + + def parse_result(self): + """ + get the final results of performance + """ + global reader_nums + for i in range(reader_nums): + data_path = os.path.join( + self.directory_to_watch, f"cyber_benchmark_reader_{i}.data") + recv_total = -1 + send_total = -1 + with open(data_path, "r") as f: + for l in f.readlines(): + k, v = l.strip().strip().split(" : ")[0], l.strip().split(" : ")[1] + if k == f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_recv_msgs_nums": + if i == 0: + recv_total = int(v) + else: + recv_total += int(v) + elif k == f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_total_msgs_nums": + if i == 0: + send_total = int(v) + else: + send_total += int(v) + if recv_total == -1 or send_total == -1: + logger.error("parse cyber_benchmark_reader.data result failed") + sys.exit(3) + + writer_data_path = os.path.join( + self.directory_to_watch, "cyber_benchmark_writer.data") + test_time = -1 + test_message_size = -1 + with open(writer_data_path, "r") as f: + for l in f.readlines(): + k, v = l.strip().strip().split(" : ")[0], l.strip().split(" : ")[1] + if k == "cyber_benchmark_cyber_benchmark_writer_test_time": + test_time = float(v) + elif k == "cyber_benchmark_cyber_benchmark_writer_message_size": + test_message_size = int(v) + if test_time == -1 or test_message_size == -1: + logger.error("parse cyber_benchmark_writer.data result failed") + sys.exit(3) + + test_message_size = test_message_size / 1024 / 1024 # in MB + + msg_lose_rate = round((send_total - recv_total) / send_total * 100, 2) + bandwidth = round(recv_total * test_message_size / test_time * 8, 2) # mbps + + ret_str = f"{self.performance_key}:\n" + for k in self.performances[self.performance_key]: + self.performances[self.performance_key][k].remove( + max(self.performances[self.performance_key][k])) + self.performances[self.performance_key][k].remove( + min(self.performances[self.performance_key][k])) + self.performances[self.performance_key][k] = list( + filter(lambda x: x != 0, self.performances[self.performance_key][k])) + if "cpu" in k: + self.performances[self.performance_key][k] = list( + filter(lambda x: x < 120, self.performances[self.performance_key][k])) + pavg = round(np.mean(self.performances[self.performance_key][k]), 2) + p99 = round(np.percentile(self.performances[self.performance_key][k], 99), 2) + p95 = round(np.percentile(self.performances[self.performance_key][k], 95), 2) + p50 = round(np.percentile(self.performances[self.performance_key][k], 50), 2) + pmin = round(np.min(self.performances[self.performance_key][k]), 2) + pmax = round(np.max(self.performances[self.performance_key][k]), 2) + ret_str += f"{k}: \n" + ret_str += f" avg: {pavg}, pmin: {pmin}, pmax: {pmax}, p50: {p50}, p95: {p95}, p99: {p99}\n" + + ret_str += f"bandwidth: {bandwidth} mbps\n" + ret_str += f"msg_lose_rate: {msg_lose_rate}%" + print(ret_str) + self.performances[self.performance_key]["test_message_size"] = test_message_size + self.performances[self.performance_key]["test_time"] = test_time + + def save_data(self): + """ + record all performance data + """ + self.data_fd.write( + json.dumps(self.performances[self.performance_key])) + self.data_fd.flush() + + def run(self): + """ + run the performance test + """ + global reader_nums + transport_data_type = [] + if self.params.transport_type == 0 or \ + self.params.transport_type == 1: + transport_data_type = [self.params.transport_type] + else: + transport_data_type = [0, 1] + + cartesian_product = list(itertools.product(self.params.data_size, + self.params.reader_nums, self.params.frequency, transport_data_type)) + + for item in cartesian_product: + ds = item[0] + rn = item[1] + f = item[2] + dt = item[3] + + reader_nums = rn + + for k in self.base_key: + self.latency_key[k] = self.base_key[k] + for i in range(rn): + self.latency_key[ + f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_cyber_latency" + ] = "cyber_latency" + self.latency_key[ + f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_tran_latency" + ] = "cyber_tran_latency" + + if self.params.best_effords: + qos = 1 + else: + qos = 0 + self.performance_key = \ + f"data-size:{ds}/reader-nums:{rn}/frequency:{f}/data_type:{dt}/qos:{qos}" + self.performances[self.performance_key] = {} + print(f"\nrunning test with {self.performance_key}") + self.readers = [] + for i in range(rn): + try: + reader_args_list = [ + "cyber_benchmark_reader", + "-n", f"{i}"] + reader = subprocess.Popen(reader_args_list, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except Exception as err: + logger.error('Subprocess Popen exception: ' + str(err)) + sys.exit(2) + else: + if reader.pid == 0 or reader.returncode is not None: + logger.error('Start process cyber_benchmark_reader failed.') + sys.exit(2) + self.readers.append(reader) + time.sleep(3) + try: + writer_args_list = [ + "cyber_benchmark_writer", "-s", f"{ds}", + "-t", f"{f}", "-T", f"{self.params.time}", + "-d", f"{dt}", "-q", f"{qos}"] + ret = subprocess.run(writer_args_list, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL) + except Exception as err: + logger.error('Subprocess run writer exception: ' + str(err)) + sys.exit(2) + else: + if ret.returncode != 0: + logger.error('Run process cyber_benchmark_writer failed.') + sys.exit(2) + time.sleep(3) + for reader in self.readers: + reader.kill() + self.parse_result() + self.save_data() + + +def param_parse(params): + """ + parse user parameters + """ + pattern = re.compile(r'^\d+(\.\d+)?[kKmMbB]$') + for i in range(len(params.data_size)): + param = params.data_size[i] + if not pattern.match(param): + logger.error(f"data size {param} is invalid") + params.data_size[i] = \ + param[: len(params.data_size[i]) - 1] + param[-1].upper() + for i in range(len(params.reader_nums)): + try: + param = int(params.reader_nums[i]) + except: + logger.error( + f"reader nums {params.reader_nums[i]} is invalid") + params.reader_nums[i] = param + for i in range(len(params.frequency)): + try: + param = int(params.frequency[i]) + except: + logger.error( + f"frequency {params.frequency[i]} is invalid") + params.frequency[i] = param + return params + + +def main(): + """ + entry + """ + parser = argparse.ArgumentParser(description='cyber benchmark') + parser.add_argument( + '-s', '--data_size', nargs='*', metavar='*', + default=['16B', '1K', '64K', '256K', '1M', '5M', '10M'], + type=str.lstrip, help="transport data size, default is 16B - 10M" + ) + parser.add_argument( + '-T', '--transport_type', type=int, default=0, + help='transport data type, 0 means bytes, 1 means repeted field, while others mean both' + ) + parser.add_argument( + '-b', '--best_effords', action='store_true', default=False, + help='test the performance using qos policy best effords' + ) + parser.add_argument( + '-r', '--reader_nums', nargs='*', metavar='*', default=[1, 2, 5, 10], + help='desribe how many readers receive the message' + ) + parser.add_argument( + '-f', '--frequency', nargs='*', metavar='*', default=[10, 20, 50, 100, -1], + help='desribe the frequency of message sended, e.g. 10 means 10 hz' + ) + parser.add_argument( + '-t', '--time', type=int, default=60, + help='desribe the time of performance test, default is 60s' + ) + params = param_parse(parser.parse_args(sys.argv[1:])) + benchmark = Benchmark(params) + observer = Observer() + + observer.schedule(benchmark, benchmark.directory_to_watch) + observer.start() + benchmark.run() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/cyber/benchmark/cyber_benchmark_reader.cc b/cyber/benchmark/cyber_benchmark_reader.cc new file mode 100644 index 0000000..a23fb2f --- /dev/null +++ b/cyber/benchmark/cyber_benchmark_reader.cc @@ -0,0 +1,179 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include +#include +#include +#include + +#include "cyber/benchmark/benchmark_msg.pb.h" +#include "cyber/cyber.h" + +#if __has_include("gperftools/profiler.h") +#include "gperftools/heap-profiler.h" +#include "gperftools/malloc_extension.h" +#include "gperftools/profiler.h" +#endif + +using apollo::cyber::benchmark::BenchmarkMsg; + +std::string BINARY_NAME = "cyber_benchmark_reader"; // NOLINT + +int nums_of_reader = 1; +bool enable_cpuprofile = false; +bool enable_heapprofile = false; +std::string profile_filename = "cyber_benchmark_reader_cpu.prof"; // NOLINT +std::string heapprofile_filename = "cyber_benchmark_reader_mem.prof"; // NOLINT + +void DisplayUsage() { + AINFO << "Usage: \n " << BINARY_NAME << " [OPTION]...\n" + << "Description: \n" + << " -h, --help: help information \n" + << " -n, --nums_of_reader=nums_of_reader: numbers of reader, " + "default value is 1\n" + << " -c, --cpuprofile: enable gperftools cpu profile\n" + << " -o, --profile_filename=filename: the filename to dump the " + "profile to, default value is cyber_benchmark_writer_cpu.prof. " + "Only work with -c option\n" + << " -H, --heapprofile: enable gperftools heap profile\n" + << " -O, --heapprofile_filename=filename: the filename " + " to dump the profile to, default value is " + "cyber_benchmark_writer_mem.prof. Only work with -H option\n" + << "Example:\n" + << " " << BINARY_NAME << " -h\n" + << " " << BINARY_NAME << " -n 1\n" + << " " << BINARY_NAME << " -n 10 -c -H "; +} + +void GetOptions(const int argc, char* const argv[]) { + opterr = 0; // extern int opterr + int long_index = 0; + const std::string short_opts = "hn:co:HO:"; + static const struct option long_opts[] = { + {"help", no_argument, nullptr, 'h'}, + {"nums_of_reader", required_argument, nullptr, 'n'}, + {"cpuprofile", no_argument, nullptr, 'c'}, + {"profile_filename", required_argument, nullptr, 'o'}, + {"heapprofile", no_argument, nullptr, 'H'}, + {"heapprofile_filename", required_argument, nullptr, 'O'}, + {NULL, no_argument, nullptr, 0}}; + + // log command for info + std::string cmd(""); + for (int i = 0; i < argc; ++i) { + cmd += argv[i]; + cmd += " "; + } + AINFO << "command: " << cmd; + + if (1 == argc) { + DisplayUsage(); + exit(0); + } + + do { + int opt = + getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); + if (opt == -1) { + break; + } + switch (opt) { + case 'n': + nums_of_reader = std::stoi(std::string(optarg)); + if (nums_of_reader < 0) { + AERROR << "Invalid numbers of reader. It should be grater than 0"; + exit(-1); + } + break; + case 'c': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_cpuprofile = true; + break; + case 'o': + profile_filename = std::string(optarg); + break; + case 'H': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_heapprofile = true; + break; + case 'O': + heapprofile_filename = std::string(optarg); + break; + case 'h': + DisplayUsage(); + exit(0); + default: + break; + } + } while (true); + + if (optind < argc) { + AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; + DisplayUsage(); + exit(1); + } +} + +int main(int argc, char** argv) { + GetOptions(argc, argv); + google::SetCommandLineOption("bvar_dump_interval", "1"); + apollo::cyber::Init(argv[0], + BINARY_NAME + "_" + std::to_string(nums_of_reader)); + + apollo::cyber::ReaderConfig reader_config; + reader_config.channel_name = "/apollo/cyber/benchmark"; + reader_config.qos_profile.set_depth(10); + + std::vector>> vec; + + // for (int i = 0; i < nums_of_reader; i++) { + std::string node_name = BINARY_NAME + "-" + std::to_string(nums_of_reader); + auto node = apollo::cyber::CreateNode(node_name); + vec.push_back(std::move(node->CreateReader( + reader_config, [](const std::shared_ptr m) {}))); + // } + +#ifndef NO_TCMALLOC +#ifdef BASE_PROFILER_H_ + if (enable_cpuprofile) { + ProfilerStart(profile_filename.c_str()); + } + if (enable_heapprofile) { + HeapProfilerStart(heapprofile_filename.c_str()); + } +#endif +#endif + + apollo::cyber::WaitForShutdown(); + +#ifndef NO_TCMALLOC +#ifdef BASE_PROFILER_H_ + if (enable_cpuprofile) { + ProfilerStop(); + } + if (enable_heapprofile) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } +#endif +#endif + + return 0; +} diff --git a/cyber/benchmark/cyber_benchmark_writer.cc b/cyber/benchmark/cyber_benchmark_writer.cc new file mode 100644 index 0000000..78b19ca --- /dev/null +++ b/cyber/benchmark/cyber_benchmark_writer.cc @@ -0,0 +1,362 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "cyber/benchmark/benchmark_msg.pb.h" +#include "cyber/cyber.h" +#include "cyber/time/duration.h" +#include "cyber/time/time.h" + +#if __has_include("gperftools/profiler.h") +#include "gperftools/heap-profiler.h" +#include "gperftools/malloc_extension.h" +#include "gperftools/profiler.h" +#endif + +std::string BINARY_NAME = "cyber_benchmark_writer"; // NOLINT + +int message_size = -1; +int transport_freq = -1; +int qos_policy = 0; +int data_type = 0; +int running_time = 10; +bool enable_cpuprofile = false; +bool enable_heapprofile = false; +std::string profile_filename = "cyber_benchmark_writer_cpu.prof"; // NOLINT +std::string heapprofile_filename = "cyber_benchmark_writer_mem.prof"; // NOLINT + +void DisplayUsage() { + AINFO << "Usage: \n " << BINARY_NAME << " [OPTION]...\n" + << "Description: \n" + << " -h, --help: help information \n" + << " -s, --message_size=message_size: transport message size\n" + << " -t, --transport_freq=transmission_frequency: transmission " + "frequency\n" // NOLINT + << " -q, --qos_policy=qos_reliable_policy: set qos reliable policy, " + "0 is Reliable, 1 is Best effort, default value is 0\n" + << " -d, --data_type=data_type: transport data type, " + "0 is bytes, 1 is repeated field, default value is 0\n" + << " -T, --time=time: running time, default value is 10 seconds\n" + << " -c, --cpuprofile: enable gperftools cpu profile\n" + << " -o, --profile_filename=filename: the filename to dump the " + "profile to, default value is cyber_benchmark_writer_cpu.prof. Only " + "work " // NOLINT + "with -c option\n" + << " -H, --heapprofile: enable gperftools heap profile\n" + << " -O, --heapprofile_filename=filename: the filename to dump the " + "profile to, default value is cyber_benchmark_writer_mem.prof. Only " + "work " // NOLINT + "with -H option\n" + << "Example:\n" + << " " << BINARY_NAME << " -h\n" + << " " << BINARY_NAME << " -s 64K -t 10\n" + << " " << BINARY_NAME << " -s 64K -t 10 -c -H "; +} + +void GetOptions(const int argc, char* const argv[]) { + opterr = 0; // extern int opterr + int long_index = 0; + const std::string short_opts = "hs:t:q:d:T:co:HO:"; + static const struct option long_opts[] = { + {"help", no_argument, nullptr, 'h'}, + {"message_size", required_argument, nullptr, 's'}, + {"transport_freq", required_argument, nullptr, 't'}, + {"qos_policy", required_argument, nullptr, 'q'}, + {"data_type", required_argument, nullptr, 'd'}, + {"time", required_argument, nullptr, 'T'}, + {"cpuprofile", no_argument, nullptr, 'c'}, + {"profile_filename", required_argument, nullptr, 'o'}, + {"heapprofile", no_argument, nullptr, 'H'}, + {"heapprofile_filename", required_argument, nullptr, 'O'}, + {NULL, no_argument, nullptr, 0}}; + + // log command for info + std::string cmd(""); + for (int i = 0; i < argc; ++i) { + cmd += argv[i]; + cmd += " "; + } + AINFO << "command: " << cmd; + + if (1 == argc) { + DisplayUsage(); + exit(0); + } + + do { + int opt = + getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); + if (opt == -1) { + break; + } + int base_size = 1; + std::string arg; + switch (opt) { + case 's': + arg = std::string(optarg); + switch (arg[arg.length() - 1]) { + case 'B': + base_size = 1; + break; + case 'K': + base_size = 1024; + break; + case 'M': + base_size = 1024 * 1024; + break; + default: + AERROR << "Invalid identifier. It should be 'K' or 'M' or 'B'"; + exit(-1); + } + message_size = std::stoi(arg.substr(0, arg.length() - 1)) * base_size; + if (message_size < 0 || message_size % 4 != 0) { + AERROR << "Invalid message size."; + exit(-1); + } + break; + case 't': + transport_freq = std::stoi(std::string(optarg)); + break; + case 'T': + running_time = std::stoi(std::string(optarg)); + if (running_time < 0) { + AERROR << "Invalid running time. It should greater than 0"; + exit(-1); + } + break; + case 'q': + qos_policy = std::stoi(std::string(optarg)); + if (qos_policy != 0 && qos_policy != 1) { + AERROR << "Invalid qos_policy. It should be 0 or 1"; + exit(-1); + } + break; + case 'd': + data_type = std::stoi(std::string(optarg)); + if (data_type != 0 && data_type != 1) { + AERROR << "Invalid data_type. It should be 0 or 1"; + exit(-1); + } + break; + case 'c': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_cpuprofile = true; + break; + case 'o': + profile_filename = std::string(optarg); + break; + case 'H': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_heapprofile = true; + break; + case 'O': + heapprofile_filename = std::string(optarg); + break; + case 'h': + DisplayUsage(); + exit(0); + default: + break; + } + } while (true); + + if (optind < argc) { + AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; + DisplayUsage(); + exit(1); + } + + if (message_size == -1) { + AINFO << "-s parameters must be specified"; + DisplayUsage(); + exit(1); + } +} + +int main(int argc, char** argv) { + GetOptions(argc, argv); + google::SetCommandLineOption("bvar_dump_interval", "1"); + + apollo::cyber::Init(argv[0], BINARY_NAME); + + auto node = apollo::cyber::CreateNode(BINARY_NAME); + auto test_time = + std::make_shared<::bvar::Status>(BINARY_NAME + "-test-time", 0); + auto test_message_size = std::make_shared<::bvar::Status>( + BINARY_NAME + "-message-size", 0); + apollo::cyber::proto::RoleAttributes attrs; + attrs.set_channel_name("/apollo/cyber/benchmark"); + auto qos = attrs.mutable_qos_profile(); + qos->set_depth(10); + + if (qos_policy == 1) { + qos->set_reliability( + apollo::cyber::proto::QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); + } else { + qos->set_reliability( + apollo::cyber::proto::QosReliabilityPolicy::RELIABILITY_RELIABLE); + } + auto writer = + node->CreateWriter(attrs); + + // sleep a while for initialization, aboout 2 seconds + apollo::cyber::Rate rate_init(0.5); + + apollo::cyber::Rate rate_ctl(static_cast(transport_freq)); + + rate_init.Sleep(); + + uint64_t send_msg_total = transport_freq * running_time; + + // std::vector trans_vec; + // int num_of_instance = message_size / 4; + // for (int i = 0; i < num_of_instance; i++) { + // trans_vec.push_back(rand()); + // } + + // char* data = (char*)malloc(message_size); + // for (int i = 0; i < num_of_instance; i++) { + // *(uint32_t*)(data + i * 4) = rand(); + // } + + // if (data_type == 0) { + // trans_unit->set_data_bytes(data, message_size); + // } else { + // for (int i = 0; i < num_of_instance; i++) { + // trans_unit->add_data(trans_vec[i]); + // } + // } + // free(data); + + int send_msg = 0; + +#ifndef NO_TCMALLOC +#ifdef BASE_PROFILER_H_ + if (enable_cpuprofile) { + ProfilerStart(profile_filename.c_str()); + } + if (enable_heapprofile) { + HeapProfilerStart(heapprofile_filename.c_str()); + } +#endif +#endif + + std::vector trans_vec; + int num_of_instance = message_size / 4; + for (int i = 0; i < num_of_instance; i++) { + trans_vec.push_back(rand()); // NOLINT + } + + char* data = (char*)malloc(message_size); // NOLINT + + if (transport_freq > 0) { + auto start_time = apollo::cyber::Time::Now(); + while (send_msg < send_msg_total) { + auto trans_unit = writer->AcquireMessage(); + int base = rand(); // NOLINT + + for (int i = 0; i < num_of_instance; i++) { + trans_vec[i] = base * i; + } + + for (int i = 0; i < num_of_instance; i++) { + *(uint32_t*)(data + i * 4) = base * i; // NOLINT + } + + if (data_type == 0) { + trans_unit->set_data_bytes(data, message_size); + } else { + for (int i = 0; i < num_of_instance; i++) { + trans_unit->add_data(trans_vec[i]); + } + } + + writer->Write(trans_unit); + ++send_msg; + + rate_ctl.Sleep(); + } + auto end_time = apollo::cyber::Time::Now(); + test_time->set_value((end_time - start_time).ToSecond()); + } else { + auto start_time = apollo::cyber::Time::Now(); + auto current = start_time; + auto endtime = apollo::cyber::Time::Now() + + apollo::cyber::Duration(static_cast(running_time)); + while (current < endtime) { + auto trans_unit = writer->AcquireMessage(); + int base = rand(); // NOLINT + + for (int i = 0; i < num_of_instance; i++) { + trans_vec[i] = base * i; + } + + for (int i = 0; i < num_of_instance; i++) { + *(uint32_t*)(data + i * 4) = base * i; // NOLINT + } + + if (data_type == 0) { + trans_unit->set_data_bytes(data, message_size); + } else { + for (int i = 0; i < num_of_instance; i++) { + trans_unit->add_data(trans_vec[i]); + } + } + + writer->Write(trans_unit); + ++send_msg; + current = apollo::cyber::Time::Now(); + } + test_time->set_value((current - start_time).ToSecond()); + } + + auto m = writer->AcquireMessage(); + if (data_type == 0) { + m->set_data_bytes(data, message_size); + } else { + for (int i = 0; i < num_of_instance; i++) { + m->add_data(trans_vec[i]); + } + } + test_message_size->set_value(m->ByteSizeLong()); + + free(data); + +#ifndef NO_TCMALLOC +#ifdef BASE_PROFILER_H_ + if (enable_cpuprofile) { + ProfilerStop(); + } + if (enable_heapprofile) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } +#endif +#endif + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + apollo::cyber::Clear(); + + return 0; +} diff --git a/cyber/common/BUILD b/cyber/common/BUILD index 5d9031d..386fc8e 100644 --- a/cyber/common/BUILD +++ b/cyber/common/BUILD @@ -1,16 +1,13 @@ load("//tools:cpplint.bzl", "cpplint") -load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package", "apollo_cc_test") +load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") package(default_visibility = ["//visibility:public"]) apollo_cc_library( name = "cyber_common", srcs = [ - "global_data.cc", "file.cc", - ], - data = [ - "//cyber:cyber_conf", + "global_data.cc", ], hdrs = [ "environment.h", @@ -22,13 +19,17 @@ apollo_cc_library( "types.h", "util.h", ], + data = [ + "//cyber:cyber_conf", + ], deps = [ "//cyber:cyber_binary", "//cyber/base:cyber_base", "//cyber/proto:cyber_conf_cc_proto", + "//cyber/proto:transport_conf_cc_proto", + "@com_github_google_glog//:glog", "@com_github_nlohmann_json//:json", "@com_google_protobuf//:protobuf", - "@com_github_google_glog//:glog", ], ) diff --git a/cyber/common/file.cc b/cyber/common/file.cc index 29b1930..44a61ef 100644 --- a/cyber/common/file.cc +++ b/cyber/common/file.cc @@ -66,6 +66,26 @@ bool SetProtoToASCIIFile(const google::protobuf::Message &message, return SetProtoToASCIIFile(message, fd); } +bool SetStringToASCIIFile(const std::string &content, + const std::string &file_name) { + int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); + if (fd < 0) { + AERROR << "Unable to open file " << file_name << " to write."; + return false; + } + // Write the string data to the file + ssize_t bytes_written = write(fd, content.c_str(), content.size()); + if (bytes_written < 0) { + AERROR << "Failed to write to file."; + close(fd); // Ensure the file descriptor is closed even on error + return false; + } + + close(fd); // Close the file descriptor + + return true; +} + bool GetProtoFromASCIIFile(const std::string &file_name, google::protobuf::Message *message) { using google::protobuf::TextFormat; @@ -227,12 +247,26 @@ bool CopyFile(const std::string &from, const std::string &to) { return true; } +bool IsValidPath(const std::string &path) { + const std::string illegal_chars = "\0<>:\"|?*;"; + for (char ch : path) { + if (illegal_chars.find(ch) != std::string::npos) { + return false; + } + } + return true; +} + bool CopyDir(const std::string &from, const std::string &to) { DIR *directory = opendir(from.c_str()); if (directory == nullptr) { AERROR << "Cannot open directory " << from; return false; } + if (!IsValidPath(from) || !IsValidPath(to)) { + AERROR << "invalid path format: " << from << " to " << to; + return false; + } bool ret = true; if (EnsureDirectory(to)) { diff --git a/cyber/common/file.h b/cyber/common/file.h index eee9a97..ec3dd88 100644 --- a/cyber/common/file.h +++ b/cyber/common/file.h @@ -60,6 +60,16 @@ bool SetProtoToASCIIFile(const google::protobuf::Message &message, bool SetProtoToASCIIFile(const google::protobuf::Message &message, const std::string &file_name); +/** + * @brief Sets the content of the file specified by the file_name to be the + * ascii representation of the input string. + * @param content The string to output to the specified file. + * @param file_name The name of the target file to set the content. + * @return If the action is successful. + */ +bool SetStringToASCIIFile(const std::string &content, + const std::string &file_name); + /** * @brief Parses the content of the file specified by the file_name as ascii * representation of protobufs, and merges the parsed content to the diff --git a/cyber/common/file_test.cc b/cyber/common/file_test.cc index addd677..853daad 100644 --- a/cyber/common/file_test.cc +++ b/cyber/common/file_test.cc @@ -120,9 +120,9 @@ TEST(FileTest, Glob) { EXPECT_THAT( Glob("/apol?o/modules/p*"), testing::AllOf( - testing::Contains(std::string("/apollo/modules/perception")), - testing::Contains(std::string("/apollo/modules/planning")), - testing::Contains(std::string("/apollo/modules/prediction")))); + testing::Contains(std::string("modules/perception")), + testing::Contains(std::string("modules/planning")), + testing::Contains(std::string("modules/prediction")))); } TEST(FileTest, GetAbsolutePath) { diff --git a/cyber/common/global_data.cc b/cyber/common/global_data.cc index 7d94f1b..4a54063 100644 --- a/cyber/common/global_data.cc +++ b/cyber/common/global_data.cc @@ -103,6 +103,51 @@ bool GlobalData::IsMockTimeMode() const { return clock_mode_ == ClockMode::MODE_MOCK; } +bool GlobalData::IsChannelEnableArenaShm(std::string channel_name) const { + if (!config_.has_transport_conf() || + !config_.transport_conf().has_shm_conf() || + !config_.transport_conf().shm_conf().has_arena_shm_conf()) { + return false; + } + bool found = false; + for (auto arena_channel_conf : config_.transport_conf() + .shm_conf() + .arena_shm_conf() + .arena_channel_conf()) { + if (channel_name == arena_channel_conf.channel_name()) { + found = true; + break; + } + } + return found; +} + +bool GlobalData::IsChannelEnableArenaShm(uint64_t channel_id) const { + auto channel_name = + cyber::common::GlobalData::Instance()->GetChannelById(channel_id); + return IsChannelEnableArenaShm(channel_name); +} + +apollo::cyber::proto::ArenaChannelConf GlobalData::GetChannelArenaConf( + std::string channel_name) const& { + for (auto arena_channel_conf : config_.transport_conf() + .shm_conf() + .arena_shm_conf() + .arena_channel_conf()) { + if (channel_name == arena_channel_conf.channel_name()) { + return arena_channel_conf; + } + } + return apollo::cyber::proto::ArenaChannelConf(); +} + +apollo::cyber::proto::ArenaChannelConf GlobalData::GetChannelArenaConf( + uint64_t channel_id) const& { + auto channel_name = + cyber::common::GlobalData::Instance()->GetChannelById(channel_id); + return GetChannelArenaConf(channel_name); +} + void GlobalData::InitHostInfo() { char host_name[1024]; gethostname(host_name, sizeof(host_name)); diff --git a/cyber/common/global_data.h b/cyber/common/global_data.h index 2e3a194..d3ce39b 100644 --- a/cyber/common/global_data.h +++ b/cyber/common/global_data.h @@ -21,6 +21,7 @@ #include #include "cyber/proto/cyber_conf.pb.h" +#include "cyber/proto/transport_conf.pb.h" #include "cyber/base/atomic_hash_map.h" #include "cyber/base/atomic_rw_lock.h" @@ -64,6 +65,13 @@ class GlobalData { bool IsRealityMode() const; bool IsMockTimeMode() const; + bool IsChannelEnableArenaShm(std::string channel_name) const; + bool IsChannelEnableArenaShm(uint64_t channel_id) const; + apollo::cyber::proto::ArenaChannelConf GetChannelArenaConf( + std::string channel_name) const&; + apollo::cyber::proto::ArenaChannelConf GetChannelArenaConf( + uint64_t channel_id) const&; + static uint64_t GenerateHashId(const std::string& name) { return common::Hash(name); } diff --git a/cyber/component/component.h b/cyber/component/component.h index 4b36fd7..b1700b6 100644 --- a/cyber/component/component.h +++ b/cyber/component/component.h @@ -30,6 +30,8 @@ #include "cyber/croutine/routine_factory.h" #include "cyber/data/data_visitor.h" #include "cyber/scheduler/scheduler.h" +#include "cyber/statistics/statistics.h" +#include "cyber/time/time.h" namespace apollo { namespace cyber { @@ -181,15 +183,31 @@ bool Component::Initialize( reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + auto role_attr = std::make_shared(); + role_attr->set_node_name(config.name()); + role_attr->set_channel_name(config.readers(0).channel()); + std::weak_ptr> self = std::dynamic_pointer_cast>(shared_from_this()); - auto func = [self](const std::shared_ptr& msg) { + auto func = [self, role_attr](const std::shared_ptr& msg) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { ptr->Process(msg); } else { AERROR << "Component object has been destroyed."; } + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } }; std::shared_ptr> reader = nullptr; @@ -257,6 +275,10 @@ bool Component::Initialize( reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + auto role_attr = std::make_shared(); + role_attr->set_node_name(config.name()); + role_attr->set_channel_name(config.readers(0).channel()); + std::shared_ptr> reader0 = nullptr; if (cyber_likely(is_reality_mode)) { reader0 = node_->template CreateReader(reader_cfg); @@ -267,12 +289,24 @@ bool Component::Initialize( auto blocker1 = blocker::BlockerManager::Instance()->GetBlocker( config.readers(1).channel()); - auto func = [self, blocker1](const std::shared_ptr& msg0) { + auto func = [self, blocker1, role_attr](const std::shared_ptr& msg0) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { if (!blocker1->IsPublishedEmpty()) { auto msg1 = blocker1->GetLatestPublishedPtr(); ptr->Process(msg0, msg1); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } } } else { AERROR << "Component object has been destroyed."; @@ -295,11 +329,23 @@ bool Component::Initialize( auto sched = scheduler::Instance(); std::weak_ptr> self = std::dynamic_pointer_cast>(shared_from_this()); - auto func = [self](const std::shared_ptr& msg0, - const std::shared_ptr& msg1) { + auto func = [self, role_attr](const std::shared_ptr& msg0, + const std::shared_ptr& msg1) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { ptr->Process(msg0, msg1); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } } else { AERROR << "Component object has been destroyed."; } @@ -359,6 +405,11 @@ bool Component::Initialize( reader_cfg.channel_name = config.readers(0).channel(); reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + + auto role_attr = std::make_shared(); + role_attr->set_node_name(config.name()); + role_attr->set_channel_name(config.readers(0).channel()); + std::shared_ptr> reader0 = nullptr; if (cyber_likely(is_reality_mode)) { reader0 = node_->template CreateReader(reader_cfg); @@ -372,13 +423,26 @@ bool Component::Initialize( auto blocker2 = blocker::BlockerManager::Instance()->GetBlocker( config.readers(2).channel()); - auto func = [self, blocker1, blocker2](const std::shared_ptr& msg0) { + auto func = [self, blocker1, blocker2, + role_attr](const std::shared_ptr& msg0) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { if (!blocker1->IsPublishedEmpty() && !blocker2->IsPublishedEmpty()) { auto msg1 = blocker1->GetLatestPublishedPtr(); auto msg2 = blocker2->GetLatestPublishedPtr(); ptr->Process(msg0, msg1, msg2); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } } } else { AERROR << "Component object has been destroyed."; @@ -404,12 +468,24 @@ bool Component::Initialize( std::weak_ptr> self = std::dynamic_pointer_cast>( shared_from_this()); - auto func = [self](const std::shared_ptr& msg0, - const std::shared_ptr& msg1, - const std::shared_ptr& msg2) { + auto func = [self, role_attr](const std::shared_ptr& msg0, + const std::shared_ptr& msg1, + const std::shared_ptr& msg2) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { ptr->Process(msg0, msg1, msg2); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } } else { AERROR << "Component object has been destroyed."; } @@ -476,6 +552,10 @@ bool Component::Initialize(const ComponentConfig& config) { reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + auto role_attr = std::make_shared(); + role_attr->set_node_name(config.name()); + role_attr->set_channel_name(config.readers(0).channel()); + std::shared_ptr> reader0 = nullptr; if (cyber_likely(is_reality_mode)) { reader0 = node_->template CreateReader(reader_cfg); @@ -491,8 +571,9 @@ bool Component::Initialize(const ComponentConfig& config) { auto blocker3 = blocker::BlockerManager::Instance()->GetBlocker( config.readers(3).channel()); - auto func = [self, blocker1, blocker2, - blocker3](const std::shared_ptr& msg0) { + auto func = [self, blocker1, blocker2, blocker3, + role_attr](const std::shared_ptr& msg0) { + auto start_time = Time::Now().ToMicrosecond(); auto ptr = self.lock(); if (ptr) { if (!blocker1->IsPublishedEmpty() && !blocker2->IsPublishedEmpty() && @@ -501,6 +582,17 @@ bool Component::Initialize(const ComponentConfig& config) { auto msg2 = blocker2->GetLatestPublishedPtr(); auto msg3 = blocker3->GetLatestPublishedPtr(); ptr->Process(msg0, msg1, msg2, msg3); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } } } else { AERROR << "Component object has been destroyed."; @@ -527,16 +619,29 @@ bool Component::Initialize(const ComponentConfig& config) { auto sched = scheduler::Instance(); std::weak_ptr> self = std::dynamic_pointer_cast>(shared_from_this()); - auto func = - [self](const std::shared_ptr& msg0, const std::shared_ptr& msg1, - const std::shared_ptr& msg2, const std::shared_ptr& msg3) { - auto ptr = self.lock(); - if (ptr) { - ptr->Process(msg0, msg1, msg2, msg3); - } else { - AERROR << "Component object has been destroyed." << std::endl; - } - }; + auto func = [self, role_attr](const std::shared_ptr& msg0, + const std::shared_ptr& msg1, + const std::shared_ptr& msg2, + const std::shared_ptr& msg3) { + auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + ptr->Process(msg0, msg1, msg2, msg3); + auto end_time = Time::Now().ToMicrosecond(); + // sampling proc latency and cyber latency in microsecond + uint64_t process_start_time; + statistics::Statistics::Instance()->SamplingProcLatency( + *role_attr, end_time - start_time); + if (statistics::Statistics::Instance()->GetProcStatus( + *role_attr, &process_start_time) && + (start_time - process_start_time) > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + *role_attr, start_time - process_start_time); + } + } else { + AERROR << "Component object has been destroyed." << std::endl; + } + }; std::vector config_list; for (auto& reader : readers_) { diff --git a/cyber/component/timer_component.cc b/cyber/component/timer_component.cc index 3248708..6cf96e0 100644 --- a/cyber/component/timer_component.cc +++ b/cyber/component/timer_component.cc @@ -16,6 +16,7 @@ #include "cyber/component/timer_component.h" +#include "cyber/statistics/statistics.h" #include "cyber/timer/timer.h" namespace apollo { @@ -44,9 +45,21 @@ bool TimerComponent::Initialize(const TimerComponentConfig& config) { } interval_ = config.interval(); + auto role_attr = std::make_shared(); + role_attr->set_node_name(config.name()); + role_attr->set_channel_name(statistics::TIMER_COMPONENT_CHAN_NAME); + statistics::Statistics::Instance()->RegisterChanVar(*role_attr); + std::shared_ptr self = std::dynamic_pointer_cast(shared_from_this()); - auto func = [self]() { self->Process(); }; + auto func = [self, role_attr]() { + auto start_time = Time::Now().ToNanosecond(); + self->Process(); + auto end_time = Time::Now().ToNanosecond(); + // sampling proc latency in microsecond + statistics::Statistics::Instance()->SamplingProcLatency< + uint64_t>(*role_attr, (end_time-start_time)/1000); + }; timer_.reset(new Timer(config.interval(), func, false)); timer_->Start(); return true; diff --git a/cyber/conf/cyber.pb.conf b/cyber/conf/cyber.pb.conf index 2ce5045..8cbf0f4 100644 --- a/cyber/conf/cyber.pb.conf +++ b/cyber/conf/cyber.pb.conf @@ -24,6 +24,29 @@ # max_history_depth: 1000 # } # } +# +transport_conf { + communication_mode { + same_proc: INTRA + diff_proc: SHM + diff_host: RTPS + } + participant_attr { + lease_duration: 12 + announcement_period: 3 + domain_id_gain: 250 + port_base: 7400 + } + shm_conf { + arena_shm_conf { + arena_channel_conf { + channel_name: "/apollo/msg" + max_msg_size: 33554432 + max_pool_size: 32 + } + } + } +} run_mode_conf { run_mode: MODE_REALITY diff --git a/cyber/context/BUILD b/cyber/context/BUILD index 8628958..3dffa88 100644 --- a/cyber/context/BUILD +++ b/cyber/context/BUILD @@ -19,6 +19,7 @@ apollo_cc_test( size = "small", srcs = ["context_test.cc"], linkstatic = True, + linkopts = ["-lm"], deps = [ ":cyber_context", "@com_google_googletest//:gtest_main", diff --git a/cyber/cyberfile.xml b/cyber/cyberfile.xml index 3f0195d..5601e16 100644 --- a/cyber/cyberfile.xml +++ b/cyber/cyberfile.xml @@ -16,7 +16,7 @@ //cyber libncurses5-dev - libuuid1 + uuid-dev 3rd-rules-python 3rd-grpc @@ -26,7 +26,10 @@ 3rd-bazel-skylib 3rd-protobuf - 3rd-fastrtps + + 3rd-fastdds-wrap + 3rd-proj + 3rd-eigen3 3rd-glog 3rd-gflags common-msgs @@ -36,4 +39,10 @@ libtinyxml2-dev bazel-extend-tools + libunwind-dev + nethogs + sysstat + gperftools + bvar + diff --git a/cyber/examples/common_component_example/common.launch b/cyber/examples/common_component_example/common.launch index 2dd31bf..f32358e 100644 --- a/cyber/examples/common_component_example/common.launch +++ b/cyber/examples/common_component_example/common.launch @@ -2,6 +2,8 @@ common /apollo/cyber/examples/common_component_example/common.dag + /apollo/example_cpu.prof + /apollo/example_mem.prof common diff --git a/cyber/examples/service.cc b/cyber/examples/service.cc index babe651..8aaf561 100644 --- a/cyber/examples/service.cc +++ b/cyber/examples/service.cc @@ -40,7 +40,7 @@ int main(int argc, char* argv[]) { while (apollo::cyber::OK()) { auto res = client->SendRequest(driver_msg); if (res != nullptr) { - AINFO << "client: responese: " << res->ShortDebugString(); + AINFO << "client: response: " << res->ShortDebugString(); } else { AINFO << "client: service may not ready."; } diff --git a/cyber/init.cc b/cyber/init.cc index 86cd48b..a53cb22 100644 --- a/cyber/init.cc +++ b/cyber/init.cc @@ -22,10 +22,14 @@ #include #include +#include #include +#include #include #include +#include "gflags/gflags.h" + #include "cyber/proto/clock.pb.h" #include "cyber/binary.h" @@ -36,6 +40,7 @@ #include "cyber/node/node.h" #include "cyber/scheduler/scheduler.h" #include "cyber/service_discovery/topology_manager.h" +#include "cyber/statistics/statistics.h" #include "cyber/sysmo/sysmo.h" #include "cyber/task/task.h" #include "cyber/time/clock.h" @@ -45,9 +50,6 @@ namespace apollo { namespace cyber { -using apollo::cyber::scheduler::Scheduler; -using apollo::cyber::service_discovery::TopologyManager; - namespace { const std::string& kClockChannel = "/clock"; @@ -93,7 +95,15 @@ void OnShutdown(int sig) { void ExitHandle() { Clear(); } -bool Init(const char* binary_name) { +bool Init(const char* binary_name, const std::string& dag_info) { + const char* apollo_runtime_path = std::getenv("APOLLO_RUNTIME_PATH"); + if (apollo_runtime_path != nullptr) { + if (std::filesystem::is_directory( + std::filesystem::status(apollo_runtime_path))) { + std::filesystem::current_path(apollo_runtime_path); + } + } + std::lock_guard lg(g_mutex); if (GetState() != STATE_UNINITIALIZED) { return false; @@ -127,6 +137,24 @@ bool Init(const char* binary_name) { }; clock_node->CreateReader(kClockChannel, cb); } + + if (dag_info != "") { + std::string dump_path; + if (dag_info.length() > 200) { + std::string truncated = dag_info.substr(0, 200); + dump_path = common::GetEnv("APOLLO_ENV_WORKROOT", "/apollo") + "/dumps/" + + truncated; + } else { + dump_path = common::GetEnv("APOLLO_ENV_WORKROOT", "/apollo") + "/dumps/" + + dag_info; + } + google::SetCommandLineOption("bvar_dump_file", dump_path.c_str()); + } else { + statistics::Statistics::Instance()->DisableChanVar(); + } + google::SetCommandLineOption("bvar_dump_exclude", "*qps"); + google::SetCommandLineOption("bvar_dump", "true"); + return true; } diff --git a/cyber/init.h b/cyber/init.h index d28c8dc..bac78a6 100644 --- a/cyber/init.h +++ b/cyber/init.h @@ -17,14 +17,17 @@ #ifndef CYBER_INIT_H_ #define CYBER_INIT_H_ +#include + #include "cyber/common/log.h" #include "cyber/state.h" namespace apollo { namespace cyber { -bool Init(const char* binary_name); +bool Init(const char* binary_name, const std::string& dag_info = ""); void Clear(); +void OnShutdown(int sig); } // namespace cyber } // namespace apollo diff --git a/cyber/mainboard/BUILD b/cyber/mainboard/BUILD index 7ae3f85..05feac4 100644 --- a/cyber/mainboard/BUILD +++ b/cyber/mainboard/BUILD @@ -12,9 +12,14 @@ apollo_cc_binary( "module_controller.cc", "module_controller.h", ], - linkopts = ["-pthread"], + linkopts = [ + "-pthread", + "-lprofiler", + "-ltcmalloc", + ], deps = [ "//cyber", + "//cyber/common:cyber_common", "//cyber/plugin_manager:cyber_plugin_manager", "//cyber/proto:dag_conf_cc_proto", ], diff --git a/cyber/mainboard/mainboard.cc b/cyber/mainboard/mainboard.cc index b518e08..1abe162 100644 --- a/cyber/mainboard/mainboard.cc +++ b/cyber/mainboard/mainboard.cc @@ -14,6 +14,11 @@ * limitations under the License. *****************************************************************************/ +#include + +#include +#include + #include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/init.h" @@ -21,6 +26,10 @@ #include "cyber/mainboard/module_controller.h" #include "cyber/state.h" +#include "gperftools/profiler.h" +#include "gperftools/heap-profiler.h" +#include "gperftools/malloc_extension.h" + using apollo::cyber::mainboard::ModuleArgument; using apollo::cyber::mainboard::ModuleController; @@ -29,8 +38,50 @@ int main(int argc, char** argv) { ModuleArgument module_args; module_args.ParseArgument(argc, argv); + auto dag_list = module_args.GetDAGConfList(); + + std::string dag_info; + for (auto&& i = dag_list.begin(); i != dag_list.end(); i++) { + size_t pos = 0; + for (size_t j = 0; j < (*i).length(); j++) { + pos = ((*i)[j] == '/') ? j: pos; + } + if (i != dag_list.begin()) dag_info += "_"; + + if (pos == 0) { + dag_info += *i; + } else { + dag_info += + (pos == (*i).length()-1) ? (*i).substr(pos): (*i).substr(pos+1); + } + } + + if (module_args.GetProcessGroup() != + apollo::cyber::mainboard::DEFAULT_process_group_) { + dag_info = module_args.GetProcessGroup(); + } + // initialize cyber - apollo::cyber::Init(argv[0]); + apollo::cyber::Init(argv[0], dag_info); + + static bool enable_cpu_profile = module_args.GetEnableCpuprofile(); + static bool enable_mem_profile = module_args.GetEnableHeapprofile(); + std::signal(SIGTERM, [](int sig){ + apollo::cyber::OnShutdown(sig); + if (enable_cpu_profile) { + ProfilerStop(); + } + + if (enable_mem_profile) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } + }); + + if (module_args.GetEnableHeapprofile()) { + auto profile_filename = module_args.GetHeapProfileFilename(); + HeapProfilerStart(profile_filename.c_str()); + } // start module ModuleController controller(module_args); @@ -40,7 +91,22 @@ int main(int argc, char** argv) { return -1; } + if (module_args.GetEnableCpuprofile()) { + auto profile_filename = module_args.GetProfileFilename(); + ProfilerStart(profile_filename.c_str()); + } + apollo::cyber::WaitForShutdown(); + + if (module_args.GetEnableCpuprofile()) { + ProfilerStop(); + } + + if (module_args.GetEnableHeapprofile()) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } + controller.Clear(); AINFO << "exit mainboard."; diff --git a/cyber/mainboard/module_argument.cc b/cyber/mainboard/module_argument.cc index f169583..7e59cea 100644 --- a/cyber/mainboard/module_argument.cc +++ b/cyber/mainboard/module_argument.cc @@ -16,9 +16,15 @@ #include "cyber/mainboard/module_argument.h" +#include "cyber/common/environment.h" + #include #include +#if __has_include("gperftools/profiler.h") +#include "gperftools/profiler.h" +#endif + using apollo::cyber::common::GlobalData; namespace apollo { @@ -38,6 +44,14 @@ void ModuleArgument::DisplayUsage() { "plugin\n" << " --disable_plugin_autoload : default enable autoload " "mode of plugins, use disable_plugin_autoload to ingore autoload\n" + << " -c, --cpuprofile: enable gperftools cpu profile\n" + << " -o, --profile_filename=filename: the filename to dump the " + "profile to, default value is ${process_group}_cpu.prof. Only work " + "with -c option\n" + << " -H, --heapprofile: enable gperftools heap profile\n" + << " -O, --heapprofile_filename=filename: the filename to dump the " + "profile to, default value is ${process_group}_mem.prof. Only work " + "with -c option\n" << "Example:\n" << " " << binary_name_ << " -h\n" << " " << binary_name_ << " -d dag_conf_file1 -d dag_conf_file2 " @@ -57,6 +71,27 @@ void ModuleArgument::ParseArgument(const int argc, char* const argv[]) { sched_name_ = DEFAULT_sched_name_; } + if (enable_cpuprofile_ && profile_filename_.empty()) { + auto pwd = common::GetEnv("PWD"); + profile_filename_ = pwd + "/" + process_group_ + std::string("_cpu.prof"); + } + + if (profile_filename_[0] != '/') { + auto pwd = common::GetEnv("PWD"); + profile_filename_ = pwd + "/" + profile_filename_; + } + + if (enable_heapprofile_ && heapprofile_filename_.empty()) { + auto pwd = common::GetEnv("PWD"); + heapprofile_filename_ = + pwd + "/" + process_group_ + std::string("_mem.prof"); + } + + if (heapprofile_filename_[0] != '/') { + auto pwd = common::GetEnv("PWD"); + heapprofile_filename_ = pwd + "/" + heapprofile_filename_; + } + GlobalData::Instance()->SetProcessGroup(process_group_); GlobalData::Instance()->SetSchedName(sched_name_); AINFO << "binary_name_ is " << binary_name_ << ", process_group_ is " @@ -69,7 +104,7 @@ void ModuleArgument::ParseArgument(const int argc, char* const argv[]) { void ModuleArgument::GetOptions(const int argc, char* const argv[]) { opterr = 0; // extern int opterr int long_index = 0; - const std::string short_opts = "hd:p:s:"; + const std::string short_opts = "hd:p:s:co:HO:"; static const struct option long_opts[] = { {"help", no_argument, nullptr, 'h'}, {"dag_conf", required_argument, nullptr, 'd'}, @@ -78,6 +113,10 @@ void ModuleArgument::GetOptions(const int argc, char* const argv[]) { {"plugin", required_argument, nullptr, ARGS_OPT_CODE_PLUGIN}, {"disable_plugin_autoload", no_argument, nullptr, ARGS_OPT_CODE_DISABLE_PLUGIN_AUTOLOAD}, + {"cpuprofile", no_argument, nullptr, 'c'}, + {"profile_filename", required_argument, nullptr, 'o'}, + {"heapprofile", no_argument, nullptr, 'H'}, + {"heapprofile_filename", required_argument, nullptr, 'O'}, {NULL, no_argument, nullptr, 0}}; // log command for info @@ -120,7 +159,25 @@ void ModuleArgument::GetOptions(const int argc, char* const argv[]) { plugin_description_list_.emplace_back(std::string(optarg)); break; case ARGS_OPT_CODE_DISABLE_PLUGIN_AUTOLOAD: - disable_plugin_autoload_ = true; + disable_plugin_autoload_ = true; + break; + case 'c': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_cpuprofile_ = true; + break; + case 'o': + profile_filename_ = std::string(optarg); + break; + case 'H': +#ifndef BASE_PROFILER_H_ + AWARN << "gperftools not installed, ignore perf parameters"; +#endif + enable_heapprofile_ = true; + break; + case 'O': + heapprofile_filename_ = std::string(optarg); break; case 'h': DisplayUsage(); diff --git a/cyber/mainboard/module_argument.h b/cyber/mainboard/module_argument.h index 5f2ed9f..ddc1dfa 100644 --- a/cyber/mainboard/module_argument.h +++ b/cyber/mainboard/module_argument.h @@ -47,6 +47,12 @@ class ModuleArgument { const std::string& GetSchedName() const; const std::list& GetDAGConfList() const; const std::list& GetPluginDescriptionList() const; + const bool GetEnableCpuprofile() const { return enable_cpuprofile_; } + const std::string GetProfileFilename() const { return profile_filename_; } + const bool GetEnableHeapprofile() const { return enable_heapprofile_; } + const std::string GetHeapProfileFilename() const { + return heapprofile_filename_; + } const bool& GetDisablePluginsAutoLoad() const; private: @@ -55,6 +61,10 @@ class ModuleArgument { std::string binary_name_; std::string process_group_; std::string sched_name_; + bool enable_cpuprofile_ = false; + std::string profile_filename_; + bool enable_heapprofile_ = false; + std::string heapprofile_filename_; bool disable_plugin_autoload_ = false; }; diff --git a/cyber/message/BUILD b/cyber/message/BUILD index e12d060..f0b690e 100644 --- a/cyber/message/BUILD +++ b/cyber/message/BUILD @@ -1,5 +1,5 @@ load("//tools:cpplint.bzl", "cpplint") -load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_library", "apollo_cc_test", "apollo_cc_binary") +load("//tools:apollo_package.bzl", "apollo_cc_binary", "apollo_cc_library", "apollo_cc_test", "apollo_package") package(default_visibility = ["//visibility:public"]) @@ -15,7 +15,12 @@ apollo_cc_test( apollo_cc_library( name = "cyber_message", + srcs = [ + "protobuf_factory.cc", + ], hdrs = [ + "arena_manager_base.h", + "arena_message_wrapper.h", "message_header.h", "message_traits.h", "protobuf_factory.h", @@ -25,9 +30,6 @@ apollo_cc_library( "raw_message.h", "raw_message_traits.h", ], - srcs = [ - "protobuf_factory.cc", - ], deps = [ "//cyber/common:cyber_common", "//cyber/proto:proto_desc_cc_proto", @@ -67,4 +69,5 @@ apollo_cc_test( ) apollo_package() + cpplint() diff --git a/cyber/message/arena_manager_base.h b/cyber/message/arena_manager_base.h new file mode 100644 index 0000000..aa8209a --- /dev/null +++ b/cyber/message/arena_manager_base.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_MESSAGE_ARENA_MANAGER_BASE_H_ +#define CYBER_MESSAGE_ARENA_MANAGER_BASE_H_ + +#include +#include + +namespace apollo { +namespace cyber { +namespace message { + +class ArenaMessageWrapper; + +class ArenaManagerBase { + public: + ArenaManagerBase() {} + virtual ~ArenaManagerBase() {} + + virtual uint64_t GetBaseAddress(const ArenaMessageWrapper* wrapper) { + return 0; + } + + virtual void* SetMessage(ArenaMessageWrapper* wrapper, + const void* message) = 0; + virtual void* GetMessage(ArenaMessageWrapper* wrapper) = 0; + + std::shared_ptr CreateMessageWrapper() { + return std::make_shared(this); + } + + template + MessageT* SetMessage(ArenaMessageWrapper* wrapper, const MessageT& message) { + void* msg = SetMessage(wrapper, reinterpret_cast(&message)); + return reinterpret_cast(msg); + } + + template + MessageT* GetMessage(ArenaMessageWrapper* wrapper) { + void* msg = GetMessage(wrapper); + return reinterpret_cast(msg); + } +}; + +} // namespace message +} // namespace cyber +} // namespace apollo + +#endif diff --git a/cyber/message/arena_message_wrapper.h b/cyber/message/arena_message_wrapper.h new file mode 100644 index 0000000..92e573a --- /dev/null +++ b/cyber/message/arena_message_wrapper.h @@ -0,0 +1,145 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_MESSAGE_ARENA_MESSAGE_WRAPPER_H_ +#define CYBER_MESSAGE_ARENA_MESSAGE_WRAPPER_H_ + +#include +#include +#include + +#include "cyber/message/arena_manager_base.h" + +namespace apollo { +namespace cyber { +namespace message { + +union ArenaMessageWrapperMeta { + struct { + uint64_t version_; + uint64_t addr_offset_; + } struct_; + uint8_t bytes_[128]; +}; + +union ArenaMessageWrapperExtended { + uint8_t bytes_[256]; +}; + +union ArenaMessageWrapperDataStruct { + struct { + union ArenaMessageWrapperMeta meta_; + union ArenaMessageWrapperExtended extended_; + } struct_; + uint8_t bytes_[1024]; +}; + +class ArenaMessageWrapper { + public: + static const uint64_t kDefaultVersion = 1L; + + ArenaMessageWrapper() : arena_manager_(nullptr) { + data_.struct_.meta_.struct_.version_ = kDefaultVersion; + data_.struct_.meta_.struct_.addr_offset_ = 0; + } + + explicit ArenaMessageWrapper(ArenaManagerBase* arena_manager) + : arena_manager_(arena_manager) { + data_.struct_.meta_.struct_.version_ = kDefaultVersion; + data_.struct_.meta_.struct_.addr_offset_ = 0; + } + + virtual ~ArenaMessageWrapper() {} + + void SetVersion(uint64_t version) { + data_.struct_.meta_.struct_.version_ = version; + } + uint64_t GetVersion() const { return data_.struct_.meta_.struct_.version_; } + + uint64_t GetMessageAddress() const { + return arena_manager_->GetBaseAddress(this) + + data_.struct_.meta_.struct_.addr_offset_; + } + + void* GetData() { return reinterpret_cast(data_.bytes_); } + + bool FillMeta(void* meta, uint64_t size) { + if (size > 128) { + return false; + } + memcpy(&data_.struct_.meta_, meta, size); + return true; + } + + ArenaMessageWrapperMeta* GetMeta() { + return reinterpret_cast( + data_.struct_.meta_.bytes_); + } + + bool FillExtended(void* extended, uint64_t size) { + if (size > 256) { + return false; + } + memcpy(&data_.struct_.extended_, extended, size); + return true; + } + + template + T* GetExtended() { + return reinterpret_cast(data_.struct_.extended_.bytes_); + } + + template + MessageT* GetMessage() { + // uint64_t base_address = + // reinterpret_cast(arena_manager_->GetBaseAddress()); + // uint64_t message_address = base_address + data_.struct_.addr_offset_; + // return std::shared_ptr( + // reinterpret_cast(GetMessageAddress())); + auto msg_ptr = arena_manager_->GetMessage(this); + return msg_ptr; + } + + template + MessageT* SetMessage(const MessageT& message) { + auto msg_ptr = arena_manager_->SetMessage(this, message); + return msg_ptr; + } + + private: + // union { + // struct { + // union { + // uint64_t version_; + // uint64_t addr_offset_; + // uint8_t bytes_[128]; + // } meta_; + // union { + // uint8_t bytes_[256]; + // } extended_; + // } struct_; + // uint8_t bytes_[1024]; + // } data_; + ArenaMessageWrapperDataStruct data_; + // message holder + std::shared_ptr message_; + ArenaManagerBase* arena_manager_; +}; + +} // namespace message +} // namespace cyber +} // namespace apollo + +#endif diff --git a/cyber/message/message_traits.h b/cyber/message/message_traits.h index 506203b..d5edc2f 100644 --- a/cyber/message/message_traits.h +++ b/cyber/message/message_traits.h @@ -18,9 +18,11 @@ #define CYBER_MESSAGE_MESSAGE_TRAITS_H_ #include +#include #include "cyber/base/macros.h" #include "cyber/common/log.h" +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/message_header.h" #include "cyber/message/protobuf_traits.h" #include "cyber/message/py_message_traits.h" @@ -40,6 +42,9 @@ DEFINE_TYPE_TRAIT(HasSerializeToString, SerializeToString) DEFINE_TYPE_TRAIT(HasParseFromString, ParseFromString) DEFINE_TYPE_TRAIT(HasSerializeToArray, SerializeToArray) DEFINE_TYPE_TRAIT(HasParseFromArray, ParseFromArray) +DEFINE_TYPE_TRAIT(HasSerializeToArenaMessageWrapper, + SerializeToArenaMessageWrapper) +DEFINE_TYPE_TRAIT(HasParseFromArenaMessageWrapper, ParseFromArenaMessageWrapper) template class HasSerializer { @@ -141,6 +146,26 @@ int FullByteSize(const T& message) { return content_size + static_cast(sizeof(MessageHeader)); } +template +typename std::enable_if::value, bool>::type +ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, T* message, + T** message_ptr) { + return message->ParseFromArenaMessageWrapper(wrapper, message_ptr); +} + +template ::value && + !std::is_base_of::value, + bool>::type = 0> +bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, T* message, + T** message_ptr) { + (void)wrapper; + (void)message; + (void)message_ptr; + return false; +} + template typename std::enable_if::value, bool>::type ParseFromArray( const void* data, int size, T* message) { @@ -184,6 +209,27 @@ typename std::enable_if::value, bool>::type ParseFromHC( return false; } +template +typename std::enable_if::value, bool>::type +SerializeToArenaMessageWrapper(const T& message, ArenaMessageWrapper* wrapper, + T** message_ptr) { + return message->SerializeToArenaMessageWrapper(wrapper, message_ptr); +} + +template ::value && + !std::is_base_of::value, + bool>::type = 0> +bool SerializeToArenaMessageWrapper(const T& message, + ArenaMessageWrapper* wrapper, + T** message_ptr) { + (void)message; + (void)wrapper; + (void)message_ptr; + return false; +} + template typename std::enable_if::value, bool>::type SerializeToArray(const T& message, void* data, int size) { diff --git a/cyber/message/protobuf_traits.h b/cyber/message/protobuf_traits.h index 0a4317a..a03f690 100644 --- a/cyber/message/protobuf_traits.h +++ b/cyber/message/protobuf_traits.h @@ -21,6 +21,7 @@ #include #include +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/protobuf_factory.h" namespace apollo { @@ -69,6 +70,28 @@ bool RegisterMessage(const MessageT& message) { return ProtobufFactory::Instance()->RegisterMessage(message); } +template ::value, + bool>::type = true> +bool SerializeToArenaMessageWrapper(const MessageT& message, + ArenaMessageWrapper* wrapper, + MessageT** message_ptr) { + *message_ptr = wrapper->SetMessage(message); + return true; +} + +template ::value, + bool>::type = true> +bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, + MessageT* message, MessageT** message_ptr) { + *message_ptr = wrapper->GetMessage(); + // message->CopyFrom(*message_ptr); + return true; +} + } // namespace message } // namespace cyber } // namespace apollo diff --git a/cyber/message/raw_message.h b/cyber/message/raw_message.h index 85accc7..bc94866 100644 --- a/cyber/message/raw_message.h +++ b/cyber/message/raw_message.h @@ -22,6 +22,7 @@ #include #include +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/protobuf_factory.h" namespace apollo { @@ -82,6 +83,10 @@ struct RawMessage { return true; } + // bool SerializeToArenaMessageWrapper(ArenaMessageWrapper *wrapper) const { + // return true; + // } + bool ParseFromArray(const void *data, int size) { if (data == nullptr || size <= 0) { return false; @@ -96,6 +101,10 @@ struct RawMessage { return true; } + // bool ParseFromArenaMessageWrapper(const ArenaMessageWrapper &wrapper) { + // return true; + // } + int ByteSize() const { return static_cast(message.size()); } static std::string TypeName() { return "apollo.cyber.message.RawMessage"; } diff --git a/cyber/message/raw_message_traits.h b/cyber/message/raw_message_traits.h index 70e868f..5d4b21f 100644 --- a/cyber/message/raw_message_traits.h +++ b/cyber/message/raw_message_traits.h @@ -21,6 +21,7 @@ #include #include +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/raw_message.h" namespace apollo { @@ -38,6 +39,16 @@ inline bool ParseFromArray(const void* data, int size, RawMessage* message) { inline int ByteSize(const RawMessage& message) { return message.ByteSize(); } +inline bool SerializeToArenaMessageWrapper(const RawMessage& message, + ArenaMessageWrapper* wrapper) { + return false; +} + +inline bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, + RawMessage* message) { + return false; +} + } // namespace message } // namespace cyber } // namespace apollo diff --git a/cyber/node/BUILD b/cyber/node/BUILD index 366d6b0..3d7bffc 100644 --- a/cyber/node/BUILD +++ b/cyber/node/BUILD @@ -17,6 +17,7 @@ apollo_cc_library( "writer.h", "writer_base.h", ], + linkopts = ["-lbvar"], deps = [ "//cyber/blocker:cyber_blocker", "//cyber/common:cyber_common", @@ -32,6 +33,7 @@ apollo_cc_library( "//cyber/transport:cyber_transport", "//cyber/event:cyber_event", "//cyber/proto:role_attributes_cc_proto", + # "//cyber/statistics:apollo_statistics", ], ) diff --git a/cyber/node/node.cc b/cyber/node/node.cc index b524121..0c974ca 100644 --- a/cyber/node/node.cc +++ b/cyber/node/node.cc @@ -16,14 +16,9 @@ #include "cyber/node/node.h" -#include "cyber/common/global_data.h" -#include "cyber/time/time.h" - namespace apollo { namespace cyber { -using proto::RoleType; - Node::Node(const std::string& node_name, const std::string& name_space) : node_name_(node_name), name_space_(name_space) { node_channel_impl_.reset(new NodeChannelImpl(node_name)); diff --git a/cyber/node/node.h b/cyber/node/node.h index 87a3def..b03844b 100644 --- a/cyber/node/node.h +++ b/cyber/node/node.h @@ -39,14 +39,14 @@ class TimerComponent; * A module can have different types of communication by defining * read/write and/or service/client in a node. * @warning Duplicate name is not allowed in topo objects, such as node, - * reader/writer, service/clinet in the topo. + * reader/writer, service/client in the topo. */ class Node { public: template friend class Component; friend class TimerComponent; - friend bool Init(const char*); + friend bool Init(const char*, const std::string&); friend std::unique_ptr CreateNode(const std::string&, const std::string&); virtual ~Node(); diff --git a/cyber/node/reader.h b/cyber/node/reader.h index 83f4fb5..5c098d0 100644 --- a/cyber/node/reader.h +++ b/cyber/node/reader.h @@ -35,6 +35,7 @@ #include "cyber/node/reader_base.h" #include "cyber/scheduler/scheduler_factory.h" #include "cyber/service_discovery/topology_manager.h" +#include "cyber/statistics/statistics.h" #include "cyber/time/time.h" #include "cyber/transport/transport.h" @@ -259,11 +260,34 @@ bool Reader::Init() { if (init_.exchange(true)) { return true; } + auto statistics_center = statistics::Statistics::Instance(); + if (!statistics_center->RegisterChanVar(role_attr_)) { + AWARN << "Failed to register reader var!"; + } std::function&)> func; if (reader_func_ != nullptr) { func = [this](const std::shared_ptr& msg) { + uint64_t process_start_time; + uint64_t proc_done_time; + uint64_t proc_start_time; + this->Enqueue(msg); this->reader_func_(msg); + // sampling proc latency in microsecond + proc_done_time = Time::Now().ToMicrosecond(); + proc_start_time = + static_cast(latest_recv_time_sec_ * 1000000UL); + + statistics::Statistics::Instance()->SamplingProcLatency( + this->role_attr_, (proc_done_time - proc_start_time)); + if (statistics::Statistics::Instance()->GetProcStatus( + this->role_attr_, &process_start_time)) { + auto cyber_latency = proc_start_time - process_start_time; + if (process_start_time > 0 && cyber_latency > 0) { + statistics::Statistics::Instance()->SamplingCyberLatency( + this->role_attr_, cyber_latency); + } + } }; } else { func = [this](const std::shared_ptr& msg) { this->Enqueue(msg); }; diff --git a/cyber/node/reader_base.h b/cyber/node/reader_base.h index 57e393f..ae5caaf 100644 --- a/cyber/node/reader_base.h +++ b/cyber/node/reader_base.h @@ -158,7 +158,7 @@ class ReaderBase { /** * @brief One Channel is related to one Receiver. * ReceiverManager is in charge of attaching one Receiver to its responding - * Channel. We pass a DataDispatche's callback func to this Receiver so when a + * Channel. We pass a DataDispatcher's callback func to this Receiver so when a * message is received, it will be push to the `ChannelBuffer`, and * `DataVisitor` will `Fetch` data and pass to `Reader`'s callback func * diff --git a/cyber/node/writer.h b/cyber/node/writer.h index b4a7a69..aad5f25 100644 --- a/cyber/node/writer.h +++ b/cyber/node/writer.h @@ -100,6 +100,12 @@ class Writer : public WriterBase { */ void GetReaders(std::vector* readers) override; + /** + * @brief Acquire message instance to send + * + */ + std::shared_ptr AcquireMessage(); + private: void JoinTheTopology(); void LeaveTheTopology(); @@ -231,6 +237,23 @@ void Writer::GetReaders(std::vector* readers) { channel_manager_->GetReadersOfChannel(role_attr_.channel_name(), readers); } +template +std::shared_ptr Writer::AcquireMessage() { + if (!WriterBase::IsInit()) { + AERROR << "Please Acquire message after init writer!"; + auto m = std::make_shared(); + return m; + } + + std::shared_ptr m(nullptr); + if (transmitter_->AcquireMessage(m)) { + return m; + } else { + m = std::make_shared(); + return m; + } +} + } // namespace cyber } // namespace apollo diff --git a/cyber/node/writer_base.h b/cyber/node/writer_base.h index 6e2fa22..389cb82 100644 --- a/cyber/node/writer_base.h +++ b/cyber/node/writer_base.h @@ -83,6 +83,13 @@ class WriterBase { return role_attr_.channel_name(); } + /** + * @brief Get Writer's Channel id + * + * @return const uint64_t& const reference to the channel id + */ + const uint64_t GetChannelId() const { return role_attr_.channel_id(); } + /** * @brief Is Writer initialized? * diff --git a/cyber/parameter/BUILD b/cyber/parameter/BUILD index d4868ac..8639b90 100644 --- a/cyber/parameter/BUILD +++ b/cyber/parameter/BUILD @@ -21,7 +21,7 @@ apollo_cc_library( "//cyber/proto:parameter_cc_proto", "//cyber/node:cyber_node", "//cyber/service:cyber_service", - "@fastrtps", + "@fastdds", ], ) diff --git a/cyber/parameter/parameter_client.h b/cyber/parameter/parameter_client.h index c0345f3..5c29701 100644 --- a/cyber/parameter/parameter_client.h +++ b/cyber/parameter/parameter_client.h @@ -69,7 +69,7 @@ class ParameterClient { * @brief Set the Parameter object * * @param parameter parameter to be set - * @return true set parameter succues + * @return true set parameter success * @return false 1. call service timeout * 2. parameter not exists * The corresponding log will be recorded at the same time diff --git a/cyber/proto/BUILD b/cyber/proto/BUILD index 118fb16..346e690 100644 --- a/cyber/proto/BUILD +++ b/cyber/proto/BUILD @@ -47,10 +47,10 @@ proto_library( name = "cyber_conf_proto", srcs = ["cyber_conf.proto"], deps = [ + ":perf_conf_proto", + ":run_mode_conf_proto", ":scheduler_conf_proto", ":transport_conf_proto", - ":run_mode_conf_proto", - ":perf_conf_proto", ], ) @@ -74,12 +74,17 @@ proto_library( srcs = ["unit_test.proto"], ) +proto_library( + name = "simple_proto", + srcs = ["simple.proto"], +) + proto_library( name = "scheduler_conf_proto", srcs = ["scheduler_conf.proto"], deps = [ - ":classic_conf_proto", ":choreography_conf_proto", + ":classic_conf_proto", ], ) diff --git a/cyber/proto/simple.proto b/cyber/proto/simple.proto new file mode 100644 index 0000000..5cd64a0 --- /dev/null +++ b/cyber/proto/simple.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; + +package apollo.cyber.proto; + +message SimpleMessage { + optional int32 integer = 1; + optional string text = 2; +} + +message SimpleRepeatedMessage { + repeated SimpleMessage message = 1; +} diff --git a/cyber/proto/transport_conf.proto b/cyber/proto/transport_conf.proto index f7f34b2..b6db252 100644 --- a/cyber/proto/transport_conf.proto +++ b/cyber/proto/transport_conf.proto @@ -14,10 +14,25 @@ message ShmMulticastLocator { optional uint32 port = 2; }; +message ArenaChannelConf { + optional string channel_name = 1; + // the acutal arena segment size is equal with max_msg_size * max_pool_size + meta, + // so max_msg_size * max_pool_size should be less than the limit of ArenaAddressAllocator: + // 2^31 - 128 * 1024 * 1024, which is hardcode in the underlying implementation + optional uint64 max_msg_size = 2 [default = 33554432]; + optional uint64 max_pool_size = 3 [default = 32]; + optional uint64 shared_buffer_size = 4 [default = 0]; +}; + +message ArenaShmConf { + repeated ArenaChannelConf arena_channel_conf = 1; +}; + message ShmConf { optional string notifier_type = 1; optional string shm_type = 2; optional ShmMulticastLocator shm_locator = 3; + optional ArenaShmConf arena_shm_conf = 4; }; message RtpsParticipantAttr { diff --git a/cyber/python/cyber_py3/cyber.py b/cyber/python/cyber_py3/cyber.py index 67912c2..466e414 100644 --- a/cyber/python/cyber_py3/cyber.py +++ b/cyber/python/cyber_py3/cyber.py @@ -35,7 +35,7 @@ APOLLO_DISTRIBUTION_HOME = os.environ.get( 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') -if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): +if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): wrapper_lib_path = os.path.join( APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") diff --git a/cyber/python/cyber_py3/cyber_time.py b/cyber/python/cyber_py3/cyber_time.py index 303fb02..ba0f93c 100644 --- a/cyber/python/cyber_py3/cyber_time.py +++ b/cyber/python/cyber_py3/cyber_time.py @@ -25,7 +25,7 @@ APOLLO_DISTRIBUTION_HOME = os.environ.get( 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') -if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): +if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): wrapper_lib_path = os.path.join( APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") diff --git a/cyber/python/cyber_py3/cyber_timer.py b/cyber/python/cyber_py3/cyber_timer.py index 5c1911a..3123843 100644 --- a/cyber/python/cyber_py3/cyber_timer.py +++ b/cyber/python/cyber_py3/cyber_timer.py @@ -30,7 +30,7 @@ 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') # init vars -if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): +if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): wrapper_lib_path = os.path.join( APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") diff --git a/cyber/python/cyber_py3/parameter.py b/cyber/python/cyber_py3/parameter.py index 03a91bc..60ef028 100644 --- a/cyber/python/cyber_py3/parameter.py +++ b/cyber/python/cyber_py3/parameter.py @@ -29,7 +29,7 @@ APOLLO_DISTRIBUTION_HOME = os.environ.get( 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') -if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): +if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): wrapper_lib_path = os.path.join( APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") diff --git a/cyber/python/cyber_py3/record.py b/cyber/python/cyber_py3/record.py index de5cd42..31d820e 100644 --- a/cyber/python/cyber_py3/record.py +++ b/cyber/python/cyber_py3/record.py @@ -30,7 +30,7 @@ APOLLO_DISTRIBUTION_HOME = os.environ.get( 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') -if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): +if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): wrapper_lib_path = os.path.join( APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") diff --git a/cyber/python/cyber_py3/test/BUILD b/cyber/python/cyber_py3/test/BUILD index 22a15f1..f519a52 100644 --- a/cyber/python/cyber_py3/test/BUILD +++ b/cyber/python/cyber_py3/test/BUILD @@ -16,20 +16,26 @@ py_test( name = "init_test", timeout = "short", srcs = ["init_test.py"], + imports = [ + "../../internal", + ], deps = [ "//cyber/python/cyber_py3:cyber", ], ) -# py_test( -# name = "cyber_test", -# timeout = "short", -# srcs = ["cyber_test.py"], -# deps = [ -# "//cyber/python/cyber_py3:cyber", -# "//cyber/proto:simple_py_pb2", -# ], -# ) +py_test( + name = "cyber_test", + timeout = "short", + srcs = ["cyber_test.py"], + imports = [ + "../../internal", + ], + deps = [ + "//cyber/proto:simple_py_pb2", + "//cyber/python/cyber_py3:cyber", + ], +) # FIXME(all): parameter_test seems to run forever # py_test( # name = "parameter_test", @@ -45,6 +51,9 @@ py_test( name = "cyber_time_test", timeout = "short", srcs = ["cyber_time_test.py"], + imports = [ + "../../internal", + ], deps = [ "//cyber/python/cyber_py3:cyber", "//cyber/python/cyber_py3:cyber_time", @@ -62,4 +71,4 @@ py_test( # ], #) -apollo_package() \ No newline at end of file +apollo_package() diff --git a/cyber/python/internal/BUILD b/cyber/python/internal/BUILD index e5ee8e0..6b95e3b 100644 --- a/cyber/python/internal/BUILD +++ b/cyber/python/internal/BUILD @@ -86,7 +86,7 @@ apollo_cc_library( hdrs = ["py_time.h"], deps = [ "//cyber", - "@fastrtps", + "@fastdds", "@local_config_python//:python_headers", "@local_config_python//:python_lib", ], diff --git a/cyber/python/internal/py_cyber.cc b/cyber/python/internal/py_cyber.cc index a8dca54..3b0982c 100644 --- a/cyber/python/internal/py_cyber.cc +++ b/cyber/python/internal/py_cyber.cc @@ -89,7 +89,8 @@ template T PyObjectToPtr(PyObject *pyobj, const std::string &type_ptr) { T obj_ptr = (T)PyCapsule_GetPointer(pyobj, type_ptr.c_str()); if (obj_ptr == nullptr) { - AERROR << "PyObjectToPtr failed,type->" << type_ptr << "pyobj: " << pyobj; + AERROR << "PyObjectToPtr failed,type->" << type_ptr << " " + << "pyobj: " << pyobj; } return obj_ptr; } @@ -139,11 +140,12 @@ PyObject *cyber_delete_PyWriter(PyObject *self, PyObject *args) { PyObject *cyber_PyWriter_write(PyObject *self, PyObject *args) { PyObject *pyobj_writer = nullptr; - char *data = nullptr; - Py_ssize_t len = 0; - if (!PyArg_ParseTuple(args, const_cast("Os#:cyber_PyWriter_write"), - &pyobj_writer, &data, &len)) { + Py_buffer buffer; + // Py_ssize_t len = 0; + if (!PyArg_ParseTuple(args, const_cast("Oy*:cyber_PyWriter_write"), + &pyobj_writer, &buffer)) { AERROR << "cyber_PyWriter_write:cyber_PyWriter_write failed!"; + PyBuffer_Release(&buffer); return PyInt_FromLong(1); } @@ -152,11 +154,14 @@ PyObject *cyber_PyWriter_write(PyObject *self, PyObject *args) { if (nullptr == writer) { AERROR << "cyber_PyWriter_write:writer ptr is null!"; + PyBuffer_Release(&buffer); return PyInt_FromLong(1); } - std::string data_str(data, len); + std::string data_str( + const_cast(static_cast(buffer.buf)), buffer.len); int ret = writer->write(data_str); + PyBuffer_Release(&buffer); return PyInt_FromLong(ret); } @@ -297,11 +302,12 @@ PyObject *cyber_delete_PyClient(PyObject *self, PyObject *args) { PyObject *cyber_PyClient_send_request(PyObject *self, PyObject *args) { PyObject *pyobj_client = nullptr; - char *data = nullptr; - Py_ssize_t len = 0; - if (!PyArg_ParseTuple(args, const_cast("Os#:PyClient_send_request"), - &pyobj_client, &data, &len)) { + Py_buffer buffer; + // Py_ssize_t len = 0; + if (!PyArg_ParseTuple(args, const_cast("Oy*:PyClient_send_request"), + &pyobj_client, &buffer)) { AERROR << "cyber_PyClient_send_request:PyArg_ParseTuple failed!"; + PyBuffer_Release(&buffer); return PYOBJECT_NULL_STRING; } @@ -310,14 +316,17 @@ PyObject *cyber_PyClient_send_request(PyObject *self, PyObject *args) { if (nullptr == client) { AERROR << "cyber_PyClient_send_request:client ptr is null!"; + PyBuffer_Release(&buffer); return PYOBJECT_NULL_STRING; } - std::string data_str(data, len); + std::string data_str( + const_cast(static_cast(buffer.buf)), buffer.len); ADEBUG << "c++:PyClient_send_request data->[ " << data_str << "]"; const std::string response_str = client->send_request((std::string const &)data_str); ADEBUG << "c++:response data->[ " << response_str << "]"; + PyBuffer_Release(&buffer); return C_STR_TO_PY_BYTES(response_str); } @@ -406,11 +415,12 @@ PyObject *cyber_PyService_read(PyObject *self, PyObject *args) { PyObject *cyber_PyService_write(PyObject *self, PyObject *args) { PyObject *pyobj_service = nullptr; - char *data = nullptr; - Py_ssize_t len = 0; - if (!PyArg_ParseTuple(args, const_cast("Os#:cyber_PyService_write"), - &pyobj_service, &data, &len)) { + Py_buffer buffer; + // Py_ssize_t len = 0; + if (!PyArg_ParseTuple(args, const_cast("Oy*:cyber_PyService_write"), + &pyobj_service, &buffer)) { AERROR << "cyber_PyService_write:PyArg_ParseTuple failed!"; + PyBuffer_Release(&buffer); return PyInt_FromLong(1); } @@ -419,12 +429,15 @@ PyObject *cyber_PyService_write(PyObject *self, PyObject *args) { if (nullptr == service) { AERROR << "cyber_PyService_write:writer ptr is null!"; + PyBuffer_Release(&buffer); return PyInt_FromLong(1); } - std::string data_str(data, len); + std::string data_str( + const_cast(static_cast(buffer.buf)), buffer.len); ADEBUG << "c++:PyService_write data->[ " << data_str << "]"; int ret = service->write((std::string const &)data_str); + PyBuffer_Release(&buffer); return PyInt_FromLong(ret); } @@ -594,24 +607,29 @@ PyObject *cyber_PyNode_shutdown(PyObject *self, PyObject *args) { PyObject *cyber_PyNode_register_message(PyObject *self, PyObject *args) { PyObject *pyobj_node = nullptr; - char *desc = nullptr; - int len = 0; + Py_buffer buffer; + // int len = 0; if (!PyArg_ParseTuple(args, - const_cast("Os#:cyber_PyNode_register_message"), - &pyobj_node, &desc, &len)) { + const_cast("Oy*:cyber_PyNode_register_message"), + &pyobj_node, &buffer)) { AERROR << "cyber_PyNode_register_message: failed!"; Py_INCREF(Py_None); + PyBuffer_Release(&buffer); return Py_None; } + std::string desc_str( + const_cast(static_cast(buffer.buf)), buffer.len); PyNode *node = PyObjectToPtr(pyobj_node, "apollo_cyber_pynode"); if (nullptr == node) { - AERROR << "cyber_PyNode_register_message:node ptr is null! desc->" << desc; + AERROR << "cyber_PyNode_register_message:node ptr is null! desc->" + << desc_str; Py_INCREF(Py_None); + PyBuffer_Release(&buffer); return Py_None; } - std::string desc_str(desc, len); node->register_message((std::string const &)desc_str); Py_INCREF(Py_None); + PyBuffer_Release(&buffer); return Py_None; } diff --git a/cyber/python/internal/py_cyber.h b/cyber/python/internal/py_cyber.h index 3f0d750..b1cca07 100644 --- a/cyber/python/internal/py_cyber.h +++ b/cyber/python/internal/py_cyber.h @@ -16,6 +16,7 @@ #ifndef CYBER_PYTHON_INTERNAL_PY_CYBER_H_ #define CYBER_PYTHON_INTERNAL_PY_CYBER_H_ +#define PY_SSIZE_T_CLEAN #include diff --git a/cyber/record/file/record_file_writer.cc b/cyber/record/file/record_file_writer.cc index 1f0d80d..3f53273 100644 --- a/cyber/record/file/record_file_writer.cc +++ b/cyber/record/file/record_file_writer.cc @@ -222,7 +222,7 @@ bool RecordFileWriter::WriteMessage(const proto::SingleMessage& message) { header_.chunk_interval()) { need_flush = true; } - if (header_.chunk_raw_size() > 0 && + if (!in_writing_ && header_.chunk_raw_size() > 0 && chunk_active_->header_.raw_size() > header_.chunk_raw_size()) { need_flush = true; } @@ -248,9 +248,11 @@ void RecordFileWriter::Flush() { if (chunk_flush_->empty()) { continue; } + in_writing_ = true; if (!WriteChunk(chunk_flush_->header_, *(chunk_flush_->body_.get()))) { AERROR << "Write chunk fail."; } + in_writing_ = false; chunk_flush_->clear(); } } diff --git a/cyber/record/file/record_file_writer.h b/cyber/record/file/record_file_writer.h index 0a9481c..2f95f91 100644 --- a/cyber/record/file/record_file_writer.h +++ b/cyber/record/file/record_file_writer.h @@ -93,6 +93,7 @@ class RecordFileWriter : public RecordFileBase { bool WriteIndex(); void Flush(); std::atomic_bool is_writing_; + std::atomic_bool in_writing_{false}; std::unique_ptr chunk_active_ = nullptr; std::unique_ptr chunk_flush_ = nullptr; std::shared_ptr flush_thread_ = nullptr; diff --git a/cyber/record/header_builder.h b/cyber/record/header_builder.h index 6a38350..3b89cfe 100644 --- a/cyber/record/header_builder.h +++ b/cyber/record/header_builder.h @@ -66,7 +66,7 @@ class HeaderBuilder { proto::CompressType::COMPRESS_NONE; static const uint64_t CHUNK_INTERVAL_ = 20 * 1000 * 1000 * 1000ULL; // 20s static const uint64_t SEGMENT_INTERVAL_ = 60 * 1000 * 1000 * 1000ULL; // 60s - static const uint64_t CHUNK_RAW_SIZE_ = 1 * 1024 * 1024ULL; // 1MB + static const uint64_t CHUNK_RAW_SIZE_ = 16 * 1024 * 1024ULL; // 16MB static const uint64_t SEGMENT_RAW_SIZE_ = 2048 * 1024 * 1024ULL; // 2GB }; diff --git a/cyber/ros_bridge/BUILD b/cyber/ros_bridge/BUILD new file mode 100644 index 0000000..3378128 --- /dev/null +++ b/cyber/ros_bridge/BUILD @@ -0,0 +1,59 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_binary", "apollo_package") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_data", + srcs = glob([ + "conf/**", + ]), +) + +apollo_cc_library( + name = "converter_base", + hdrs = [ + "converter_base/message_converter.h", + "converter_base/converter_base.h", + "converter_base/convert_ros_quadruple.h", + "converter_base/convert_ros_triple.h", + "converter_base/convert_ros_double.h", + "converter_base/convert_ros_single.h", + "converter_base/convert_apollo_quadruple.h", + "converter_base/convert_apollo_triple.h", + "converter_base/convert_apollo_double.h", + "converter_base/convert_apollo_single.h", + "converter_base/converter_interface.h", + + "common/bridge_argument.h", + "common/ros_bridge_gflags.h", + "common/utils.h", + "common/macros.h", + ], + srcs = [ + "common/ros_bridge_gflags.cc", + "common/bridge_argument.cc", + ], + deps = [ + "//cyber", + "//cyber/ros_bridge/proto:converter_conf_proto", + "@com_github_gflags_gflags//:gflags", + "@ros", + ], +) + +apollo_cc_binary( + name = "ros_bridge", + srcs = ["ros_bridge.cc"], + linkopts = [ + "-ltcmalloc", + "-lprofiler", + ], + deps = [ + ":converter_base", + "//cyber/ros_bridge/proto:ros_bridge_conf_proto", + ] +) + +apollo_package() +cpplint() diff --git a/cyber/ros_bridge/common/bridge_argument.cc b/cyber/ros_bridge/common/bridge_argument.cc new file mode 100644 index 0000000..75c35fa --- /dev/null +++ b/cyber/ros_bridge/common/bridge_argument.cc @@ -0,0 +1,112 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/common/bridge_argument.h" + +#include +#include + +namespace apollo { +namespace cyber { + +void BridgeArgument::DisplayUsage() { + AINFO << "Usage: \n " << binary_name_ << " [OPTION]...\n" + << "Description: \n" + << " -h, --help: help information \n" + << " -c, --cpuprofile: enable gperftools cpu profile\n" + << " -o, --profile_filename=filename: the filename to dump the " + "profile to, default value is ${binary_name}_cpu.prof. Only work " + "with -c option\n" + << " -H, --heapprofile: enable gperftools heap profile\n" + << " -O, --heapprofile_filename=filename: the filename to dump the " + "profile to, default value is ${binary_name}_mem.prof. Only work " + "with -H option\n" + << "Example:\n" + << " " << binary_name_ << " -h\n" + << " " << binary_name_ << " -c -H "; +} + +void BridgeArgument::ParseArgument(const int argc, char* const argv[]) { + binary_name_ = std::string(basename(argv[0])); + GetOptions(argc, argv); + + if (enable_cpuprofile_ && profile_filename_.empty()) { + profile_filename_ = binary_name_ + std::string("_cpu.prof"); + } + + if (enable_heapprofile_ && heapprofile_filename_.empty()) { + heapprofile_filename_ = binary_name_ + std::string("_mem.prof"); + } + + AINFO << "binary_name_ is " << binary_name_; +} + +void BridgeArgument::GetOptions(const int argc, char* const argv[]) { + opterr = 0; // extern int opterr + int long_index = 0; + const std::string short_opts = "hco:HO:"; + static const struct option long_opts[] = { + {"help", no_argument, nullptr, 'h'}, + {"cpuprofile", no_argument, nullptr, 'c'}, + {"profile_filename", required_argument, nullptr, 'o'}, + {"heapprofile", no_argument, nullptr, 'H'}, + {"heapprofile_filename", required_argument, nullptr, 'O'}, + {NULL, no_argument, nullptr, 0}}; + + // log command for info + std::string cmd(""); + for (int i = 0; i < argc; ++i) { + cmd += argv[i]; + cmd += " "; + } + AINFO << "command: " << cmd; + + do { + int opt = + getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); + if (opt == -1) { + break; + } + switch (opt) { + case 'c': + enable_cpuprofile_ = true; + break; + case 'o': + profile_filename_ = std::string(optarg); + break; + case 'H': + enable_heapprofile_ = true; + break; + case 'O': + heapprofile_filename_ = std::string(optarg); + break; + case 'h': + DisplayUsage(); + exit(0); + default: + break; + } + } while (true); + + if (optind < argc) { + AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; + DisplayUsage(); + exit(1); + } +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/common/bridge_argument.h b/cyber/ros_bridge/common/bridge_argument.h new file mode 100644 index 0000000..482a812 --- /dev/null +++ b/cyber/ros_bridge/common/bridge_argument.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * Copyright 2018 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include + +#include "cyber/common/global_data.h" +#include "cyber/common/log.h" +#include "cyber/common/types.h" + +namespace apollo { +namespace cyber { + +class BridgeArgument { + public: + BridgeArgument() = default; + virtual ~BridgeArgument() = default; + void DisplayUsage(); + void ParseArgument(int argc, char* const argv[]); + void GetOptions(const int argc, char* const argv[]); + const std::string& GetBinaryName() const; + const bool GetEnableCpuprofile() const { return enable_cpuprofile_; } + const std::string GetProfileFilename() const { return profile_filename_; } + const bool GetEnableHeapprofile() const { return enable_heapprofile_; } + const std::string GetHeapProfileFilename() const { + return heapprofile_filename_; + } + + private: + std::string binary_name_; + bool enable_cpuprofile_ = false; + std::string profile_filename_; + bool enable_heapprofile_ = false; + std::string heapprofile_filename_; +}; + +inline const std::string& BridgeArgument::GetBinaryName() const { + return binary_name_; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/common/macros.h b/cyber/ros_bridge/common/macros.h new file mode 100644 index 0000000..feccf11 --- /dev/null +++ b/cyber/ros_bridge/common/macros.h @@ -0,0 +1,26 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef ROS_BRIDGE_MACROS_H_ +#define ROS_BRIDGE_MACROS_H_ + +// replacement macro for eprosima namespace to eprosima_wrap +// for adapting different version fastdds on a single process +#ifndef eprosima +#define eprosima eprosima_wrap +#endif + +#endif // ROS_BRIDGE_MACROS_H_ diff --git a/cyber/ros_bridge/common/ros_bridge_gflags.cc b/cyber/ros_bridge/common/ros_bridge_gflags.cc new file mode 100644 index 0000000..aeb32e7 --- /dev/null +++ b/cyber/ros_bridge/common/ros_bridge_gflags.cc @@ -0,0 +1,32 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +/** + * @file ros_bridge_gflags.h + * @brief The gflags used by ros bridge binary + */ + +#include "cyber/ros_bridge/common/ros_bridge_gflags.h" + +namespace apollo { +namespace cyber { + +// config path +DEFINE_string(bridge_conf_path, + "ros_bridge/conf/ros_bridge_conf.pb.txt", "ros config file path"); + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/common/ros_bridge_gflags.h b/cyber/ros_bridge/common/ros_bridge_gflags.h new file mode 100644 index 0000000..6efd55f --- /dev/null +++ b/cyber/ros_bridge/common/ros_bridge_gflags.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +/** + * @file ros_bridge_gflags.h + * @brief The gflags used by ros bridge binary + */ + +#pragma once + +#include "gflags/gflags.h" + +namespace apollo { +namespace cyber { + +// config path +DECLARE_string(bridge_conf_path); + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/common/utils.h b/cyber/ros_bridge/common/utils.h new file mode 100644 index 0000000..5ee9df8 --- /dev/null +++ b/cyber/ros_bridge/common/utils.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include + +namespace apollo { +namespace cyber { + +std::string GetFullConverterClassName(const std::string& class_name) { + static const std::string kNameSpace = "apollo::cyber::"; + // If the class name already has namespace in it, do nothing. + if (class_name.find("::") != std::string::npos) { + return class_name; + } + return kNameSpace + class_name; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt b/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt new file mode 100644 index 0000000..3c1ae1d --- /dev/null +++ b/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt @@ -0,0 +1,19 @@ +converter { + type: "LidarPointcloud" +} + +converter { + type: "HeadingMsgFusion" +} + +converter { + type: "ImuMsgConverter" +} + +converter { + type: "NavMsgConverter" +} + +converter { + type: "OdometryMsgConverter" +} diff --git a/cyber/ros_bridge/converter_base/convert_apollo_double.h b/cyber/ros_bridge/converter_base/convert_apollo_double.h new file mode 100644 index 0000000..7a0136a --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_apollo_double.h @@ -0,0 +1,384 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_APOLLO_ROS_SINGLE_H_ +#define CYBER_APOLLO_ROS_SINGLE_H_ + +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + auto func = [this, ros_publisher_0, + apollo_blocker_1](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1](const std::shared_ptr in) { +#endif + auto out = std::make_shared(); + if (!apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(in, msg1)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + auto func = [this, apollo_blocker_1, ros_publisher_0, + ros_publisher_1](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(in, msg1)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + auto func = [this, apollo_blocker_1, ros_publisher_0, ros_publisher_1, + ros_publisher_2](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(in, msg1)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + auto ros_publisher_3 = + ros_node_->create_publisher(ros_topic_name_3, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + ros_publishers_.push_back(std::move(ros_publisher_3)); + auto func = [this, apollo_blocker_1, ros_publisher_0, ros_publisher_1, + ros_publisher_2, + ros_publisher_3](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(in, msg1)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); + ros_publisher_3->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + + return true; +} + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h b/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h new file mode 100644 index 0000000..815a5e0 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h @@ -0,0 +1,503 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_APOLLO_ROS_SINGLE_H_ +#define CYBER_APOLLO_ROS_SINGLE_H_ + +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + apollo::cyber::ReaderConfig reader_cfg_3; + reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); + auto apollo_reader_3 = + cyber_node_->template CreateReader(reader_cfg_3); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + auto apollo_blocker_3 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_3.channel_name); +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + auto func = [this, ros_publisher_0, apollo_blocker_1, apollo_blocker_2, + apollo_blocker_3](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, apollo_blocker_2, + apollo_blocker_3](const std::shared_ptr in) { +#endif + auto out = std::make_shared(); + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty() && + !apollo_blocker_3->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(in, msg1, msg2, msg3)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + apollo_readers_.push_back(std::move(apollo_reader_3)); + + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes>& output) = 0; +}; // NOLINT + +// template +// bool ApolloRosMessageConverter, +// std::shared_ptr, +// std::shared_ptr, +// std::shared_ptr>, +// OutputTypes>>::Init() + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + apollo::cyber::ReaderConfig reader_cfg_3; + reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); + auto apollo_reader_3 = + cyber_node_->template CreateReader(reader_cfg_3); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + auto apollo_blocker_3 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_3.channel_name); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, + ros_publisher_0, + ros_publisher_1](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, apollo_blocker_2, + apollo_blocker_3](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty() && + !apollo_blocker_3->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(in, msg1, msg2, msg3)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + apollo_readers_.push_back(std::move(apollo_reader_3)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + apollo::cyber::ReaderConfig reader_cfg_3; + reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); + auto apollo_reader_3 = + cyber_node_->template CreateReader(reader_cfg_3); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + auto apollo_blocker_3 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_3.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, + ros_publisher_0, ros_publisher_1, + ros_publisher_2](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, apollo_blocker_2, + apollo_blocker_3](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(in, msg1, msg2, msg3)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + apollo_readers_.push_back(std::move(apollo_reader_3)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + apollo::cyber::ReaderConfig reader_cfg_3; + reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); + auto apollo_reader_3 = + cyber_node_->template CreateReader(reader_cfg_3); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + auto apollo_blocker_3 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_3.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + auto ros_publisher_3 = + ros_node_->create_publisher(ros_topic_name_3, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + ros_publishers_.push_back(std::move(ros_publisher_3)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, + ros_publisher_0, ros_publisher_1, ros_publisher_2, + ros_publisher_3](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, apollo_blocker_2, + apollo_blocker_3](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty() && + !apollo_blocker_3->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(in, msg1, msg2, msg3)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); + ros_publisher_3->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + apollo_readers_.push_back(std::move(apollo_reader_3)); + + return true; +} + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_apollo_single.h b/cyber/ros_bridge/converter_base/convert_apollo_single.h new file mode 100644 index 0000000..aa6bab6 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_apollo_single.h @@ -0,0 +1,325 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_APOLLO_ROS_SINGLE_H_ +#define CYBER_APOLLO_ROS_SINGLE_H_ + +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +class ApolloRosMessageConverter>, + OutputTypes>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg(InputTypes>& input, + OutputTypes>& output) = 0; +}; + +template +bool ApolloRosMessageConverter>, + OutputTypes>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + // ros_publishers_.push_back(ros_publisher_0); + auto func = [this, ros_publisher_0](const std::shared_ptr in) { +#else + auto func = [this](const std::shared_ptr in) { +#endif + std::shared_ptr out(new OutType0); + auto in_container = + InputTypes>{std::make_tuple(in)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); + AERROR << "out of convert"; +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out); +#endif + AERROR << "after ros publish"; + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg(InputTypes>& input, + OutputTypes, + std::shared_ptr>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + auto func = [this, ros_publisher_0, + ros_publisher_1](const std::shared_ptr in) { +#else + auto func = [this](const std::shared_ptr in) { +#endif + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto in_container = + InputTypes>{std::make_tuple(in)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); +#endif + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + auto func = [this, ros_publisher_0, ros_publisher_1, + ros_publisher_2](const std::shared_ptr in) { +#else + auto func = [this](const std::shared_ptr in) { +#endif + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto in_container = + InputTypes>{std::make_tuple(in)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); +#endif + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + auto ros_publisher_3 = + ros_node_->create_publisher(ros_topic_name_3, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + ros_publishers_.push_back(std::move(ros_publisher_3)); + auto func = [this, ros_publisher_0, ros_publisher_1, ros_publisher_2, + ros_publisher_3](const std::shared_ptr in) { +#else + auto func = [this](const std::shared_ptr in) { +#endif + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + auto in_container = + InputTypes>{std::make_tuple(in)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); + ros_publisher_3->publish(*out_2); +#endif + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + + return true; +} + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_apollo_triple.h b/cyber/ros_bridge/converter_base/convert_apollo_triple.h new file mode 100644 index 0000000..e1a5140 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_apollo_triple.h @@ -0,0 +1,450 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_APOLLO_ROS_SINGLE_H_ +#define CYBER_APOLLO_ROS_SINGLE_H_ + +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + auto func = [this, ros_publisher_0, apollo_blocker_1, + apollo_blocker_2](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, + apollo_blocker_2](const std::shared_ptr in) { +#endif + auto out = std::make_shared(); + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, + ros_publisher_1](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, + apollo_blocker_2](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, + ros_publisher_1, + ros_publisher_2](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, + apollo_blocker_2](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_1->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + + return true; +} + +template +class ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; +}; + +template +bool ApolloRosMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>>::Init() { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo::cyber::ReaderConfig reader_cfg_0; + reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); + + apollo::cyber::ReaderConfig reader_cfg_1; + reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); + auto apollo_reader_1 = + cyber_node_->template CreateReader(reader_cfg_1); + + apollo::cyber::ReaderConfig reader_cfg_2; + reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); + auto apollo_reader_2 = + cyber_node_->template CreateReader(reader_cfg_2); + + auto apollo_blocker_1 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_1.channel_name); + auto apollo_blocker_2 = + blocker::BlockerManager::Instance()->GetBlocker( + reader_cfg_2.channel_name); + + std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + +#ifdef RCLCPP__RCLCPP_HPP_ + auto ros_publisher_0 = + ros_node_->create_publisher(ros_topic_name_0, 10); + auto ros_publisher_1 = + ros_node_->create_publisher(ros_topic_name_1, 10); + auto ros_publisher_2 = + ros_node_->create_publisher(ros_topic_name_2, 10); + auto ros_publisher_3 = + ros_node_->create_publisher(ros_topic_name_3, 10); + ros_publishers_.push_back(std::move(ros_publisher_0)); + ros_publishers_.push_back(std::move(ros_publisher_1)); + ros_publishers_.push_back(std::move(ros_publisher_2)); + ros_publishers_.push_back(std::move(ros_publisher_3)); + auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, + ros_publisher_1, ros_publisher_2, + ros_publisher_3](const std::shared_ptr in) { +#else + auto func = [this, apollo_blocker_1, + apollo_blocker_2](const std::shared_ptr in) { +#endif + if (!apollo_blocker_1->IsPublishedEmpty() && + !apollo_blocker_2->IsPublishedEmpty()) { + auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); + auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_publisher_0->publish(*out_0); + ros_publisher_1->publish(*out_1); + ros_publisher_2->publish(*out_2); + ros_publisher_3->publish(*out_2); +#endif + } + }; + auto apollo_reader_0 = + cyber_node_->template CreateReader(reader_cfg_0, func); + apollo_readers_.push_back(std::move(apollo_reader_0)); + apollo_readers_.push_back(std::move(apollo_reader_1)); + apollo_readers_.push_back(std::move(apollo_reader_2)); + + return true; +} + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_ros_base.h b/cyber/ros_bridge/converter_base/convert_ros_base.h new file mode 100644 index 0000000..a127f1a --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_ros_base.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_ROS_APOLLO_BASE_H_ +#define CYBER_ROS_APOLLO_BASE_H_ + +#include +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +class RosApolloMessageConverter : public MessageConverter { + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override; + + protected: + virtual bool ConvertMsg( + const std::shared_ptr& ros_msg0, const std::shared_ptr& ros_msg1, + const std::shared_ptr& ros_msg2, const std::shared_ptr& ros_msg3, + std::shared_ptr& apollo_msg0, std::shared_ptr& apollo_msg1, + std::shared_ptr& apollo_msg2, std::shared_ptr& apollo_msg3) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(const std::shared_ptr& ros_msg0, + const std::shared_ptr& ros_msg1, + const std::shared_ptr& ros_msg2, + const std::shared_ptr& ros_msg3); +#endif +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_ros_double.h b/cyber/ros_bridge/converter_base/convert_ros_double.h new file mode 100644 index 0000000..bd8b5b0 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_ros_double.h @@ -0,0 +1,452 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_ROS_APOLLO_DOUBLE_H_ +#define CYBER_ROS_APOLLO_DOUBLE_H_ + +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" + +namespace apollo { +namespace cyber { + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + auto writer_attrs = + std::make_shared(); + writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); + apollo_attrs_.push_back(writer_attrs); + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*writer_attrs); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1) { + auto out = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + std::shared_ptr> apollo_writer_3_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); + apollo_writer_3_ = + cyber_node_->template CreateWriter(*apollo_attrs_[3]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + auto in_container = + InputTypes, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + apollo_writer_3_->Write(out_3); + } +#endif +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_ros_quadruple.h b/cyber/ros_bridge/converter_base/convert_ros_quadruple.h new file mode 100644 index 0000000..8e80160 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_ros_quadruple.h @@ -0,0 +1,551 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_ROS_APOLLO_TRIPLE_H_ +#define CYBER_ROS_APOLLO_TRIPLE_H_ + +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" + +namespace apollo { +namespace cyber { + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + auto writer_attrs = + std::make_shared(); + writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); + apollo_attrs_.push_back(writer_attrs); + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*writer_attrs); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_3))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get()), + *dynamic_cast*>( + ros_msg_subs_[3].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2, + std::shared_ptr ros_msg3) { + auto out = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + typename InType3::SharedPtr internal_in_prt_3 = + std::make_shared(*ros_msg3.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1, + internal_in_prt_2, internal_in_prt_3)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_3))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get()), + *dynamic_cast*>( + ros_msg_subs_[3].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2, + std::shared_ptr ros_msg3) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + typename InType3::SharedPtr internal_in_prt_3 = + std::make_shared(*ros_msg3.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1, + internal_in_prt_2, internal_in_prt_3)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_3))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get()), + *dynamic_cast*>( + ros_msg_subs_[3].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2, + std::shared_ptr ros_msg3) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + typename InType3::SharedPtr internal_in_prt_3 = + std::make_shared(*ros_msg3.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1, + internal_in_prt_2, internal_in_prt_3)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + std::shared_ptr> apollo_writer_3_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); + apollo_writer_3_ = + cyber_node_->template CreateWriter(*apollo_attrs_[3]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_3))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get()), + *dynamic_cast*>( + ros_msg_subs_[3].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2, + std::shared_ptr ros_msg3) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + typename InType3::SharedPtr internal_in_prt_3 = + std::make_shared(*ros_msg3.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(internal_in_prt_0, internal_in_prt_1, + internal_in_prt_2, internal_in_prt_3)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + apollo_writer_3_->Write(out_3); + } +#endif +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_ros_single.h b/cyber/ros_bridge/converter_base/convert_ros_single.h new file mode 100644 index 0000000..3e0f391 --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_ros_single.h @@ -0,0 +1,364 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_ROS_APOLLO_SINGLE_H_ +#define CYBER_ROS_APOLLO_SINGLE_H_ + +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" + +namespace apollo { +namespace cyber { + +template +class RosApolloMessageConverter>, + OutputTypes>> + : public MessageConverter { + private: + std::shared_ptr> apollo_writer_0_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + AERROR << "load config failed"; + return false; + } + + auto writer_attrs = + std::make_shared(); + writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); + apollo_attrs_.push_back(writer_attrs); + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*writer_attrs); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_subscriptions_.push_back( + std::move(ros_node_->create_subscription( + ros_topic_name_0, 10, + std::bind( + &RosApolloMessageConverter< + InputTypes>, + OutputTypes>>::TopicCallback, + this, std::placeholders::_1)))); + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg(InputTypes>& input, + OutputTypes>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0) { + auto out = std::make_shared(); + typename InType0::SharedPtr internal_in_prt = + std::make_shared(*ros_msg0.get()); + auto in_container = + InputTypes>{std::make_tuple(internal_in_prt)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + private: + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_subscriptions_.push_back( + std::move(ros_node_->create_subscription( + ros_topic_name_0, 10, + std::bind( + &RosApolloMessageConverter< + InputTypes>, + OutputTypes, + std::shared_ptr>>::TopicCallback, + this, std::placeholders::_1)))); + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg(InputTypes>& input, + OutputTypes, + std::shared_ptr>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt = + std::make_shared(*ros_msg0.get()); + auto in_container = + InputTypes>{std::make_tuple(internal_in_prt)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + private: + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_subscriptions_.push_back( + std::move(ros_node_->create_subscription( + ros_topic_name_0, 10, + std::bind( + &RosApolloMessageConverter< + InputTypes>, + OutputTypes, + std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this, std::placeholders::_1)))); + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt = + std::make_shared(*ros_msg0.get()); + auto in_container = + InputTypes>{std::make_tuple(internal_in_prt)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + private: + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + std::shared_ptr> apollo_writer_3_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); + apollo_writer_3_ = + cyber_node_->template CreateWriter(*apollo_attrs_[3]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_subscriptions_.push_back( + std::move(ros_node_->create_subscription( + ros_topic_name_0, 10, + std::bind( + &RosApolloMessageConverter< + InputTypes>, + OutputTypes, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this, std::placeholders::_1)))); + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt = + std::make_shared(*ros_msg0.get()); + auto in_container = + InputTypes>{std::make_tuple(internal_in_prt)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + apollo_writer_3_->Write(out_3); + } +#endif +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/convert_ros_triple.h b/cyber/ros_bridge/converter_base/convert_ros_triple.h new file mode 100644 index 0000000..0d576fc --- /dev/null +++ b/cyber/ros_bridge/converter_base/convert_ros_triple.h @@ -0,0 +1,509 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_ROS_APOLLO_TRIPLE_H_ +#define CYBER_ROS_APOLLO_TRIPLE_H_ + +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/converter_base.h" + +namespace apollo { +namespace cyber { + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + auto writer_attrs = + std::make_shared(); + writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); + apollo_attrs_.push_back(writer_attrs); + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*writer_attrs); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2) { + auto out = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple( + internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; + auto out_container = + OutputTypes>{std::make_tuple(out)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple( + internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; + auto out_container = + OutputTypes, std::shared_ptr>{ + std::make_tuple(out_0, out_1)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>> : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr>& output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple( + internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + } +#endif +}; + +template +class RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>> + : public MessageConverter { + private: +#ifdef RCLCPP__RCLCPP_HPP_ + typedef message_filters::sync_policies::ApproximateTime + approximate_sync_policy; + std::shared_ptr> + syncApproximate_; +#endif + std::shared_ptr> apollo_writer_0_ = nullptr; + std::shared_ptr> apollo_writer_1_ = nullptr; + std::shared_ptr> apollo_writer_2_ = nullptr; + std::shared_ptr> apollo_writer_3_ = nullptr; + + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + MessageConverter::Init(); + if (!init_.load()) { + return false; + } + if (!LoadConfig(&converter_conf_)) { + return false; + } + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); + + apollo_attrs_.push_back( + std::make_shared()); + apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); + + auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); + auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); + auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); + + apollo_writer_0_ = + cyber_node_->template CreateWriter(*apollo_attrs_[0]); + apollo_writer_1_ = + cyber_node_->template CreateWriter(*apollo_attrs_[1]); + apollo_writer_2_ = + cyber_node_->template CreateWriter(*apollo_attrs_[2]); + apollo_writer_3_ = + cyber_node_->template CreateWriter(*apollo_attrs_[3]); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_0))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_1))); + ros_msg_subs_.push_back( + std::move(std::make_shared>( + ros_node_, ros_topic_name_2))); + syncApproximate_ = std::make_shared< + message_filters::Synchronizer>( + approximate_sync_policy(10), + *dynamic_cast*>( + ros_msg_subs_[0].get()), + *dynamic_cast*>( + ros_msg_subs_[1].get()), + *dynamic_cast*>( + ros_msg_subs_[2].get())); + syncApproximate_->registerCallback( + &RosApolloMessageConverter< + InputTypes, std::shared_ptr, + std::shared_ptr>, + OutputTypes, std::shared_ptr, + std::shared_ptr, + std::shared_ptr>>::TopicCallback, + this); + + ros_spin_thread_ = + std::make_shared(&MessageConverter::NodeSpin, this); +#endif + return true; + } + + protected: + virtual bool ConvertMsg( + InputTypes, std::shared_ptr, + std::shared_ptr>& input, + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>& + output) = 0; + +#ifdef RCLCPP__RCLCPP_HPP_ + private: + void TopicCallback(std::shared_ptr ros_msg0, + std::shared_ptr ros_msg1, + std::shared_ptr ros_msg2) { + auto out_0 = std::make_shared(); + auto out_1 = std::make_shared(); + auto out_2 = std::make_shared(); + auto out_3 = std::make_shared(); + typename InType0::SharedPtr internal_in_prt_0 = + std::make_shared(*ros_msg0.get()); + typename InType1::SharedPtr internal_in_prt_1 = + std::make_shared(*ros_msg1.get()); + typename InType2::SharedPtr internal_in_prt_2 = + std::make_shared(*ros_msg2.get()); + auto in_container = + InputTypes, std::shared_ptr, + std::shared_ptr>{std::make_tuple( + internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; + auto out_container = + OutputTypes, std::shared_ptr, + std::shared_ptr, std::shared_ptr>{ + std::make_tuple(out_0, out_1, out_2, out_3)}; + this->ConvertMsg(in_container, out_container); + apollo_writer_0_->Write(out_0); + apollo_writer_1_->Write(out_1); + apollo_writer_2_->Write(out_2); + apollo_writer_3_->Write(out_3); + } +#endif +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/converter_base.h b/cyber/ros_bridge/converter_base/converter_base.h new file mode 100644 index 0000000..5cbb418 --- /dev/null +++ b/cyber/ros_bridge/converter_base/converter_base.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_APOLLO_ROS_BASE_H_ +#define CYBER_APOLLO_ROS_BASE_H_ + +#include +#include +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/cyber.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +namespace apollo { +namespace cyber { + +template +struct InputTypes { + std::tuple values; + static constexpr size_t NInputs = sizeof...(Types); +}; + +template +struct OutputTypes { + std::tuple values; + static constexpr size_t NOutputs = sizeof...(Types); +}; + +template +class ApolloRosMessageConverter : public MessageConverter { + public: + ApolloRosMessageConverter() {} + ~ApolloRosMessageConverter() override {} + + bool Init() override { + AERROR << "input output not support"; + return false; + }; + + protected: + virtual bool ConvertMsg(InputTypes& input, OutputTypes& output) = 0; +}; + +template +class RosApolloMessageConverter : public MessageConverter { + public: + RosApolloMessageConverter() {} + ~RosApolloMessageConverter() override {} + + bool Init() override { + AERROR << "input output not support"; + return false; + }; + + protected: + virtual bool ConvertMsg(InputTypes& input, OutputTypes& output) = 0; +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converter_base/converter_interface.h b/cyber/ros_bridge/converter_base/converter_interface.h new file mode 100644 index 0000000..6667d19 --- /dev/null +++ b/cyber/ros_bridge/converter_base/converter_interface.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_CONVERTER_INTERFACE_H_ +#define CYBER_CONVERTER_INTERFACE_H_ + +#include "cyber/ros_bridge/converter_base/convert_apollo_double.h" +#include "cyber/ros_bridge/converter_base/convert_apollo_quadruple.h" +#include "cyber/ros_bridge/converter_base/convert_apollo_single.h" +#include "cyber/ros_bridge/converter_base/convert_apollo_triple.h" +#include "cyber/ros_bridge/converter_base/convert_ros_double.h" +#include "cyber/ros_bridge/converter_base/convert_ros_quadruple.h" +#include "cyber/ros_bridge/converter_base/convert_ros_single.h" +#include "cyber/ros_bridge/converter_base/convert_ros_triple.h" + +#endif diff --git a/cyber/ros_bridge/converter_base/message_converter.h b/cyber/ros_bridge/converter_base/message_converter.h new file mode 100644 index 0000000..c6a2b05 --- /dev/null +++ b/cyber/ros_bridge/converter_base/message_converter.h @@ -0,0 +1,149 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_MESSAGE_CONVERTER_H_ +#define CYBER_MESSAGE_CONVERTER_H_ + +#include // NOLINT +#include // NOLINT +#include // NOLINT +#include // NOLINT +#include // NOLINT +#include // NOLINT + +#include // NOLINT + +#include "cyber/ros_bridge/proto/converter_conf.pb.h" + +#include "cyber/cyber.h" +#include "cyber/node/reader_base.h" +#include "cyber/node/writer_base.h" +#include "cyber/plugin_manager/plugin_manager.h" +#include "cyber/ros_bridge/common/macros.h" + +#if __has_include("rclcpp/rclcpp.hpp") +#include "message_filters/subscriber.h" +#include "message_filters/sync_policies/approximate_time.h" +#include "message_filters/synchronizer.h" +#include "rclcpp/rclcpp.hpp" +#include "ros_adapter/ros_distro.h" +#endif + +namespace apollo { +namespace cyber { + +class MessageConverter { + public: + MessageConverter() : init_(false) {} + + virtual ~MessageConverter() {} + + virtual bool Init() { + if (init_.exchange(true)) { + return true; + } + LoadConfig(&converter_conf_); + cyber_node_ = std::move( + CreateNode(node_name_ + "_" + converter_conf_.name() + "_apollo")); +#ifdef RCLCPP__RCLCPP_HPP_ + ros_node_ = std::make_shared<::rclcpp::Node>( + node_name_ + "_" + converter_conf_.name() + "_ros"); + ros_node_exec_ = + std::make_shared<::rclcpp::executors::SingleThreadedExecutor>(); +#endif + return true; + } + +#ifdef RCLCPP__RCLCPP_HPP_ + void NodeSpin() { + ros_node_exec_->add_node(std::shared_ptr(ros_node_)); + ros_node_exec_->spin(); + } +#endif + + bool IsInit() const { return init_.load(); } + + protected: + bool LoadConfig(ConverterConf* config) { + int status; + std::string class_name = + abi::__cxa_demangle(typeid(*this).name(), 0, 0, &status); + std::string delimiter = "::"; + std::string sub_class_name; + std::string conf_file_prefix; + + auto pos = class_name.rfind(delimiter); + if (pos == std::string::npos) { + sub_class_name = class_name; + } else { + sub_class_name = class_name.substr(pos + delimiter.length()); + } + + for (int i = 0; i < sub_class_name.length(); i++) { + if (std::isupper(sub_class_name[i]) && i > 0) { + conf_file_prefix.push_back('_'); + } + conf_file_prefix.push_back(std::tolower(sub_class_name[i])); + } + + std::string config_path = + apollo::cyber::plugin_manager::PluginManager::Instance() + ->GetPluginConfPath( + class_name, "conf/" + conf_file_prefix + ".pb.txt"); + if (!apollo::cyber::common::PathExists(config_path)) { + config_path = apollo::cyber::plugin_manager::PluginManager::Instance() + ->GetPluginConfPath( + class_name, std::string("conf/default.pb.txt")); + } + + if (!apollo::cyber::common::GetProtoFromFile(config_path, config)) { + AERROR << "Load config of " << class_name << " failed!"; + return false; + } + AINFO << "Load the [" << class_name + << "] config file successfully, file path: " << config_path; + return true; + } + + protected: + std::atomic init_; + std::unique_ptr cyber_node_; + std::vector> + apollo_attrs_; + std::vector> apollo_readers_; + std::vector> apollo_writers_; +#ifdef RCLCPP__RCLCPP_HPP_ + std::vector> ros_publishers_; + std::vector> ros_subscriptions_; +#if defined(ROS_DISTRO_FOXY) || defined(ROS_DISTRO_GALACTIC) + std::vector> +#else + std::vector>> +#endif + ros_msg_subs_; + std::shared_ptr<::rclcpp::Node> ros_node_ = nullptr; + std::shared_ptr<::rclcpp::executors::SingleThreadedExecutor> ros_node_exec_ = + nullptr; + std::shared_ptr ros_spin_thread_; +#endif + const std::string node_name_ = "converter_base"; + ConverterConf converter_conf_; +}; + +} // namespace cyber +} // namespace apollo + +#endif // CYBER_MESSAGE_CONVERTER_H_ diff --git a/cyber/ros_bridge/converters/BUILD b/cyber/ros_bridge/converters/BUILD new file mode 100644 index 0000000..3cac8b1 --- /dev/null +++ b/cyber/ros_bridge/converters/BUILD @@ -0,0 +1,3 @@ +load("//tools:apollo_package.bzl", "apollo_package") + +apollo_package() \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/BUILD b/cyber/ros_bridge/converters/common_plugins/BUILD new file mode 100644 index 0000000..3cac8b1 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/BUILD @@ -0,0 +1,3 @@ +load("//tools:apollo_package.bzl", "apollo_package") + +apollo_package() \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD new file mode 100755 index 0000000..609edeb --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD @@ -0,0 +1,104 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") +load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_files", + srcs = glob([ + "conf/**", + "data/**", + ]), +) + +apollo_plugin( + name = "libheading_msg_fusion.so", + srcs = ["heading_msg_fusion.cc"], + hdrs = [ + "heading_msg_fusion.h", + "quaternion_math.h", + ], + description = ":heading_msg_plugins.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "//modules/common_msgs/sensor_msgs:heading_proto", + "@ros" + ], +) + +apollo_plugin( + name = "libimu_msg_converter.so", + srcs = ["imu_msg_converter.cc"], + hdrs = [ + "imu_msg_converter.h", + "quaternion_math.h", + ], + description = ":imu_plugins.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "//modules/common_msgs/localization_msgs:imu_proto", + "//modules/common_msgs/sensor_msgs:imu_proto", + "@ros" + ], +) + +apollo_plugin( + name = "libnav_msg_converter.so", + srcs = ["nav_msg_converter.cc"], + hdrs = ["nav_msg_converter.h"], + description = ":nav_plugins.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "//modules/common_msgs/sensor_msgs:gnss_best_pose_proto", + "//modules/common_msgs/sensor_msgs:ins_proto", + "@ros" + ], +) + +apollo_plugin( + name = "libodometry_msg_converter.so", + srcs = ["odometry_msg_converter.cc"], + hdrs = ["odometry_msg_converter.h"], + description = ":odometry_msg_plugins.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "//modules/common_msgs/localization_msgs:gps_proto", + "@ros" + ], +) + +apollo_plugin( + name = "libodometry_parser.so", + srcs = ["odometry_parser.cc"], + hdrs = [ + "odometry_parser.h", + "quaternion_math.h", + ], + description = ":odometry_plugins.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "@ros", + "@proj", + "@eigen" + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt new file mode 100755 index 0000000..bb25a96 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt @@ -0,0 +1,4 @@ +name: "heading" +apollo_channel_name_0: "/apollo/sensor/gnss/heading" +ros_topic_name_0: "/gps/fix" +ros_topic_name_1: "/odometry" diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt new file mode 100755 index 0000000..7b2f35f --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt @@ -0,0 +1,4 @@ +name: "imu" +apollo_channel_name_0: "/apollo/sensor/gnss/imu" +apollo_channel_name_1: "/apollo/sensor/gnss/corrected_imu" +ros_topic_name_0: "/imu/data" diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt new file mode 100755 index 0000000..318dd5f --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt @@ -0,0 +1,5 @@ +name: "nav" +apollo_channel_name_0: "/apollo/sensor/gnss/best_pose" +apollo_channel_name_1: "/apollo/sensor/gnss/ins_stat" +ros_topic_name_0: "/gps/fix" + diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt new file mode 100755 index 0000000..ac2e6ab --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt @@ -0,0 +1,3 @@ +name: "odometry" +apollo_channel_name_0: "/apollo/sensor/gnss/odometry" +ros_topic_name_0: "/odometry" diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt new file mode 100755 index 0000000..162142d --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt @@ -0,0 +1,5 @@ +name: "odometry_parser" +apollo_channel_name_0: "/apollo/sensor/gnss/odometry" +ros_topic_name_0: "/imu" +ros_topic_name_1: "/gps" +ros_topic_name_2: "/odom" diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc new file mode 100755 index 0000000..3c30af9 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc @@ -0,0 +1,97 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h" // NOLINT +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" + +namespace apollo { +namespace cyber { + +bool HeadingMsgFusion::ConvertMsg( + InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto ros_nav_ptr = std::get<0>(in.values); + auto ros_odometry_ptr = std::get<1>(in.values); + auto& ros_nav = (*ros_nav_ptr); + auto& ros_odometry = (*ros_odometry_ptr); + + auto heading_msg = std::get<0>(out.values); + + auto unix_msg_time = + ros_nav.header.stamp.sec + ros_nav.header.stamp.nanosec / 1e9; + + double quaternion[4]; + double euler_angles[3]; + + quaternion[0] = ros_odometry.pose.pose.orientation.x; + quaternion[1] = ros_odometry.pose.pose.orientation.y; + quaternion[2] = ros_odometry.pose.pose.orientation.z; + quaternion[3] = ros_odometry.pose.pose.orientation.w; + + QuaternionToEuler(quaternion, euler_angles); + auto pitch = euler_angles[1]; + auto heading = QuaternionToHeading(euler_angles[2]); + + heading_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + heading_msg->mutable_header()->set_module_name("gnss"); + heading_msg->set_measurement_time(unix_msg_time); + + if (ros_nav.status.status == -1) { + heading_msg->set_solution_status(19); + heading_msg->set_position_type(0); + } else if (ros_nav.status.status == 0) { + heading_msg->set_solution_status(0); + heading_msg->set_position_type(16); + } else if (ros_nav.status.status == 1) { + heading_msg->set_solution_status(0); + heading_msg->set_position_type(18); + } else if (ros_nav.status.status == 2) { + heading_msg->set_solution_status(0); + heading_msg->set_position_type(50); + } + heading_msg->set_heading(heading); + heading_msg->set_pitch(pitch); + + /* + pose covariance: + [ + xx, xy, xz, xroll, xpitch, xyaw, + yx, yy, yz, yroll, ypitch, yyaw, + zx, zy, zz, zroll, zpitch, zzaw, + rollx, rolly, rollz, rollroll, rollpitch, rollyaw, + pitchx, pitchy, pitchz, pitchroll, pitchpitch, pitchyaw, + yawx, yawy, yawz, yawroll, yawpitch, yawyaw + ] + thus pitch_stddev = sqrt(covariance[28]), yaw_stddev = sqrt(covariance[35]) + */ + + auto covariance = ros_odometry.pose.covariance; + auto pitch_variance = covariance[28]; + auto yaw_variance = covariance[35]; + + double pitch_stddev = sqrt(pitch_variance); + double yaw_stddev = sqrt(yaw_variance); + + heading_msg->set_heading_std_dev(yaw_stddev); + heading_msg->set_pitch_std_dev(pitch_stddev); + +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h new file mode 100755 index 0000000..ccdc408 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/sensor_msgs/heading.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") +#include "sensor_msgs/msg/nav_sat_fix.hpp" +#define ROS_NAVFOUND_FOUND +#endif + +#if __has_include("nav_msgs/msg/odometry.hpp") +#include "nav_msgs/msg/odometry.hpp" +#define ROS_ODOMETRY_FOUND +#endif + +#if defined(ROS_NAVFOUND_FOUND) && defined(ROS_ODOMETRY_FOUND) +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using RosNavMsg = sensor_msgs::msg::NavSatFix; +using RosOdometryMsg = nav_msgs::msg::Odometry; +#else +// fake wrap +using RosNavMsg = apollo::cyber::proto::SimpleMessage; +using RosOdometryMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using OutputMsg = apollo::drivers::gnss::Heading; + +using RosNavMsgPtr = std::shared_ptr; +using RosOdometryMsgPtr = std::shared_ptr; + +using OutputMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class HeadingMsgFusion : public apollo::cyber::RosApolloMessageConverter< + InputTypes, + OutputTypes> { + public: + HeadingMsgFusion() {} + ~HeadingMsgFusion() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputTypes input message container + * @param OutputTypes output message container + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::HeadingMsgFusion, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml new file mode 100755 index 0000000..c92615c --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc new file mode 100755 index 0000000..449afa3 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc @@ -0,0 +1,85 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h" // NOLINT +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" + +namespace apollo { +namespace cyber { + +bool ImuMsgConverter::ConvertMsg( + InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto ros_imu_ptr = std::get<0>(in.values); + auto& ros_imu = (*ros_imu_ptr); + + auto imu_msg = std::get<0>(out.values); + auto corrected_imu_msg = std::get<1>(out.values); + + // ros header time is unix time, + // while measurement_time of apollo imu is gps time + double unix_msg_time = + ros_imu.header.stamp.sec + ros_imu.header.stamp.nanosec / 1e9; + imu_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + imu_msg->mutable_header()->set_module_name("gnss"); + + imu_msg->set_measurement_time(unix_msg_time); + imu_msg->set_measurement_span(0.0); + imu_msg->mutable_linear_acceleration()->set_x(ros_imu.linear_acceleration.x); + imu_msg->mutable_linear_acceleration()->set_y(ros_imu.linear_acceleration.y); + imu_msg->mutable_linear_acceleration()->set_z(ros_imu.linear_acceleration.z); + imu_msg->mutable_angular_velocity()->set_x(ros_imu.angular_velocity.x); + imu_msg->mutable_angular_velocity()->set_y(ros_imu.angular_velocity.y); + imu_msg->mutable_angular_velocity()->set_z(ros_imu.angular_velocity.z); + + corrected_imu_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + corrected_imu_msg->mutable_header()->set_module_name("gnss"); + corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_x( + ros_imu.linear_acceleration.x); + corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_y( + ros_imu.linear_acceleration.y); + corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_z( + ros_imu.linear_acceleration.z); + corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_x( + ros_imu.angular_velocity.x); + corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_y( + ros_imu.angular_velocity.y); + corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_z( + ros_imu.angular_velocity.z); + double quaternion[4]; + double euler_angles[3]; + + quaternion[0] = ros_imu.orientation.x; + quaternion[1] = ros_imu.orientation.y; + quaternion[2] = ros_imu.orientation.z; + quaternion[3] = ros_imu.orientation.w; + + QuaternionToEuler(quaternion, euler_angles); + auto heading = QuaternionToHeading(euler_angles[2]); + corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_x( + euler_angles[0]); + corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_y( + euler_angles[1]); + corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_z( + euler_angles[2]); + +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h new file mode 100755 index 0000000..64f7a00 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/localization_msgs/imu.pb.h" +#include "modules/common_msgs/sensor_msgs/imu.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("sensor_msgs/msg/imu.hpp") +#include "sensor_msgs/msg/imu.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using RosImuMsg = sensor_msgs::msg::Imu; +#else +// fake wrap +using RosImuMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using ImuMsg = apollo::drivers::gnss::Imu; +using CorrectedImuMsg = apollo::localization::CorrectedImu; + +using RosImuMsgPtr = std::shared_ptr; + +using ImuMsgPtr = std::shared_ptr; +using CorrectedImuMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class ImuMsgConverter : public apollo::cyber::RosApolloMessageConverter< + InputTypes, + OutputTypes> { + public: + ImuMsgConverter() {} + ~ImuMsgConverter() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputTypes input message container + * @param OutputTypes output message container + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::ImuMsgConverter, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml new file mode 100755 index 0000000..1d36b10 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc new file mode 100755 index 0000000..4dcabf7 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc @@ -0,0 +1,78 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h" // NOLINT +#include + +namespace apollo { +namespace cyber { + +bool NavMsgConverter::ConvertMsg( + InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto ros_nav_ptr = std::get<0>(in.values); + auto& ros_nav = (*ros_nav_ptr); + + auto best_pose_msg = std::get<0>(out.values); + auto ins_stat_msg = std::get<1>(out.values); + + auto unix_msg_time = + ros_nav.header.stamp.sec + ros_nav.header.stamp.nanosec / 1e9; + best_pose_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + best_pose_msg->mutable_header()->set_module_name("gnss"); + + ins_stat_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + ins_stat_msg->mutable_header()->set_module_name("gnss"); + + best_pose_msg->set_measurement_time(unix_msg_time); + best_pose_msg->set_latitude(ros_nav.latitude); + best_pose_msg->set_longitude(ros_nav.longitude); + best_pose_msg->set_height_msl(ros_nav.altitude); + best_pose_msg->set_undulation(0); + best_pose_msg->set_datum_id(apollo::drivers::gnss::DatumId::WGS84); + best_pose_msg->set_latitude_std_dev(sqrt(ros_nav.position_covariance[4])); + best_pose_msg->set_longitude_std_dev(sqrt(ros_nav.position_covariance[0])); + best_pose_msg->set_height_std_dev(sqrt(ros_nav.position_covariance[8])); + if (ros_nav.status.status == -1) { + best_pose_msg->set_sol_status( + apollo::drivers::gnss::SolutionStatus::INVALID_FIX); + best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::NONE); + ins_stat_msg->set_pos_type(0); + } else if (ros_nav.status.status == 0) { + best_pose_msg->set_sol_status( + apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); + best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::SINGLE); + ins_stat_msg->set_pos_type(1); + } else if (ros_nav.status.status == 1) { + best_pose_msg->set_sol_status( + apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); + best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::WAAS); + ins_stat_msg->set_pos_type(2); + } else if (ros_nav.status.status == 2) { + best_pose_msg->set_sol_status( + apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); + best_pose_msg->set_sol_type( + apollo::drivers::gnss::SolutionType::NARROW_INT); + ins_stat_msg->set_pos_type(2); + } + +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h new file mode 100755 index 0000000..1fa83ab --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/sensor_msgs/gnss_best_pose.pb.h" +#include "modules/common_msgs/sensor_msgs/ins.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") +#include "sensor_msgs/msg/nav_sat_fix.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using RosNavMsg = sensor_msgs::msg::NavSatFix; +#else +// fake wrap +using RosNavMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using BestPoseMsg = apollo::drivers::gnss::GnssBestPose; +using InsStatMsg = apollo::drivers::gnss::InsStat; + +using RosNavMsgPtr = std::shared_ptr; + +using BestPoseMsgPtr = std::shared_ptr; +using InsStatMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class NavMsgConverter : public apollo::cyber::RosApolloMessageConverter< + InputTypes, + OutputTypes> { + public: + NavMsgConverter() {} + ~NavMsgConverter() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputTypes input message container + * @param OutputTypes output message container + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::NavMsgConverter, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml new file mode 100755 index 0000000..95e7c02 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc new file mode 100755 index 0000000..4bbd809 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc @@ -0,0 +1,66 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h" // NOLINT + +namespace apollo { +namespace cyber { + +bool OdometryMsgConverter::ConvertMsg(InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto ros_odometry_ptr = std::get<0>(in.values); + auto& ros_odometry = (*ros_odometry_ptr); + + auto odometry_msg = std::get<0>(out.values); + + auto unix_msg_time = + ros_odometry.header.stamp.sec + ros_odometry.header.stamp.nanosec / 1e9; + odometry_msg->mutable_header()->set_timestamp_sec(unix_msg_time); + odometry_msg->mutable_header()->set_module_name("gnss"); + odometry_msg->mutable_localization()->mutable_position()->set_x( + ros_odometry.pose.pose.position.x); + odometry_msg->mutable_localization()->mutable_position()->set_y( + ros_odometry.pose.pose.position.y); + odometry_msg->mutable_localization()->mutable_position()->set_z( + ros_odometry.pose.pose.position.z); + odometry_msg->mutable_localization()->mutable_linear_velocity()->set_x( + ros_odometry.twist.twist.linear.x); + odometry_msg->mutable_localization()->mutable_linear_velocity()->set_y( + ros_odometry.twist.twist.linear.y); + odometry_msg->mutable_localization()->mutable_linear_velocity()->set_z( + ros_odometry.twist.twist.linear.z); + odometry_msg->mutable_localization()->mutable_angular_velocity()->set_x( + ros_odometry.twist.twist.angular.x); + odometry_msg->mutable_localization()->mutable_angular_velocity()->set_y( + ros_odometry.twist.twist.angular.y); + odometry_msg->mutable_localization()->mutable_angular_velocity()->set_z( + ros_odometry.twist.twist.angular.z); + odometry_msg->mutable_localization()->mutable_orientation()->set_qx( + ros_odometry.pose.pose.orientation.x); + odometry_msg->mutable_localization()->mutable_orientation()->set_qy( + ros_odometry.pose.pose.orientation.y); + odometry_msg->mutable_localization()->mutable_orientation()->set_qz( + ros_odometry.pose.pose.orientation.z); + odometry_msg->mutable_localization()->mutable_orientation()->set_qw( + ros_odometry.pose.pose.orientation.w); + +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h new file mode 100755 index 0000000..29ae889 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h @@ -0,0 +1,74 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/localization_msgs/gps.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("nav_msgs/msg/odometry.hpp") +#include "nav_msgs/msg/odometry.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using RosOdometryMsg = nav_msgs::msg::Odometry; +#else +// fake wrap +using RosOdometryMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using OdometryOutputMsg = apollo::localization::Gps; + +using RosOdometryMsgPtr = std::shared_ptr; + +using OdometryOutputMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class OdometryMsgConverter + : public apollo::cyber::RosApolloMessageConverter< + InputTypes, OutputTypes> { + public: + OdometryMsgConverter() {} + ~OdometryMsgConverter() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputTypes input message container + * @param OutputTypes output message container + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::OdometryMsgConverter, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml new file mode 100755 index 0000000..f7456c8 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc new file mode 100755 index 0000000..8d03ee8 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc @@ -0,0 +1,140 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h" // NOLINT +#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" + +namespace apollo { +namespace cyber { + +void OdometryParser::imuCallback(std::shared_ptr msg) { +#ifdef ENABLE_ROS_MSG + imu_received_.store(true); + auto current_time = msg->header.stamp.sec + msg->header.stamp.nanosec / 1e9; + double dt = current_time - last_time_; + last_time_ = current_time; + + F_(0, 3) = dt; + F_(1, 4) = dt; + F_(2, 5) = dt; + + X_ = F_ * X_; + P_ = F_ * P_ * F_.transpose() + Q_; + + X_(3) += msg->linear_acceleration.x * dt; + X_(4) += msg->linear_acceleration.y * dt; + X_(5) += msg->linear_acceleration.z * dt; + + double euler_angles[3]; + + quaternion_[0] = msg->orientation.x; + quaternion_[1] = msg->orientation.y; + quaternion_[2] = msg->orientation.z; + quaternion_[3] = msg->orientation.w; + + QuaternionToEuler(quaternion_, euler_angles); + auto roll = euler_angles[0]; + auto pitch = euler_angles[1]; + auto yaw = euler_angles[2]; + + X_(6) = roll; + X_(7) = pitch; + X_(8) = yaw; +#endif +} + +void OdometryParser::gpsCallback(std::shared_ptr msg) { +#ifdef ENABLE_ROS_MSG + gps_received_.store(true); + constexpr double DEG_TO_RAD_LOCAL = M_PI / 180.0; + Eigen::VectorXd Z(9); + + double lon = msg->longitude; + double lat = msg->latitude; + double px = lon * DEG_TO_RAD_LOCAL; + double py = lat * DEG_TO_RAD_LOCAL; + + if (utm_target_ == NULL) { + std::string proj4_text; + int zone = static_cast(std::ceil((lon + 180.0) / 6.0)); + proj4_text = "+proj=utm +zone=" + std::to_string(zone) + + " +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"; + utm_target_ = pj_init_plus(proj4_text.c_str()); + } + pj_transform(wgs84pj_source_, utm_target_, 1, 1, &px, &py, NULL); + + Z << px, py, msg->altitude, 0, 0, 0, 0, 0, 0; + + Eigen::MatrixXd y = Z - H_ * X_; + Eigen::MatrixXd S = H_ * P_ * H_.transpose() + R_; + Eigen::MatrixXd K = P_ * H_.transpose() * S.inverse(); + X_ = X_ + K * y; + P_ = (Eigen::MatrixXd::Identity(9, 9) - K * H_) * P_; +#endif +} + +void OdometryParser::publishOdometry() { +#ifdef ENABLE_ROS_MSG + if (!gps_received_.load() || !imu_received_.load()) { + return; + } + RosOdomMsg odom_msg; + odom_msg.header.stamp = ros_node_->get_clock()->now(); + + odom_msg.pose.pose.position.x = X_(0); + odom_msg.pose.pose.position.y = X_(1); + odom_msg.pose.pose.position.z = X_(2); + + odom_msg.pose.pose.orientation.x = quaternion_[0]; + odom_msg.pose.pose.orientation.y = quaternion_[1]; + odom_msg.pose.pose.orientation.z = quaternion_[2]; + odom_msg.pose.pose.orientation.w = quaternion_[3]; + + odom_msg.twist.twist.linear.x = X_(3); + odom_msg.twist.twist.linear.y = X_(4); + odom_msg.twist.twist.linear.z = X_(5); + + for (int i = 0; i < 6; ++i) { + for (int j = 0; j < 6; ++j) { + if (i < 3 && j < 3) { + odom_msg.pose.covariance[i * 6 + j] = P_(i, j); + } else if (i >= 3 && j >= 3) { + odom_msg.pose.covariance[i * 6 + j] = P_(i + 3, j + 3); + } + } + } + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + odom_msg.twist.covariance[i * 6 + j] = P_(i + 3, j + 3); + } + } + + odom_pub_->publish(odom_msg); + imu_received_.store(false); + imu_received_.store(false); +#endif +} + +bool OdometryParser::ConvertMsg(InputTypes& in, + OutputTypes& out) { + // do nothing + return true; +} + +} // namespace cyber +} // namespace apollo + diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h new file mode 100755 index 0000000..da94679 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h @@ -0,0 +1,152 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H +#include // NOLINT + +#include // NOLINT + +#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") +#include "sensor_msgs/msg/nav_sat_fix.hpp" +#define ROS_NAVFOUND_FOUND +#endif + +#if __has_include("sensor_msgs/msg/imu.hpp") +#include "sensor_msgs/msg/imu.hpp" +#define ROS_IMU_FOUND +#endif + +#if __has_include("nav_msgs/msg/odometry.hpp") +#include "nav_msgs/msg/odometry.hpp" +#define ROS_ODOMETRY_FOUND +#endif + +#if defined(ROS_NAVFOUND_FOUND) && defined(ROS_IMU_FOUND) && \ + defined(ROS_ODOMETRY_FOUND) +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using RosNavMsg = sensor_msgs::msg::NavSatFix; +using RosImuMsg = sensor_msgs::msg::Imu; +using RosWrapMsg = std_msgs::msg::Header; +using RosOdomMsg = nav_msgs::msg::Odometry; +#else +// fake wrap +using RosNavMsg = apollo::cyber::proto::SimpleMessage; +using RosImuMsg = apollo::cyber::proto::SimpleMessage; +using RosWrapMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using OutputWrapMsg = apollo::cyber::proto::SimpleMessage; + +using RosWrapMsgPtr = std::shared_ptr; +using OutputWrapMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class OdometryParser + : public apollo::cyber::RosApolloMessageConverter< + InputTypes, OutputTypes> { + public: + OdometryParser() { +#ifdef ENABLE_ROS_MSG + imu_sub_ = ros_node_->create_subscription( + converter_conf_.ros_topic_name_0(), 10, + std::bind(&OdometryParser::imuCallback, this, std::placeholders::_1)); + gps_sub_ = ros_node_->create_subscription( + converter_conf_.ros_topic_name_1(), 10, + std::bind(&OdometryParser::gpsCallback, this, std::placeholders::_1)); + odom_pub_ = ros_node_->create_publisher( + converter_conf_.ros_topic_name_2(), 10); + timer_ = ros_node_->create_wall_timer( + std::chrono::milliseconds(100), + std::bind(&OdometryParser::publishOdometry, this)); +#endif + + wgs84pj_source_ = pj_init_plus("+proj=latlong +ellps=WGS84"); + X_ = Eigen::VectorXd::Zero(9); + P_ = Eigen::MatrixXd::Identity(9, 9); + F_ = Eigen::MatrixXd::Identity(9, 9); + H_ = Eigen::MatrixXd::Identity(9, 9); + R_ = Eigen::MatrixXd::Identity(9, 9) * 0.1; + Q_ = Eigen::MatrixXd::Identity(9, 9) * 0.01; + last_time_ = apollo::cyber::Time::Now().ToSecond(); + } + ~OdometryParser() {} + + void imuCallback(std::shared_ptr msg); + + void gpsCallback(std::shared_ptr msg); + + void publishOdometry(); + + /** + * @brief convert the message between ros and apollo + * + * @param InputTypes input message container + * @param OutputTypes output message container + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); + + private: + projPJ wgs84pj_source_ = NULL; + projPJ utm_target_ = NULL; +#ifdef ENABLE_ROS_MSG + ::rclcpp::SubscriptionBase::SharedPtr imu_sub_; + ::rclcpp::SubscriptionBase::SharedPtr gps_sub_; + ::rclcpp::Publisher::SharedPtr odom_pub_; + ::rclcpp::TimerBase::SharedPtr timer_; +#endif + + std::atomic imu_received_ = false; + std::atomic gps_received_ = false; + + double last_time_; + + double quaternion_[4]; + + // Kalman filter + Eigen::VectorXd X_; // State vector: [x, y, z, vx, vy, vz, roll, pitch, yaw] + Eigen::MatrixXd P_; // Covariance matrix + Eigen::MatrixXd F_; // State transition matrix + Eigen::MatrixXd H_; // Measurement matrix + Eigen::MatrixXd R_; // Measurement noise covariance matrix + Eigen::MatrixXd Q_; // Process noise covariance matrix +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::OdometryParser, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml new file mode 100755 index 0000000..449c0d8 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h new file mode 100644 index 0000000..8af76f3 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include + +namespace apollo { +namespace cyber { + +inline void QuaternionToEuler(const double quaternion[4], double att[3]) { + double dcm21 = + 2 * (quaternion[2] * quaternion[3] + quaternion[0] * quaternion[1]); + double dcm20 = + 2 * (quaternion[1] * quaternion[3] - quaternion[0] * quaternion[2]); + double dcm22 = quaternion[0] * quaternion[0] - quaternion[1] * quaternion[1] - + quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3]; + double dcm01 = + 2 * (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]); + double dcm11 = quaternion[0] * quaternion[0] - quaternion[1] * quaternion[1] + + quaternion[2] * quaternion[2] - quaternion[3] * quaternion[3]; + + att[0] = std::asin(dcm21); // the angle rotate respect to X + att[1] = std::atan2(-dcm20, dcm22); // the angle rotate respect to Y + att[2] = std::atan2(dcm01, dcm11); // the angle rotate respect to Z + + return; +} + +inline double QuaternionToHeading(double yaw) { + double a = std::fmod(yaw + M_PI_2 + M_PI, 2.0 * M_PI); + if (a < 0.0) { + a += (2.0 * M_PI); + } + return a - M_PI; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD new file mode 100755 index 0000000..73c9547 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD @@ -0,0 +1,33 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") +load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_files", + srcs = glob([ + "conf/**", + "data/**", + ]), +) + +apollo_plugin( + name = "liblocalization_estimate.so", + srcs = ["localization_estimate.cc"], + hdrs = ["localization_estimate.h"], + description = ":localization_estimate.xml", + deps = [ + "//cyber", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//modules/common_msgs/localization_msgs:localization_proto", + "//modules/common_msgs/transform_msgs:transform_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "@ros" + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt new file mode 100755 index 0000000..4fb4ca5 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt @@ -0,0 +1,4 @@ +name: "lidar" +apollo_channel_name_0: "/apollo/vanjee/pointcloud2" +apollo_channel_name_1: "/apollo/localization/pose" +ros_topic_name_0: "/pose" diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc new file mode 100755 index 0000000..7bc83e5 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc @@ -0,0 +1,86 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h" // NOLINT + +namespace apollo { +namespace cyber { + +bool LocalizationEstimate::ConvertMsg( + InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto ros_odometry_ptr = std::get<0>(in.values); + auto& ros_odometry = (*ros_odometry_ptr); + auto localization_estimate = std::get<0>(out.values); + auto tf = std::get<1>(out.values); + + auto unix_msg_time = + ros_odometry.header.stamp.sec + ros_odometry.header.stamp.nanosec / 1e9; + localization_estimate->mutable_header()->set_timestamp_sec(unix_msg_time); + localization_estimate->mutable_header()->set_module_name("localization"); + localization_estimate->set_measurement_time(unix_msg_time); + localization_estimate->mutable_pose()->mutable_position()->set_x( + ros_odometry.pose.pose.position.x); + localization_estimate->mutable_pose()->mutable_position()->set_y( + ros_odometry.pose.pose.position.y); + localization_estimate->mutable_pose()->mutable_position()->set_z( + ros_odometry.pose.pose.position.z); + localization_estimate->mutable_pose()->mutable_linear_velocity()->set_x( + ros_odometry.twist.twist.linear.x); + localization_estimate->mutable_pose()->mutable_linear_velocity()->set_y( + ros_odometry.twist.twist.linear.y); + localization_estimate->mutable_pose()->mutable_linear_velocity()->set_z( + ros_odometry.twist.twist.linear.z); + localization_estimate->mutable_pose()->mutable_angular_velocity()->set_x( + ros_odometry.twist.twist.angular.x); + localization_estimate->mutable_pose()->mutable_angular_velocity()->set_y( + ros_odometry.twist.twist.angular.y); + localization_estimate->mutable_pose()->mutable_angular_velocity()->set_z( + ros_odometry.twist.twist.angular.z); + localization_estimate->mutable_pose()->mutable_orientation()->set_qx( + ros_odometry.pose.pose.orientation.x); + localization_estimate->mutable_pose()->mutable_orientation()->set_qy( + ros_odometry.pose.pose.orientation.y); + localization_estimate->mutable_pose()->mutable_orientation()->set_qz( + ros_odometry.pose.pose.orientation.z); + localization_estimate->mutable_pose()->mutable_orientation()->set_qw( + ros_odometry.pose.pose.orientation.w); + + auto single_tf = tf->add_transforms(); + single_tf->mutable_header()->set_timestamp_sec(unix_msg_time); + single_tf->mutable_header()->set_frame_id("world"); + single_tf->set_child_frame_id("localization"); + single_tf->mutable_transform()->mutable_translation()->set_x( + ros_odometry.pose.pose.position.x); + single_tf->mutable_transform()->mutable_translation()->set_y( + ros_odometry.pose.pose.position.y); + single_tf->mutable_transform()->mutable_translation()->set_z( + ros_odometry.pose.pose.position.z); + single_tf->mutable_transform()->mutable_rotation()->set_qx( + ros_odometry.pose.pose.orientation.x); + single_tf->mutable_transform()->mutable_rotation()->set_qy( + ros_odometry.pose.pose.orientation.y); + single_tf->mutable_transform()->mutable_rotation()->set_qz( + ros_odometry.pose.pose.orientation.z); + single_tf->mutable_transform()->mutable_rotation()->set_qw( + ros_odometry.pose.pose.orientation.w); +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h new file mode 100755 index 0000000..da13923 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/localization_msgs/localization.pb.h" +#include "modules/common_msgs/transform_msgs/transform.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("nav_msgs/msg/odometry.hpp") +#include "nav_msgs/msg/odometry.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using InputMsg = nav_msgs::msg::Odometry; +#else +using InputMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using LocalizationMsg = apollo::localization::LocalizationEstimate; +using TransformMsg = apollo::transform::TransformStampeds; + +using LocalizationMsgPtr = std::shared_ptr; +using TransformMsgPtr = std::shared_ptr; +using InputMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class LocalizationEstimate + : public apollo::cyber::RosApolloMessageConverter< + InputTypes, + OutputTypes> { + public: + LocalizationEstimate() {} + ~LocalizationEstimate() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputMsgPtr shared pointer of input message + * @param OutputMsgPtr shared pointer of output message + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::LocalizationEstimate, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml new file mode 100755 index 0000000..61a1569 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD new file mode 100755 index 0000000..eb2e8b6 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD @@ -0,0 +1,32 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") +load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_files", + srcs = glob([ + "conf/**", + "data/**", + ]), +) + +apollo_plugin( + name = "liblidar_pointcloud_plugin.so", + srcs = ["lidar_pointcloud.cc"], + hdrs = ["lidar_pointcloud.h"], + description = ":plugins.xml", + deps = [ + "//cyber", + "//modules/common_msgs/sensor_msgs:pointcloud_proto", + "//cyber/ros_bridge:converter_base", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge/proto:converter_conf_proto", + "@ros" + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt new file mode 100755 index 0000000..4245cd3 --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt @@ -0,0 +1,3 @@ +name: "lidar" +apollo_channel_name_0: "/apollo/sample/pointcloud2" +ros_topic_name_0: "/sample_pointcloud2" diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc new file mode 100755 index 0000000..616d8ff --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc @@ -0,0 +1,230 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h" // NOLINT + +namespace apollo { +namespace cyber { + +#ifdef ENABLE_ROS_MSG +void ParseField(sensor_msgs::msg::PointField field, + std::shared_ptr point_clouds, + std::string field_name, + sensor_msgs::msg::PointCloud2& raw_message) { + switch (field.datatype) { + case sensor_msgs::msg::PointField::INT8: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::UINT8: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::INT16: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::UINT16: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::INT32: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::UINT32: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::FLOAT32: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + case sensor_msgs::msg::PointField::FLOAT64: { + sensor_msgs::PointCloud2ConstIterator iter(raw_message, + field_name); + int index = 0; + for (; iter != iter.end(); ++iter) { + if (field_name == "intensity") { + point_clouds->mutable_point(index)->set_intensity( + static_cast(*iter)); + } else { + point_clouds->mutable_point(index)->set_timestamp( + static_cast(*iter)); + AERROR << *iter; + } + index++; + } + break; + } + default: + throw std::runtime_error("Unsupported PointField datatype"); + } +} +#endif + +bool LidarPointcloud::ConvertMsg(InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto in_msg = std::get<0>(in.values); + auto out_msg = std::get<0>(out.values); + float x, y, z; + float intensity = -1.0; + double timestamp = 0.0; + auto& cloud_msg = (*in_msg); + + bool has_x = false, has_y = false, has_z = false, has_intensity = false, + has_time = false; + std::string time_field_name; + sensor_msgs::msg::PointField time_field_type; + sensor_msgs::msg::PointField intensity_field_type; + for (const auto& field : cloud_msg.fields) { + if (field.name == "x") has_x = true; + if (field.name == "y") has_y = true; + if (field.name == "z") has_z = true; + if (field.name == "intensity") { + has_intensity = true; + intensity_field_type = field; + } + if (field.name == "t" || field.name == "time" || + field.name == "timestamp") { + has_time = true; + time_field_type = field; + time_field_name = field.name; + } + } + if (!(has_x && has_y && has_z)) { + AERROR << "PointCloud2 does not contain x, y, z fields."; + return false; + } + + sensor_msgs::PointCloud2ConstIterator iter_x(cloud_msg, "x"); + sensor_msgs::PointCloud2ConstIterator iter_y(cloud_msg, "y"); + sensor_msgs::PointCloud2ConstIterator iter_z(cloud_msg, "z"); + + for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) { + x = *iter_x; + y = *iter_y; + z = *iter_z; + + auto pointcloud = out_msg->add_point(); + pointcloud->set_x(x); + pointcloud->set_y(y); + pointcloud->set_z(z); + } + if (has_time) { + ParseField(time_field_type, out_msg, time_field_name, cloud_msg); + } + if (has_intensity) { + ParseField(intensity_field_type, out_msg, "intensity", cloud_msg); + } +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h new file mode 100755 index 0000000..11a628c --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include +#include +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "modules/common_msgs/sensor_msgs/pointcloud.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("sensor_msgs/point_cloud2_iterator.hpp") +#include "sensor_msgs/point_cloud2_iterator.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using InputMsg = sensor_msgs::msg::PointCloud2; +#else +using InputMsg = apollo::cyber::proto::SimpleMessage; +#endif + +using OutputMsg = apollo::drivers::PointCloud; + +using InputMsgPtr = std::shared_ptr; +using OutputMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class LidarPointcloud + : public apollo::cyber::RosApolloMessageConverter< + InputTypes, OutputTypes> { + public: + LidarPointcloud() {} + ~LidarPointcloud() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputMsgPtr shared pointer of input message + * @param OutputMsgPtr shared pointer of output message + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, OutputTypes&); + +#ifdef ENABLE_ROS_MSG + inline int FindFieldIndex( + std::string name, sensor_msgs::msg::PointCloud2& cloud_msg) { // NOLINT + for (int i = 0; i < cloud_msg.fields.size(); i++) { + if (cloud_msg.fields[i].name == name) { + return i; + } + } + return -1; + } +#endif +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::LidarPointcloud, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml new file mode 100755 index 0000000..612c10f --- /dev/null +++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD b/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD new file mode 100644 index 0000000..108b103 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD @@ -0,0 +1,34 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") +load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_files", + srcs = glob([ + "conf/**", + "data/**", + ]), +) + +# import ros repository is new feature of cyber 2.0 +# depend on the env configuration provided by the apollo tool +# currently under development +apollo_plugin( + name = "libapollo_ros_converter_plugin.so", + srcs = ["apollo_ros_converter.cc"], + hdrs = ["apollo_ros_converter.h"], + description = ":plugins.xml", + deps = [ + "//cyber", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge:converter_base", + "//cyber/ros_bridge/proto:converter_conf_proto", + # "@ros" + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc new file mode 100644 index 0000000..6b29474 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h" + +namespace apollo { +namespace cyber { + +bool ApolloRosConverter::ConvertMsg(InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto in_msg = std::get<0>(in.values); + auto out_msg = std::get<0>(out.values); + out_msg->data = in_msg->text(); + // out->data = in->text(); +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h new file mode 100644 index 0000000..757ead1 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("std_msgs/msg/string.hpp") +#include "std_msgs/msg/int32.hpp" +#include "std_msgs/msg/int64.hpp" +#include "std_msgs/msg/int8.hpp" +#include "std_msgs/msg/string.hpp" +#define ENABLE_ROS_MSG +#endif + +using InputMsg0 = apollo::cyber::proto::SimpleMessage; +#ifdef ENABLE_ROS_MSG +using OutputMsg0 = std_msgs::msg::String; +#else +using OutputMsg0 = apollo::cyber::proto::SimpleRepeatedMessage; +#endif +using OutputMsg0Ptr = std::shared_ptr; +using InputMsg0Ptr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class ApolloRosConverter + : public apollo::cyber::ApolloRosMessageConverter< + InputTypes, OutputTypes> { + public: + ApolloRosConverter() {} + ~ApolloRosConverter() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputMsgPtr shared pointer of input message + * @param OutputMsgPtr shared pointer of output message + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes&, + OutputTypes&); +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::ApolloRosConverter, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt new file mode 100644 index 0000000..455afec --- /dev/null +++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt @@ -0,0 +1,2 @@ +apollo_channel_name: "/apollo/test1" +ros_topic_name: "ros_test1" diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml b/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml new file mode 100644 index 0000000..016eb7d --- /dev/null +++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD b/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD new file mode 100644 index 0000000..57f1c42 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD @@ -0,0 +1,34 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") +load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "runtime_files", + srcs = glob([ + "conf/**", + "data/**", + ]), +) + +# import ros repository is new feature of cyber 2.0 +# depend on the env configuration provided by the apollo tool +# currently under development +apollo_plugin( + name = "libros_apollo_converter_plugin.so", + srcs = ["ros_apollo_converter.cc"], + hdrs = ["ros_apollo_converter.h"], + description = ":plugins.xml", + deps = [ + "//cyber", + "//cyber/proto:simple_proto", + "//cyber/ros_bridge:converter_base", + "//cyber/ros_bridge/proto:converter_conf_proto", + "@ros" + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt new file mode 100644 index 0000000..362809d --- /dev/null +++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt @@ -0,0 +1,2 @@ +apollo_channel_name_0: "/apollo/test2" +ros_topic_name_0: "/chatter" diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml b/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml new file mode 100644 index 0000000..4ff4aef --- /dev/null +++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc new file mode 100644 index 0000000..89fbcb8 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc @@ -0,0 +1,33 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h" + +namespace apollo { +namespace cyber { + +bool RosApolloConverter::ConvertMsg(InputTypes& in, + OutputTypes& out) { +#ifdef ENABLE_ROS_MSG + auto in_msg = std::get<0>(in.values); + auto out_msg = std::get<0>(out.values); + out_msg->set_text(in_msg->data.c_str()); +#endif + return true; +} + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h new file mode 100644 index 0000000..c7ed499 --- /dev/null +++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Copyright 2023 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include + +#include "cyber/ros_bridge/converter_base/converter_interface.h" + +#include "cyber/proto/simple.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" + +#if __has_include("std_msgs/msg/string.hpp") +#include "std_msgs/msg/string.hpp" +#define ENABLE_ROS_MSG +#endif + +#ifdef ENABLE_ROS_MSG +using InputMsg = std_msgs::msg::String; +#else +using InputMsg = apollo::cyber::proto::SimpleRepeatedMessage; +#endif +using OutputMsg = apollo::cyber::proto::SimpleMessage; +using InputMsgPtr = std::shared_ptr; +using OutputMsgPtr = std::shared_ptr; + +namespace apollo { +namespace cyber { + +class RosApolloConverter + : public apollo::cyber::RosApolloMessageConverter< + InputTypes, OutputTypes> { + public: + RosApolloConverter() {} + ~RosApolloConverter() {} + + /** + * @brief convert the message between ros and apollo + * + * @param InputMsgPtr shared pointer of input message + * @param OutputMsgPtr shared pointer of output message + * @return result, true for success + */ + virtual bool ConvertMsg(InputTypes& in, + OutputTypes& out); // NOLINT +}; + +CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::RosApolloConverter, + apollo::cyber::MessageConverter) + +} // namespace cyber +} // namespace apollo diff --git a/cyber/ros_bridge/proto/BUILD b/cyber/ros_bridge/proto/BUILD new file mode 100644 index 0000000..5d8e890 --- /dev/null +++ b/cyber/ros_bridge/proto/BUILD @@ -0,0 +1,16 @@ +load("//tools/proto:proto.bzl", "proto_library") +load("//tools:apollo_package.bzl", "apollo_package") + +package(default_visibility = ["//visibility:public"]) + +proto_library( + name = "converter_conf_proto", + srcs = ["converter_conf.proto"], +) + +proto_library( + name = "ros_bridge_conf_proto", + srcs = ["ros_bridge_conf.proto"], +) + +apollo_package() \ No newline at end of file diff --git a/cyber/ros_bridge/proto/converter_conf.proto b/cyber/ros_bridge/proto/converter_conf.proto new file mode 100644 index 0000000..91b4abe --- /dev/null +++ b/cyber/ros_bridge/proto/converter_conf.proto @@ -0,0 +1,15 @@ +syntax = "proto2"; + +package apollo.cyber; + +message ConverterConf { + optional string name = 1; + optional string apollo_channel_name_0 = 2; + optional string apollo_channel_name_1 = 3; + optional string apollo_channel_name_2 = 4; + optional string apollo_channel_name_3 = 5; + optional string ros_topic_name_0 = 6; + optional string ros_topic_name_1 = 7; + optional string ros_topic_name_2 = 8; + optional string ros_topic_name_3 = 9; +} \ No newline at end of file diff --git a/cyber/ros_bridge/proto/ros_bridge_conf.proto b/cyber/ros_bridge/proto/ros_bridge_conf.proto new file mode 100644 index 0000000..e4fe62f --- /dev/null +++ b/cyber/ros_bridge/proto/ros_bridge_conf.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; + +package apollo.cyber; + +message BridgeConf { + // The contained converter list of the ros bridge pipeline. + repeated PluginDeclareInfo converter = 1; +} + +message PluginDeclareInfo { + // classname of converter + optional string type = 1; +} diff --git a/cyber/ros_bridge/ros_bridge.cc b/cyber/ros_bridge/ros_bridge.cc new file mode 100644 index 0000000..8b9f5d2 --- /dev/null +++ b/cyber/ros_bridge/ros_bridge.cc @@ -0,0 +1,99 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include + +#include "cyber/ros_bridge/common/macros.h" + +#include "cyber/ros_bridge/proto/ros_bridge_conf.pb.h" +#include "cyber/cyber.h" +#include "cyber/plugin_manager/plugin_manager.h" +#include "cyber/ros_bridge/common/bridge_argument.h" +#include "cyber/ros_bridge/common/ros_bridge_gflags.h" +#include "cyber/ros_bridge/common/utils.h" +#include "cyber/ros_bridge/converter_base/message_converter.h" + +#include "gperftools/heap-profiler.h" +#include "gperftools/malloc_extension.h" +#include "gperftools/profiler.h" + +#if __has_include("rclcpp/rclcpp.hpp") +#include "rclcpp/rclcpp.hpp" +#endif + +using apollo::cyber::BridgeArgument; +using apollo::cyber::MessageConverter; +using apollo::cyber::plugin_manager::PluginManager; +using namespace apollo::cyber::common; // NOLINT + +int main(int argc, char** argv) { + apollo::cyber::BridgeConf bridge_conf; + std::vector> converter_list_; + + BridgeArgument bridge_args; + bridge_args.ParseArgument(argc, argv); + + apollo::cyber::Init(argv[0]); + +#ifdef RCLCPP__RCLCPP_HPP_ + rclcpp::init(argc, argv); +#endif + + PluginManager::Instance()->LoadInstalledPlugins(); + + auto config_path = + GetAbsolutePath(WorkRoot(), apollo::cyber::FLAGS_bridge_conf_path); + if (!GetProtoFromFile(config_path, &bridge_conf)) { + AERROR << "parse ros bridge config failed!"; + return 1; + } + + for (int i = 0; i < bridge_conf.converter_size(); i++) { + auto converter = + PluginManager::Instance()->CreateInstance( + apollo::cyber::GetFullConverterClassName( + bridge_conf.converter(i).type())); + ACHECK(converter->Init()) + << "Can not init converter " << bridge_conf.converter(i).type(); + converter_list_.push_back(converter); + } + + if (bridge_args.GetEnableCpuprofile()) { + auto profile_filename = bridge_args.GetProfileFilename(); + ProfilerStart(profile_filename.c_str()); + } + + if (bridge_args.GetEnableHeapprofile()) { + auto profile_filename = bridge_args.GetHeapProfileFilename(); + HeapProfilerStart(profile_filename.c_str()); + } + + apollo::cyber::WaitForShutdown(); +#ifdef RCLCPP__RCLCPP_HPP_ + rclcpp::shutdown(); +#endif + + if (bridge_args.GetEnableCpuprofile()) { + ProfilerStop(); + } + + if (bridge_args.GetEnableHeapprofile()) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } + + return 0; +} diff --git a/cyber/service_discovery/BUILD b/cyber/service_discovery/BUILD index aa8ccb4..5b9de22 100644 --- a/cyber/service_discovery/BUILD +++ b/cyber/service_discovery/BUILD @@ -36,7 +36,6 @@ apollo_cc_library( "//cyber/common:cyber_common", "//cyber:cyber_binary", "//cyber/proto:role_attributes_cc_proto", - "@fastrtps", "//cyber:cyber_state", "//cyber/message:cyber_message", "//cyber/proto:proto_desc_cc_proto", @@ -45,6 +44,11 @@ apollo_cc_library( ], ) +apollo_cc_library( + name = "subscriber_listener", + hdrs = ["communication/subscriber_listener.h"] +) + apollo_cc_library( name = "cyber_service_discovery_role", srcs = ["role/role.cc"], diff --git a/cyber/service_discovery/communication/participant_listener.cc b/cyber/service_discovery/communication/participant_listener.cc index ed5cc94..71d020d 100644 --- a/cyber/service_discovery/communication/participant_listener.cc +++ b/cyber/service_discovery/communication/participant_listener.cc @@ -30,9 +30,20 @@ ParticipantListener::~ParticipantListener() { callback_ = nullptr; } -void ParticipantListener::onParticipantDiscovery( - eprosima::fastrtps::Participant* p, - eprosima::fastrtps::ParticipantDiscoveryInfo info) { +/** + * @brief Event handler for participant discovery. + * + * This function is called when a new participant is discovered in the DDS domain. + * + * @param p Pointer to the DomainParticipant. This parameter is unused in this function. + * DomainParticipant represents an entity that participates in a DDS domain, + * allowing publishers and subscribers to communicate. + * @param info An rvalue reference to the ParticipantDiscoveryInfo, which contains + * information about the discovered participant. + */ +void ParticipantListener::on_participant_discovery( + eprosima::fastdds::dds::DomainParticipant* p, + eprosima::fastrtps::rtps::ParticipantDiscoveryInfo&& info) { RETURN_IF_NULL(callback_); (void)p; std::lock_guard lock(mutex_); diff --git a/cyber/service_discovery/communication/participant_listener.h b/cyber/service_discovery/communication/participant_listener.h index 91cc20d..d80994b 100644 --- a/cyber/service_discovery/communication/participant_listener.h +++ b/cyber/service_discovery/communication/participant_listener.h @@ -20,25 +20,27 @@ #include #include +#include "cyber/base/macros.h" + +#include "fastdds/dds/domain/DomainParticipantListener.hpp" #include "fastrtps/Domain.h" -#include "fastrtps/participant/Participant.h" -#include "fastrtps/participant/ParticipantListener.h" namespace apollo { namespace cyber { namespace service_discovery { -class ParticipantListener : public eprosima::fastrtps::ParticipantListener { +class ParticipantListener + : public eprosima::fastdds::dds::DomainParticipantListener { public: using ChangeFunc = std::function; + const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info)>; explicit ParticipantListener(const ChangeFunc& callback); virtual ~ParticipantListener(); - virtual void onParticipantDiscovery( - eprosima::fastrtps::Participant* p, - eprosima::fastrtps::ParticipantDiscoveryInfo info); + void on_participant_discovery( + eprosima::fastdds::dds::DomainParticipant* p, + eprosima::fastrtps::rtps::ParticipantDiscoveryInfo&& info) override; private: ChangeFunc callback_; diff --git a/cyber/service_discovery/communication/subscriber_listener.cc b/cyber/service_discovery/communication/subscriber_listener.cc index 1501b5a..dcf9581 100644 --- a/cyber/service_discovery/communication/subscriber_listener.cc +++ b/cyber/service_discovery/communication/subscriber_listener.cc @@ -16,15 +16,23 @@ #include "cyber/service_discovery/communication/subscriber_listener.h" +#include + +#include "cyber/base/macros.h" + +#include "fastdds/dds/subscriber/InstanceState.hpp" + +#include "fastdds/dds/topic/TopicDescription.hpp" + #include "cyber/common/log.h" #include "cyber/transport/rtps/underlay_message.h" -#include "cyber/transport/rtps/underlay_message_type.h" namespace apollo { namespace cyber { namespace service_discovery { -SubscriberListener::SubscriberListener(const NewMsgCallback& callback) +SubscriberListener::SubscriberListener( + const transport::rtps::subsciber_callback& callback) : callback_(callback) {} SubscriberListener::~SubscriberListener() { @@ -32,22 +40,28 @@ SubscriberListener::~SubscriberListener() { callback_ = nullptr; } -void SubscriberListener::onNewDataMessage(eprosima::fastrtps::Subscriber* sub) { +void SubscriberListener::on_data_available( + eprosima::fastdds::dds::DataReader* reader) { RETURN_IF_NULL(callback_); - std::lock_guard lock(mutex_); - eprosima::fastrtps::SampleInfo_t m_info; + eprosima::fastdds::dds::SampleInfo m_info; cyber::transport::UnderlayMessage m; - RETURN_IF(!sub->takeNextData(reinterpret_cast(&m), &m_info)); - RETURN_IF(m_info.sampleKind != eprosima::fastrtps::ALIVE); - - callback_(m.data()); + while (reader->take_next_sample(reinterpret_cast(&m), &m_info) == + eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { + if (m_info.valid_data) { + // parameter 1 and 2 are not used + callback_(std::make_shared(m.data()), 0, msg_info_); + } else { + AERROR << "Remote writer for topic " + << reader->get_topicdescription()->get_name() << " is dead"; + } + } } -void SubscriberListener::onSubscriptionMatched( - eprosima::fastrtps::Subscriber* sub, - eprosima::fastrtps::MatchingInfo& info) { - (void)sub; +void SubscriberListener::on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) { + (void)reader; (void)info; } diff --git a/cyber/service_discovery/communication/subscriber_listener.h b/cyber/service_discovery/communication/subscriber_listener.h index 1c63c1f..586ecb3 100644 --- a/cyber/service_discovery/communication/subscriber_listener.h +++ b/cyber/service_discovery/communication/subscriber_listener.h @@ -21,28 +21,33 @@ #include #include -#include "fastrtps/Domain.h" -#include "fastrtps/subscriber/SampleInfo.h" -#include "fastrtps/subscriber/Subscriber.h" -#include "fastrtps/subscriber/SubscriberListener.h" +#include "cyber/base/macros.h" + +#include "fastdds/dds/subscriber/DataReader.hpp" +#include "fastdds/dds/subscriber/SampleInfo.hpp" +#include "fastdds/dds/subscriber/SubscriberListener.hpp" + +#include "cyber/transport/common/common_type.h" namespace apollo { namespace cyber { namespace service_discovery { -class SubscriberListener : public eprosima::fastrtps::SubscriberListener { +class SubscriberListener : public eprosima::fastdds::dds::SubscriberListener { public: - using NewMsgCallback = std::function; - - explicit SubscriberListener(const NewMsgCallback& callback); + explicit SubscriberListener( + const transport::rtps::subsciber_callback& callback); virtual ~SubscriberListener(); - void onNewDataMessage(eprosima::fastrtps::Subscriber* sub); - void onSubscriptionMatched(eprosima::fastrtps::Subscriber* sub, - eprosima::fastrtps::MatchingInfo& info); // NOLINT + void on_data_available(eprosima::fastdds::dds::DataReader* reader) override; + void on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) + override; // NOLINT private: - NewMsgCallback callback_; + transport::rtps::subsciber_callback callback_; + transport::MessageInfo msg_info_; std::mutex mutex_; }; diff --git a/cyber/service_discovery/specific_manager/channel_manager.cc b/cyber/service_discovery/specific_manager/channel_manager.cc index adc6c15..8a6c2cc 100644 --- a/cyber/service_discovery/specific_manager/channel_manager.cc +++ b/cyber/service_discovery/specific_manager/channel_manager.cc @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2018 The Apollo Authors. All Rights Reserved. + * Copyright 2024 The Apollo Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ #include "cyber/service_discovery/specific_manager/channel_manager.h" #include -#include #include #include "cyber/common/global_data.h" @@ -25,8 +24,6 @@ #include "cyber/message/message_traits.h" #include "cyber/message/py_message.h" #include "cyber/message/raw_message.h" -#include "cyber/state.h" -#include "cyber/time/time.h" namespace apollo { namespace cyber { diff --git a/cyber/service_discovery/specific_manager/channel_manager.h b/cyber/service_discovery/specific_manager/channel_manager.h index 69aba27..46de5f3 100644 --- a/cyber/service_discovery/specific_manager/channel_manager.h +++ b/cyber/service_discovery/specific_manager/channel_manager.h @@ -23,6 +23,7 @@ #include #include +#include "cyber/proto/role_attributes.pb.h" #include "cyber/service_discovery/container/graph.h" #include "cyber/service_discovery/container/multi_value_warehouse.h" #include "cyber/service_discovery/container/single_value_warehouse.h" diff --git a/cyber/service_discovery/specific_manager/channel_manager_test.cc b/cyber/service_discovery/specific_manager/channel_manager_test.cc index a83303c..c3f44c5 100644 --- a/cyber/service_discovery/specific_manager/channel_manager_test.cc +++ b/cyber/service_discovery/specific_manager/channel_manager_test.cc @@ -16,15 +16,13 @@ #include "cyber/service_discovery/specific_manager/channel_manager.h" -#include #include #include #include "gtest/gtest.h" +#include "cyber/proto/unit_test.pb.h" #include "cyber/common/global_data.h" #include "cyber/message/message_traits.h" -#include "cyber/message/protobuf_factory.h" -#include "cyber/proto/unit_test.pb.h" #include "cyber/transport/common/identity.h" namespace apollo { diff --git a/cyber/service_discovery/specific_manager/manager.cc b/cyber/service_discovery/specific_manager/manager.cc index 353ef73..e97e3aa 100644 --- a/cyber/service_discovery/specific_manager/manager.cc +++ b/cyber/service_discovery/specific_manager/manager.cc @@ -21,15 +21,12 @@ #include "cyber/message/message_traits.h" #include "cyber/time/time.h" #include "cyber/transport/qos/qos_profile_conf.h" -#include "cyber/transport/rtps/attributes_filler.h" #include "cyber/transport/rtps/underlay_message.h" -#include "cyber/transport/rtps/underlay_message_type.h" namespace apollo { namespace cyber { namespace service_discovery { -using transport::AttributesFiller; using transport::QosProfileConf; Manager::Manager() @@ -39,15 +36,14 @@ Manager::Manager() change_type_(proto::ChangeType::CHANGE_PARTICIPANT), channel_name_(""), publisher_(nullptr), - subscriber_(nullptr), - listener_(nullptr) { + subscriber_(nullptr) { host_name_ = common::GlobalData::Instance()->HostName(); process_id_ = common::GlobalData::Instance()->ProcessId(); } Manager::~Manager() { Shutdown(); } -bool Manager::StartDiscovery(RtpsParticipant* participant) { +bool Manager::StartDiscovery(const ParticipantPtr& participant) { if (participant == nullptr) { return false; } @@ -59,6 +55,7 @@ bool Manager::StartDiscovery(RtpsParticipant* participant) { StopDiscovery(); return false; } + participant_ = participant; return true; } @@ -66,24 +63,6 @@ void Manager::StopDiscovery() { if (!is_discovery_started_.exchange(false)) { return; } - - { - std::lock_guard lg(lock_); - if (publisher_ != nullptr) { - eprosima::fastrtps::Domain::removePublisher(publisher_); - publisher_ = nullptr; - } - } - - if (subscriber_ != nullptr) { - eprosima::fastrtps::Domain::removeSubscriber(subscriber_); - subscriber_ = nullptr; - } - - if (listener_ != nullptr) { - delete listener_; - listener_ = nullptr; - } } void Manager::Shutdown() { @@ -137,28 +116,16 @@ void Manager::RemoveChangeListener(const ChangeConnection& conn) { local_conn.Disconnect(); } -bool Manager::CreatePublisher(RtpsParticipant* participant) { - RtpsPublisherAttr pub_attr; - RETURN_VAL_IF( - !AttributesFiller::FillInPubAttr( - channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, &pub_attr), - false); - publisher_ = - eprosima::fastrtps::Domain::createPublisher(participant, pub_attr); +bool Manager::CreatePublisher(const ParticipantPtr& participant) { + publisher_ = participant->CreatePublisher( + this->channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE); return publisher_ != nullptr; } -bool Manager::CreateSubscriber(RtpsParticipant* participant) { - RtpsSubscriberAttr sub_attr; - RETURN_VAL_IF( - !AttributesFiller::FillInSubAttr( - channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, &sub_attr), - false); - listener_ = new SubscriberListener( +bool Manager::CreateSubscriber(const ParticipantPtr& participant) { + subscriber_ = participant->CreateSubscriber( + this->channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, std::bind(&Manager::OnRemoteChange, this, std::placeholders::_1)); - - subscriber_ = eprosima::fastrtps::Domain::createSubscriber( - participant, sub_attr, listener_); return subscriber_ != nullptr; } @@ -185,14 +152,14 @@ void Manager::Convert(const RoleAttributes& attr, RoleType role, void Manager::Notify(const ChangeMsg& msg) { signal_(msg); } -void Manager::OnRemoteChange(const std::string& msg_str) { +void Manager::OnRemoteChange(const std::shared_ptr& msg_str) { if (is_shutdown_.load()) { ADEBUG << "the manager has been shut down."; return; } ChangeMsg msg; - RETURN_IF(!message::ParseFromString(msg_str, &msg)); + RETURN_IF(!message::ParseFromString(*msg_str, &msg)); if (IsFromSameProcess(msg)) { return; } @@ -211,7 +178,7 @@ bool Manager::Publish(const ChangeMsg& msg) { { std::lock_guard lg(lock_); if (publisher_ != nullptr) { - return publisher_->write(reinterpret_cast(&m)); + return publisher_->Write(m); } } return true; diff --git a/cyber/service_discovery/specific_manager/manager.h b/cyber/service_discovery/specific_manager/manager.h index 22b8341..d2aebcb 100644 --- a/cyber/service_discovery/specific_manager/manager.h +++ b/cyber/service_discovery/specific_manager/manager.h @@ -19,19 +19,22 @@ #include #include +#include #include #include -#include "fastrtps/Domain.h" -#include "fastrtps/attributes/PublisherAttributes.h" -#include "fastrtps/attributes/SubscriberAttributes.h" -#include "fastrtps/participant/Participant.h" -#include "fastrtps/publisher/Publisher.h" -#include "fastrtps/subscriber/Subscriber.h" +#include "cyber/base/macros.h" + +#include "fastdds/dds/publisher/qos/PublisherQos.hpp" +#include "fastdds/dds/subscriber/qos/SubscriberQos.hpp" -#include "cyber/base/signal.h" #include "cyber/proto/topology_change.pb.h" + +#include "cyber/base/signal.h" #include "cyber/service_discovery/communication/subscriber_listener.h" +#include "cyber/transport/rtps/participant.h" +#include "cyber/transport/rtps/publisher.h" +#include "cyber/transport/rtps/subscriber.h" namespace apollo { namespace cyber { @@ -53,11 +56,9 @@ class Manager { using ChangeSignal = base::Signal; using ChangeFunc = std::function; using ChangeConnection = base::Connection; - - using RtpsParticipant = eprosima::fastrtps::Participant; - using RtpsPublisherAttr = eprosima::fastrtps::PublisherAttributes; - using RtpsSubscriberAttr = eprosima::fastrtps::SubscriberAttributes; - + using ParticipantPtr = std::shared_ptr; + using PublisherPtr = std::shared_ptr; + using SubscriberPtr = std::shared_ptr; /** * @brief Construct a new Manager object */ @@ -75,7 +76,7 @@ class Manager { * @return true if start successfully * @return false if start fail */ - bool StartDiscovery(RtpsParticipant* participant); + bool StartDiscovery(const ParticipantPtr& participant); /** * @brief Stop topology discovery @@ -136,8 +137,8 @@ class Manager { int process_id) = 0; protected: - bool CreatePublisher(RtpsParticipant* participant); - bool CreateSubscriber(RtpsParticipant* participant); + bool CreatePublisher(const ParticipantPtr& participant); + bool CreateSubscriber(const ParticipantPtr& participant); virtual bool Check(const RoleAttributes& attr) = 0; virtual void Dispose(const ChangeMsg& msg) = 0; @@ -148,7 +149,7 @@ class Manager { void Notify(const ChangeMsg& msg); bool Publish(const ChangeMsg& msg); - void OnRemoteChange(const std::string& msg_str); + void OnRemoteChange(const std::shared_ptr& msg_str); bool IsFromSameProcess(const ChangeMsg& msg); std::atomic is_shutdown_; @@ -158,10 +159,10 @@ class Manager { std::string host_name_; int process_id_; std::string channel_name_; - eprosima::fastrtps::Publisher* publisher_; + PublisherPtr publisher_; + SubscriberPtr subscriber_; + ParticipantPtr participant_; std::mutex lock_; - eprosima::fastrtps::Subscriber* subscriber_; - SubscriberListener* listener_; ChangeSignal signal_; }; diff --git a/cyber/service_discovery/specific_manager/node_manager.cc b/cyber/service_discovery/specific_manager/node_manager.cc index 8fde169..a48559a 100644 --- a/cyber/service_discovery/specific_manager/node_manager.cc +++ b/cyber/service_discovery/specific_manager/node_manager.cc @@ -18,7 +18,6 @@ #include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/state.h" -#include "cyber/time/time.h" namespace apollo { namespace cyber { diff --git a/cyber/service_discovery/specific_manager/service_manager.cc b/cyber/service_discovery/specific_manager/service_manager.cc index 273b87c..19e39be 100644 --- a/cyber/service_discovery/specific_manager/service_manager.cc +++ b/cyber/service_discovery/specific_manager/service_manager.cc @@ -15,10 +15,8 @@ *****************************************************************************/ #include "cyber/service_discovery/specific_manager/service_manager.h" -#include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/common/util.h" -#include "cyber/time/time.h" namespace apollo { namespace cyber { diff --git a/cyber/service_discovery/topology_manager.cc b/cyber/service_discovery/topology_manager.cc index 419f9bd..a2fd97d 100644 --- a/cyber/service_discovery/topology_manager.cc +++ b/cyber/service_discovery/topology_manager.cc @@ -29,8 +29,7 @@ TopologyManager::TopologyManager() node_manager_(nullptr), channel_manager_(nullptr), service_manager_(nullptr), - participant_(nullptr), - participant_listener_(nullptr) { + participant_(nullptr) { Init(); } @@ -48,9 +47,6 @@ void TopologyManager::Shutdown() { service_manager_->Shutdown(); participant_->Shutdown(); - delete participant_listener_; - participant_listener_ = nullptr; - change_signal_.DisconnectAllSlots(); } @@ -80,8 +76,6 @@ bool TopologyManager::Init() { if (!result) { AERROR << "init manager failed."; participant_ = nullptr; - delete participant_listener_; - participant_listener_ = nullptr; node_manager_ = nullptr; channel_manager_ = nullptr; service_manager_ = nullptr; @@ -93,29 +87,34 @@ bool TopologyManager::Init() { } bool TopologyManager::InitNodeManager() { - return node_manager_->StartDiscovery(participant_->fastrtps_participant()); + return node_manager_->StartDiscovery(participant_); } bool TopologyManager::InitChannelManager() { - return channel_manager_->StartDiscovery(participant_->fastrtps_participant()); + return channel_manager_->StartDiscovery(participant_); } bool TopologyManager::InitServiceManager() { - return service_manager_->StartDiscovery(participant_->fastrtps_participant()); + return service_manager_->StartDiscovery(participant_); } bool TopologyManager::CreateParticipant() { std::string participant_name = common::GlobalData::Instance()->HostName() + '+' + std::to_string(common::GlobalData::Instance()->ProcessId()); - participant_listener_ = new ParticipantListener(std::bind( - &TopologyManager::OnParticipantChange, this, std::placeholders::_1)); participant_ = std::make_shared( - participant_name, 11511, participant_listener_); + participant_name, 11511, + new ParticipantListener(std::bind(&TopologyManager::OnParticipantChange, + this, std::placeholders::_1))); + if (!participant_->Init()) { + AERROR << "init participant failed"; + return false; + } return true; } -void TopologyManager::OnParticipantChange(const PartInfo& info) { +void TopologyManager::OnParticipantChange( + const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info) { ChangeMsg msg; if (!Convert(info, &msg)) { return; @@ -135,28 +134,39 @@ void TopologyManager::OnParticipantChange(const PartInfo& info) { change_signal_(msg); } -bool TopologyManager::Convert(const PartInfo& info, ChangeMsg* msg) { - auto guid = info.rtps.m_guid; - auto status = info.rtps.m_status; +bool TopologyManager::Convert( + const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info, + ChangeMsg* msg) { + auto guid = info.info.m_guid; std::string participant_name(""); - OperateType opt_type = OperateType::OPT_JOIN; + OperateType opt_type; - switch (status) { - case eprosima::fastrtps::rtps::DISCOVERY_STATUS::DISCOVERED_RTPSPARTICIPANT: - participant_name = info.rtps.m_RTPSParticipantName; + switch (info.status) { + case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: + DISCOVERED_PARTICIPANT: + participant_name = info.info.m_participantName; + AINFO << "discovery participant name:" << participant_name; participant_names_[guid] = participant_name; opt_type = OperateType::OPT_JOIN; break; - - case eprosima::fastrtps::rtps::DISCOVERY_STATUS::REMOVED_RTPSPARTICIPANT: - case eprosima::fastrtps::rtps::DISCOVERY_STATUS::DROPPED_RTPSPARTICIPANT: + case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: + REMOVED_PARTICIPANT: if (participant_names_.find(guid) != participant_names_.end()) { participant_name = participant_names_[guid]; + AINFO << "remove participant name:" << participant_name; + participant_names_.erase(guid); + } + opt_type = OperateType::OPT_LEAVE; + break; + case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: + DROPPED_PARTICIPANT: + if (participant_names_.find(guid) != participant_names_.end()) { + participant_name = participant_names_[guid]; + AINFO << "dropped participant name:" << participant_name; participant_names_.erase(guid); } opt_type = OperateType::OPT_LEAVE; break; - default: break; } diff --git a/cyber/service_discovery/topology_manager.h b/cyber/service_discovery/topology_manager.h index 44b47b5..dd5b23f 100644 --- a/cyber/service_discovery/topology_manager.h +++ b/cyber/service_discovery/topology_manager.h @@ -66,9 +66,9 @@ class TopologyManager { using ChangeSignal = base::Signal; using ChangeFunc = std::function; using ChangeConnection = base::Connection; + using ParticipantPtr = std::shared_ptr; using PartNameContainer = std::map; - using PartInfo = eprosima::fastrtps::ParticipantDiscoveryInfo; virtual ~TopologyManager(); @@ -114,8 +114,10 @@ class TopologyManager { bool InitServiceManager(); bool CreateParticipant(); - void OnParticipantChange(const PartInfo& info); - bool Convert(const PartInfo& info, ChangeMsg* change_msg); + void OnParticipantChange( + const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info); + bool Convert(const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info, + ChangeMsg* change_msg); bool ParseParticipantName(const std::string& participant_name, std::string* host_name, int* process_id); @@ -123,9 +125,7 @@ class TopologyManager { NodeManagerPtr node_manager_; /// shared ptr of NodeManager ChannelManagerPtr channel_manager_; /// shared ptr of ChannelManager ServiceManagerPtr service_manager_; /// shared ptr of ServiceManager - /// rtps participant to publish and subscribe - transport::ParticipantPtr participant_; - ParticipantListener* participant_listener_; + ParticipantPtr participant_; ChangeSignal change_signal_; /// topology changing signal, ///< connect to `ChangeFunc`s PartNameContainer participant_names_; /// other participant in the topology diff --git a/cyber/setup.bash b/cyber/setup.bash index cdabc56..1d0d690 100755 --- a/cyber/setup.bash +++ b/cyber/setup.bash @@ -8,6 +8,7 @@ export CYBER_PATH="${APOLLO_ROOT_DIR}/cyber" bazel_bin_path="${APOLLO_ROOT_DIR}/bazel-bin" mainboard_path="${bazel_bin_path}/cyber/mainboard" cyber_tool_path="${bazel_bin_path}/cyber/tools" +performance_path="${cyber_tool_path}/cyber_performance" recorder_path="${cyber_tool_path}/cyber_recorder" launch_path="${cyber_tool_path}/cyber_launch" channel_path="${cyber_tool_path}/cyber_channel" @@ -20,7 +21,7 @@ visualizer_path="${bazel_bin_path}/modules/tools/visualizer" for entry in "${mainboard_path}" \ "${recorder_path}" "${monitor_path}" \ "${channel_path}" "${node_path}" \ - "${service_path}" \ + "${service_path}" "${performance_path}" \ "${launch_path}" \ "${visualizer_path}" ; do pathprepend "${entry}" @@ -38,9 +39,9 @@ export GLOG_alsologtostderr=0 export GLOG_colorlogtostderr=1 export GLOG_minloglevel=0 -export sysmo_start=0 - # for DEBUG log #export GLOG_v=4 -source ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash +[[ -e ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash ]] && source ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash + +export sysmo_start=0 \ No newline at end of file diff --git a/cyber/statistics/BUILD b/cyber/statistics/BUILD new file mode 100644 index 0000000..6593465 --- /dev/null +++ b/cyber/statistics/BUILD @@ -0,0 +1,19 @@ +load("//tools:cpplint.bzl", "cpplint") +load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package") + +apollo_cc_library( + name = "apollo_statistics", + srcs = ["statistics.cc"], + hdrs = ["statistics.h"], + linkopts = ["-lbvar"], + deps = [ + "//cyber/common:cyber_common", + "//cyber/proto:role_attributes_cc_proto", + "//cyber/time:cyber_time", + "@com_github_gflags_gflags//:gflags", + ], +) + +apollo_package() + +cpplint() diff --git a/cyber/statistics/statistics.cc b/cyber/statistics/statistics.cc new file mode 100644 index 0000000..f786473 --- /dev/null +++ b/cyber/statistics/statistics.cc @@ -0,0 +1,130 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/statistics/statistics.h" + +namespace apollo { +namespace cyber { +namespace statistics { + +Statistics::Statistics() {} + +bool Statistics::RegisterChanVar(const proto::RoleAttributes& role_attr) { + if (latency_map_.find(GetProcLatencyKey(role_attr)) != latency_map_.end()) { + AERROR << "Failed to create proc latency var: " + "reader with the same channel already exists."; + return false; + } + + if (latency_map_.find(GetTranLatencyKey(role_attr)) != latency_map_.end()) { + AERROR << "Failed to create tran latency var: " + "reader with the same channel already exists."; + return false; + } + + if (latency_map_.find(GetCyberLatencyKey(role_attr)) != latency_map_.end()) { + AERROR << "Failed to create cyber latency var: " + "reader with the same channel already exists."; + return false; + } + + latency_map_[GetProcLatencyKey(role_attr)] = + std::make_shared<::bvar::LatencyRecorder>( + role_attr.node_name() + "-" + + role_attr.channel_name(), "proc"); + if (role_attr.channel_name() != TIMER_COMPONENT_CHAN_NAME) { + latency_map_[GetTranLatencyKey(role_attr)] = + std::make_shared<::bvar::LatencyRecorder>( + role_attr.node_name() + "-" + + role_attr.channel_name(), "tran"); + latency_map_[GetCyberLatencyKey(role_attr)] = + std::make_shared<::bvar::LatencyRecorder>( + role_attr.node_name() + "-" + + role_attr.channel_name(), "cyber"); + status_map_[GetStartProcessStatusKey(role_attr)] = + std::make_shared<::bvar::Status>( + role_attr.node_name() + "-" + + role_attr.channel_name() + "-process", 0); + status_map_[GetTotalMsgsStatusKey(role_attr)] = + std::make_shared<::bvar::Status>( + role_attr.node_name() + "-" + + role_attr.channel_name() + "-total-msgs-nums", 0); + adder_map_[GetTotalRecvStatusKey(role_attr)] = + std::make_shared<::bvar::Adder>( + role_attr.node_name() + + "-" + role_attr.channel_name() + "-recv-msgs-nums"); + } + return true; +} + +StatusVarPtr Statistics::GetProcStatusVar( + const proto::RoleAttributes& role_attr) { + auto v = status_map_.find(GetStartProcessStatusKey(role_attr)); + if (v == status_map_.end()) { + return nullptr; + } + return v->second; +} + +LatencyVarPtr Statistics::GetChanProcVar( + const proto::RoleAttributes& role_attr) { + auto v = latency_map_.find(GetProcLatencyKey(role_attr)); + if (v == latency_map_.end()) { + return nullptr; + } + return v->second; +} + +LatencyVarPtr Statistics::GetChanTranVar( + const proto::RoleAttributes& role_attr) { + auto v = latency_map_.find(GetTranLatencyKey(role_attr)); + if (v == latency_map_.end()) { + return nullptr; + } + return v->second; +} + +LatencyVarPtr Statistics::GetChanCyberVar( + const proto::RoleAttributes& role_attr) { + auto v = latency_map_.find(GetCyberLatencyKey(role_attr)); + if (v == latency_map_.end()) { + return nullptr; + } + return v->second; +} + +StatusVarPtr Statistics::GetTotalMsgsStatusVar( + const proto::RoleAttributes& role_attr) { + auto v = status_map_.find(GetTotalMsgsStatusKey(role_attr)); + if (v == status_map_.end()) { + return nullptr; + } + return v->second; +} + +AdderVarPtr Statistics::GetAdderVar( + const proto::RoleAttributes& role_attr) { + auto v = adder_map_.find(GetTotalRecvStatusKey(role_attr)); + if (v == adder_map_.end()) { + return nullptr; + } + return v->second; +} + + +} // namespace statistics +} // namespace cyber +} // namespace apollo diff --git a/cyber/statistics/statistics.h b/cyber/statistics/statistics.h new file mode 100644 index 0000000..3d651da --- /dev/null +++ b/cyber/statistics/statistics.h @@ -0,0 +1,314 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#ifndef CYBER_STATISTICS_STATISTICS_H_ +#define CYBER_STATISTICS_STATISTICS_H_ + +#include + +#include +#include +#include +#include +#include + +#include "cyber/base/macros.h" +#include "cyber/common/log.h" +#include "cyber/proto/role_attributes.pb.h" +#include "cyber/common/macros.h" +#include "cyber/time/time.h" +#include "third_party/var/bvar/bvar.h" + +namespace apollo { +namespace cyber { +namespace statistics { + +using LatencyVarPtr = std::shared_ptr<::bvar::LatencyRecorder>; +using StatusVarPtr = std::shared_ptr<::bvar::Status>; +using AdderVarPtr = std::shared_ptr<::bvar::Adder>; + +struct SpanHandler { + std::string name; + uint64_t start_time; + uint64_t end_time; + std::shared_ptr<::bvar::LatencyRecorder> span_trace_node; + uint64_t min_ns = 0; +}; + +static const std::string TIMER_COMPONENT_CHAN_NAME = "_timer_component"; // NOLINT + +class Statistics { + public: + ~Statistics() {} + bool RegisterChanVar(const proto::RoleAttributes& role_attr); + + inline bool CreateSpan(std::string name, uint64_t min_ns = 0); + inline bool StartSpan(std::string name); + inline bool EndSpan(std::string name); + + inline void DisableChanVar() { + disable_chan_var_ = true; + } + + template + std::shared_ptr<::bvar::Adder> CreateAdder( + const proto::RoleAttributes& role_attr) { + std::string expose_name = + role_attr.node_name() + "-" + role_attr.channel_name(); + return std::make_shared<::bvar::Adder>(expose_name); + } + + template + bool SamplingProcLatency( + const proto::RoleAttributes& role_attr, SampleT sample) { + if (disable_chan_var_) { + return true; + } + auto var_ptr = GetChanProcVar(role_attr); + if (var_ptr != nullptr) { + (*var_ptr) << sample; + } else { + return false; + } + return true; + } + + template + bool SamplingTranLatency( + const proto::RoleAttributes& role_attr, SampleT sample) { + if (disable_chan_var_) { + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return true; + } + auto var_ptr = GetChanTranVar(role_attr); + if (var_ptr != nullptr) { + (*var_ptr) << sample; + } else { + return false; + } + return true; + } + + template + bool SamplingCyberLatency( + const proto::RoleAttributes& role_attr, SampleT sample) { + if (disable_chan_var_) { + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return true; + } + auto var_ptr = GetChanCyberVar(role_attr); + if (var_ptr != nullptr) { + (*var_ptr) << sample; + } else { + return false; + } + return true; + } + + bool SetProcStatus(const proto::RoleAttributes& role_attr, uint64_t val) { + if (disable_chan_var_) { + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return true; + } + auto var_ptr = GetProcStatusVar(role_attr); + if (var_ptr != nullptr) { + var_ptr->set_value(val); + } else { + return false; + } + return true; + } + + bool GetProcStatus(const proto::RoleAttributes& role_attr, uint64_t* val) { + if (disable_chan_var_) { + *val = 0; + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return false; + } + auto var_ptr = GetProcStatusVar(role_attr); + if (var_ptr != nullptr) { + *val = var_ptr->get_value(); + } else { + return false; + } + return true; + } + + bool SetTotalMsgsStatus(const proto::RoleAttributes& role_attr, int32_t val) { + if (disable_chan_var_) { + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return true; + } + auto var_ptr = GetTotalMsgsStatusVar(role_attr); + if (var_ptr != nullptr) { + var_ptr->set_value(val); + } else { + return false; + } + return true; + } + + bool AddRecvCount(const proto::RoleAttributes& role_attr, int total_msg_val) { + if (disable_chan_var_) { + return true; + } + if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { + return true; + } + + auto var_ptr = GetAdderVar(role_attr); + if (var_ptr == nullptr) { + return true; + } + + if cyber_unlikely(first_recv_) { + (*var_ptr) << total_msg_val; + first_recv_ = false; + return true; + } + + (*var_ptr) << 1; + + return true; + } + + private: + LatencyVarPtr GetChanProcVar(const proto::RoleAttributes& role_attr); + + LatencyVarPtr GetChanTranVar(const proto::RoleAttributes& role_attr); + + LatencyVarPtr GetChanCyberVar(const proto::RoleAttributes& role_attr); + + StatusVarPtr GetProcStatusVar(const proto::RoleAttributes& role_attr); + + AdderVarPtr GetAdderVar(const proto::RoleAttributes& role_attr); + + StatusVarPtr GetTotalMsgsStatusVar(const proto::RoleAttributes& role_attr); + + inline uint64_t GetMicroTimeNow() const noexcept; + + inline const std::string GetProcLatencyKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + role_attr.channel_name() + "proc"; + } + + inline const std::string GetTranLatencyKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + role_attr.channel_name() + "tran"; + } + + inline const std::string GetCyberLatencyKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + role_attr.channel_name() + "cyber"; + } + + inline const std::string GetStartProcessStatusKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + \ + role_attr.channel_name() + "process-status"; + } + + inline const std::string GetTotalMsgsStatusKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + \ + role_attr.channel_name() + "total-sended-msgs"; + } + + inline const std::string GetTotalRecvStatusKey( + const proto::RoleAttributes& role_attr) { + return role_attr.node_name() + "-" + role_attr.channel_name() + "recv-msgs"; + } + + std::unordered_map latency_map_; + std::unordered_map status_map_; + std::unordered_map adder_map_; + + std::unordered_map> span_handlers_; + + bool first_recv_ = true; + bool disable_chan_var_ = false; + + DECLARE_SINGLETON(Statistics) +}; + +inline uint64_t Statistics::GetMicroTimeNow() const noexcept { + return Time::Now().ToMicrosecond(); +} + +inline bool Statistics::CreateSpan(std::string name, uint64_t min_ns) { + if (cyber_unlikely(span_handlers_.find(name) != span_handlers_.end())) { + AERROR << "span handler " << name << "has been created!"; + return false; + } + auto handler = std::make_shared(); + handler->name = name; + handler->span_trace_node = std::move( + std::make_shared<::bvar::LatencyRecorder>(name, "user", 1200)); + handler->min_ns = min_ns; + + span_handlers_[name] = std::move(handler); + return true; +} + +inline bool Statistics::StartSpan(std::string name) { + auto it = span_handlers_.find(name); + if (cyber_unlikely(it == span_handlers_.end())) { + AERROR << "span handler " << name << "not found!"; + return false; + } + it->second->start_time = std::move(GetMicroTimeNow()); + return true; +} + +inline bool Statistics::EndSpan(std::string name) { + auto it = span_handlers_.find(name); + if (cyber_unlikely(it == span_handlers_.end())) { + AERROR << "span handler " << name << "not found!"; + return false; + } + it->second->end_time = std::move(GetMicroTimeNow()); + auto handler = it->second; + auto diff = handler->end_time - handler->start_time; + if (cyber_unlikely(diff < handler->min_ns)) { + AWARN << "Time span less than preset value: " \ + << diff << " vs " << handler->min_ns; + return false; + } + if (cyber_unlikely(diff > INT32_MAX)) { + AWARN << "Time span is larger than INT32_MAX: " << diff << ", drop it..."; + return false; + } + *(handler->span_trace_node) << diff; + return true; +} + +} // namespace statistics +} // namespace cyber +} // namespace apollo + +#endif // CYBER_STATISTICS_STATISTICS_H_ diff --git a/cyber/tools/cyber_launch/cyber_launch.py b/cyber/tools/cyber_launch/cyber_launch.py index 7b1df7d..c13d126 100755 --- a/cyber/tools/cyber_launch/cyber_launch.py +++ b/cyber/tools/cyber_launch/cyber_launch.py @@ -25,7 +25,7 @@ import sys import time import threading -import traceback +from datetime import datetime import xml.etree.ElementTree as ET @@ -48,13 +48,39 @@ BOLD_SEQ = "\033[1m" COLORS = { - 'INFO': GREEN, - 'WARNING': YELLOW, - 'DEBUG': BLUE, - 'ERROR': RED, + 'INFO': GREEN, + 'WARNING': YELLOW, + 'DEBUG': BLUE, + 'ERROR': RED, 'CRITICAL': YELLOW } +logger = logging.Logger(__name__) + +# file logger +workspace_path = os.getenv('APOLLO_ENV_WORKROOT') or '/apollo' +log_dir_path = os.path.join(workspace_path, 'data/log') +if not os.path.exists(log_dir_path): + os.makedirs(log_dir_path) +log_name = 'cyber_launch.log.INFO.{}.{}'.format( + datetime.now().strftime("%Y%m%d-%H%M%S"), str(g_process_pid)) +log_file_path = os.path.join(log_dir_path, log_name) +file_formater = logging.Formatter( + '%(levelname)s [%(asctime)s] %(lineno)s: %(message)s') +file_hd = logging.FileHandler(filename=log_file_path) +file_hd.setFormatter(file_formater) +file_hd.setLevel(logging.INFO) +logger.addHandler(file_hd) +link_log_file = os.path.join(log_dir_path, 'cyber_launch.INFO') +try: + if os.path.exists(link_log_file) or os.path.islink(link_log_file): + os.remove(link_log_file) + os.symlink(log_name, link_log_file) +except Exception as e: + # Maybe mulitple process create link, ignore it + pass + + class ColoredFormatter(logging.Formatter): def __init__(self, msg): @@ -79,7 +105,6 @@ def format(self, record): color_formatter = ColoredFormatter("[%(levelname)-18s] %(message)s") console = logging.StreamHandler() console.setFormatter(color_formatter) -logger = logging.Logger(__name__) logger.addHandler(console) @@ -105,17 +130,22 @@ def module_monitor(mod): while True: line = mod.popen.stdout.readline() if line: - logger.debug('%s# %s' % (mod.name, line.decode('utf8').strip('\n'))) + logger.debug('%s# %s' % + (mod.name, line.decode('utf8').strip('\n'))) continue time.sleep(0.01) class ProcessWrapper(object): - def __init__(self, binary_path, dag_num, dag_list, plugin_list, process_name, process_type, - sched_name, extra_args_list, exception_handler='', respawn_limit=g_default_respawn_limit): + def __init__(self, binary_path, dag_num, dag_list, plugin_list, + process_name, process_type, sched_name, extra_args_list, + exception_handler='', respawn_limit=g_default_respawn_limit, + cpu_profile_file='', mem_profile_file='', nice=0): self.time_of_death = None self.started = False + self.cpu_profile = False + self.mem_profile = False self.binary_path = binary_path self.dag_num = dag_num self.dag_list = dag_list @@ -131,6 +161,13 @@ def __init__(self, binary_path, dag_num, dag_list, plugin_list, process_name, pr self.exception_handler = exception_handler self.respawn_limit = respawn_limit self.respawn_cnt = 0 + self.cpu_profile_file = cpu_profile_file + self.mem_profile_file = mem_profile_file + if self.cpu_profile_file != '': + self.cpu_profile = True + if self.mem_profile_file != '': + self.mem_profile = True + self.nice = nice def wait(self, timeout_secs=None): """ @@ -171,11 +208,19 @@ def start(self): args_list.append(self.sched_name) if len(self.extra_args_list) != 0: args_list.extend(self.extra_args_list) + if self.cpu_profile: + args_list.append('-c') + args_list.append('-o') + args_list.append(self.cpu_profile_file) + if self.mem_profile: + args_list.append('-H') + args_list.append('-O') + args_list.append(self.mem_profile_file) self.args = args_list try: - self.popen = subprocess.Popen(args_list, stdout=subprocess.PIPE, + self.popen = subprocess.Popen(args_list, stdout=None, stderr=subprocess.STDOUT) except Exception as err: logger.error('Subprocess Popen exception: ' + str(err)) @@ -185,12 +230,23 @@ def start(self): logger.error('Start process [%s] failed.', self.name) return 2 - th = threading.Thread(target=module_monitor, args=(self, )) - th.setDaemon(True) - th.start() + # th = threading.Thread(target=module_monitor, args=(self, )) + # th.setDaemon(True) + # th.start() self.started = True self.pid = self.popen.pid - logger.info('Start process [%s] successfully. pid: %d', self.name, self.popen.pid) + if self.nice != 0: + sudo_check = subprocess.run( + ['sudo', '-n', 'true'], stdout=None, stderr=None) + if sudo_check.returncode == 0: + subprocess.run( + ["sudo", "renice", "-n", str(self.nice), "-p", str(self.pid)], + stdout=None, stderr=subprocess.STDOUT) + else: + logger.error( + 'Can not renice because users do not have sudo privileges') + logger.info( + 'Start process [%s] successfully. pid: %d', self.name, self.popen.pid) logger.info('-' * 120) return 0 @@ -248,9 +304,11 @@ def register(self, p): @type p: L{Process} """ if self.has_process(p.name): - logger.error('Cannot add process due to duplicate name "%s".', p.name) + logger.error( + 'Cannot add process due to duplicate name "%s".', p.name) elif self.is_shutdown: - logger.error('Cannot add process [%s] due to monitor has been stopped.', p.name) + logger.error( + 'Cannot add process [%s] due to monitor has been stopped.', p.name) else: self.procs.append(p) @@ -274,13 +332,15 @@ def check_cleanup(self): continue if pw.exception_handler == "respawn": if pw.respawn_cnt < pw.respawn_limit: - logger.warning('child process [%s][%d] exit, respawn!', pw.name, pw.pid) + logger.warning( + 'child process [%s][%d] exit, respawn!', pw.name, pw.pid) pw.start() pw.respawn_cnt += 1 else: dead_cnt += 1 elif pw.exception_handler == "exit": - logger.warning('child process [%s][%d] exit, stop all', pw.name, pw.pid) + logger.warning( + 'child process [%s][%d] exit, stop all', pw.name, pw.pid) # stop and exit stop() else: @@ -318,10 +378,12 @@ def stop(self, signal): try: p.wait(force_stop_timeout_secs) except subprocess.TimeoutExpired as e: - logger.warning("Begin force kill process [%s][%s].", p.name, p.pid) + logger.warning( + "Begin force kill process [%s][%s].", p.name, p.pid) p.kill() p.wait() - logger.info('Process [%s] has been stopped. dag_file: %s', p.name, p.dag_list) + logger.info( + 'Process [%s] has been stopped. dag_file: %s', p.name, p.dag_list) # Reset members self.procs = [] self.dead_cnt = 0 @@ -386,37 +448,45 @@ def start(launch_file=''): # start each process for module in root.findall('module'): module_name = get_param_value(module, 'name') - process_name = get_param_value(module, 'process_name', 'mainboard_default_' + str(os.getpid())) + process_name = get_param_value( + module, 'process_name', 'mainboard_default_' + str(os.getpid())) sched_name = get_param_value(module, 'sched_name', 'CYBER_DEFAULT') process_type = get_param_value(module, 'type', 'library') + cpu_profile_file = get_param_value(module, 'cpuprofile') + mem_profile_file = get_param_value(module, 'memprofile') exception_handler = get_param_value(module, 'exception_handler') respawn_limit_txt = get_param_value(module, 'respawn_limit') if respawn_limit_txt.isnumeric(): respawn_limit = int(respawn_limit_txt) else: respawn_limit = g_default_respawn_limit + nice_val = get_param_value(module, 'nice', 0) logger.info('Load module [%s] %s: [%s] [%s] conf, exception_handler: [%s], respawn_limit: [%d]', module_name, process_type, process_name, sched_name, exception_handler, respawn_limit) if process_type == 'binary': if len(process_name) == 0: - logger.error('Start binary failed. Binary process_name is null.') + logger.error( + 'Start binary failed. Binary process_name is null.') continue pw = ProcessWrapper(process_name.split()[0], 0, [""], [], process_name, process_type, - sched_name, [], exception_handler, respawn_limit) + sched_name, [], exception_handler, respawn_limit, nice=nice_val) # Default is library else: dag_list = get_param_list(module, 'dag_conf') if not dag_list: - logger.error('module [%s] library dag conf is null.', module_name) + logger.error( + 'module [%s] library dag conf is null.', module_name) continue plugin_list = get_param_list(module, 'plugin') extra_args_list = [] extra_args = module.attrib.get('extra_args') if extra_args is not None: extra_args_list = extra_args.split() - pw = ProcessWrapper(g_binary_name, 0, dag_list, plugin_list, process_name, process_type, - sched_name, extra_args_list, exception_handler, respawn_limit) + pw = ProcessWrapper(g_binary_name, 0, dag_list, plugin_list, + process_name, process_type, sched_name, + extra_args_list, exception_handler, respawn_limit, + cpu_profile_file, mem_profile_file, nice_val) result = pw.start() if result != 0: logger.error('Start manager [%s] failed. Stop all!', process_name) diff --git a/cyber/tools/cyber_monitor/general_channel_message.cc b/cyber/tools/cyber_monitor/general_channel_message.cc index db43ed3..bb26ef8 100644 --- a/cyber/tools/cyber_monitor/general_channel_message.cc +++ b/cyber/tools/cyber_monitor/general_channel_message.cc @@ -21,6 +21,7 @@ #include #include +#include "cyber/common/global_data.h" #include "cyber/record/record_message.h" #include "cyber/tools/cyber_monitor/general_message.h" #include "cyber/tools/cyber_monitor/screen.h" @@ -121,9 +122,10 @@ GeneralChannelMessage* GeneralChannelMessage::OpenChannel( } auto callback = - [this]( + [this, channel_name]( const std::shared_ptr& raw_msg) { UpdateRawMessage(raw_msg); + UpdateChannelName(channel_name); }; channel_reader_ = diff --git a/cyber/tools/cyber_monitor/general_channel_message.h b/cyber/tools/cyber_monitor/general_channel_message.h index e56f2d4..f16aa85 100644 --- a/cyber/tools/cyber_monitor/general_channel_message.h +++ b/cyber/tools/cyber_monitor/general_channel_message.h @@ -151,6 +151,10 @@ class GeneralChannelMessage : public GeneralMessageBase { channel_message_.reset(); channel_message_ = raw_msg; } + void UpdateChannelName(const std::string& channel_name) { + std::lock_guard _g(inner_lock_); + channel_name_ = channel_name; + } std::shared_ptr CopyMsgPtr(void) const { decltype(channel_message_) channel_msg; @@ -185,6 +189,7 @@ class GeneralChannelMessage : public GeneralMessageBase { std::vector writers_; std::shared_ptr channel_message_; + std::string channel_name_; std::shared_ptr> channel_reader_; mutable std::mutex inner_lock_; diff --git a/cyber/tools/cyber_monitor/main.cc b/cyber/tools/cyber_monitor/main.cc index f7777ea..79fb7db 100644 --- a/cyber/tools/cyber_monitor/main.cc +++ b/cyber/tools/cyber_monitor/main.cc @@ -19,6 +19,7 @@ #include "cyber/init.h" #include "cyber/service_discovery/topology_manager.h" +#include "cyber/task/task.h" #include "cyber/tools/cyber_monitor/cyber_topology_message.h" #include "cyber/tools/cyber_monitor/general_channel_message.h" #include "cyber/tools/cyber_monitor/screen.h" @@ -82,8 +83,7 @@ int main(int argc, char *argv[]) { case HELP: printHelp(argv[0]); return 0; - default: { - } + default: {} } apollo::cyber::Init(argv[0]); @@ -95,12 +95,18 @@ int main(int argc, char *argv[]) { auto topology_callback = [&topology_msg](const apollo::cyber::proto::ChangeMsg &change_msg) { - topology_msg.TopologyChanged(change_msg); + apollo::cyber::Async([&topology_msg, change_msg] { + topology_msg.TopologyChanged(change_msg); + }); }; auto channel_manager = apollo::cyber::service_discovery::TopologyManager::Instance() ->channel_manager(); + if (channel_manager == nullptr) { + AERROR << "Cyber Service Discovery is not ready."; + return -1; + } channel_manager->AddChangeListener(topology_callback); std::vector role_vec; diff --git a/cyber/tools/cyber_performance/BUILD b/cyber/tools/cyber_performance/BUILD new file mode 100644 index 0000000..1e68ff3 --- /dev/null +++ b/cyber/tools/cyber_performance/BUILD @@ -0,0 +1,13 @@ +load("//tools/proto:proto.bzl", "apollo_py_binary") +load("//tools:apollo_package.bzl", "apollo_package") + +package( + default_visibility = ["//visibility:public"], +) + +apollo_py_binary( + name = "cyber_performance", + srcs = ["cyber_performance.py"], +) + +apollo_package() \ No newline at end of file diff --git a/cyber/tools/cyber_performance/cyber_performance.launch b/cyber/tools/cyber_performance/cyber_performance.launch new file mode 100755 index 0000000..2fe3b88 --- /dev/null +++ b/cyber/tools/cyber_performance/cyber_performance.launch @@ -0,0 +1,11 @@ + + + cyber_performance + + binary + + cyber_performance + + respawn + + \ No newline at end of file diff --git a/cyber/tools/cyber_performance/cyber_performance.py b/cyber/tools/cyber_performance/cyber_performance.py new file mode 100644 index 0000000..d0f4a05 --- /dev/null +++ b/cyber/tools/cyber_performance/cyber_performance.py @@ -0,0 +1,789 @@ +#!/usr/bin/env python3 +# **************************************************************************** +# Copyright 2024 The Apollo Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# **************************************************************************** + +import time +import json +import os +import re +import threading +import platform +import subprocess +from queue import Queue +from datetime import datetime +from flask import Flask, jsonify, render_template_string +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler +from cyber.python.cyber_py3 import cyber + +app = Flask(__name__) +data_history = { + "time": Queue(maxsize = 20), + "data": {}, +} +today = datetime.now() +data_lock = threading.Lock() +if 'APOLLO_ENV_WORKROOT' in os.environ: + DIRECTORY_TO_WATCH = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "dumps") + PERFORMANCE_TO_WRITE = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "data") +else: + DIRECTORY_TO_WATCH = os.path.join("/apollo", "dumps") + PERFORMANCE_TO_WRITE = os.path.join("/apollo", "data") +if not os.path.exists(DIRECTORY_TO_WATCH): + os.mkdir(DIRECTORY_TO_WATCH) +if not os.path.exists(PERFORMANCE_TO_WRITE): + os.mkdir(PERFORMANCE_TO_WRITE) +dumps_fio = open( + os.path.join(PERFORMANCE_TO_WRITE, + "performance_dumps.{}.json".format(today.strftime("%m-%d-%Y"))), "a+") +sample_times = 0 +response = {} +update_time = 5000 +chasis_channle = "/apollo/canbus/chassis" +iface_path = "/sys/class/net" +autodrive = False +machine = platform.machine() +nethogs_buf = "" +process_network_io = {} +network_data_lock = threading.Lock() + +sudo_prv = subprocess.run( + ['sudo', '-n', 'true'], stdout=None, stderr=None).returncode == 0 + +remove_list = [] +for i in os.listdir(DIRECTORY_TO_WATCH): + if i.startswith("performance_dumps"): + date_str = i.split(".")[1] + try: + file_save_date = datetime.strptime(date_str, "%m-%d-%Y") + except: + remove_list.append(os.path.join(DIRECTORY_TO_WATCH, i)) + continue + if (today - file_save_date).days > 30: + remove_list.append(os.path.join(DIRECTORY_TO_WATCH, i)) +for i in remove_list: + os.remove(i) + +cyber_instance = None +debounce_period = 1 +last_modified = {} + +class CyberChannelecho(object): + + def __init__(self, channel_name): + cyber.init() + self.pattern = r"driving_mode:\s*(\w+)" + self.channel_name = channel_name + self.node = cyber.Node("listener_node_echo") + self.node.create_rawdata_reader(channel_name, self.callback) + + def callback(self, raw_data): + global autodrive + msgtype = cyber.ChannelUtils.get_msgtype(self.channel_name, 0).decode('utf-8') + text = cyber.ChannelUtils.get_debugstring_rawmsgdata(msgtype, raw_data).decode('utf-8') + match = re.search(self.pattern, text) + if match: + ret = match.group(1) + if ret == "COMPLETE_AUTO_DRIVE": + autodrive = True + else: + autodrive = False + +def cyber_task(): + global cyber_instance + cyber_instance = CyberChannelecho(chasis_channle) + +def watcher_run(): + global DIRECTORY_TO_WATCH + event_handler = Handler() + observer = Observer() + + observer.schedule(event_handler, DIRECTORY_TO_WATCH) + observer.start() + try: + while True: + time.sleep(5) + except KeyboardInterrupt: + observer.stop() + observer.join() + +def gpu_memory_usage(pid): + gpu_mem_kernel_file = "/sys/kernel/debug/nvmap/iovmm/maps" + gpu_mem = 0 + + if pid == -1: + return gpu_mem + if machine == "aarch64": + total, processes = read_process_table(gpu_mem_kernel_file) + if total is not None: + for p in processes: + if pid == int(p[0]): + gpu_mem = int(p[3]) + break + else: + query_cmd = "nvidia-smi --query-compute-apps=pid,used_memory --format=csv,noheader,nounits" + p = subprocess.run(query_cmd, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip().splitlines() + for line in stdout: + eles = [i.strip() for i in line.split(",")] + if len(eles) < 2: + break + if int(eles[0]) == pid: + gpu_mem = int(eles[1]) + break + return gpu_mem + +def read_process_table(path_table): + """ + This method list all processes working with GPU + + ========== ============ ======== ============= + user process PID size + ========== ============ ======== ============= + user name process number dictionary + ========== ============ ======== ============= + + :return: list of all processes + :type spin: list + """ + if not os.path.exists(path_table): + return None, None + if not os.access(path_table, os.R_OK): + return None, None + MEM_TABLE_REG = re.compile(r'^(?P\w+)\s+(?P[^ ]+)\s+(?P\d+)\s+(?P\d+)(?P\w)\n') + TOT_TABLE_REG = re.compile(r'total\s+(?P\d+)(?P\w)') + + table = [] + total = {} + with open(path_table, "r") as fp: + for line in fp: + # Search line + match = re.search(MEM_TABLE_REG, line) + if match: + parsed_line = match.groupdict() + data = [ + parsed_line['PID'], + parsed_line['user'], + parsed_line['process'], + int(parsed_line['size']), + ] + table += [data] + continue + # Find total on table + match = re.search(TOT_TABLE_REG, line) + if match: + parsed_line = match.groupdict() + total = int(parsed_line['size']) + continue + # return total and table + return total, table + +class Handler(FileSystemEventHandler): + @staticmethod + def on_any_event(event): + global data_history + global data_lock + global autodrive + global network_data_lock, process_network_io + + if event.is_directory: + return None + + elif event.event_type == 'created' or event.event_type == 'modified': + if not event.src_path.endswith(".system.data"): + return None + + current_time = time.time() + last_mod_time = last_modified.get(event.src_path, 0) + + if current_time - last_mod_time <= debounce_period: + return None + else: + last_modified[event.src_path] = current_time + + print(f'Event type: {event.event_type} path : {event.src_path}') + file_name = event.src_path.replace(DIRECTORY_TO_WATCH + "/", "") + process_name = file_name.replace(".system.data", "") + pid_file_name = event.src_path.replace(".system.data", ".data") + latency_file_name = event.src_path.replace(".system.data", ".latency.data") + while True: + with open(event.src_path, 'r') as f: + current_data = {} + current_data["autodrive"] = autodrive + contents = f.read().split("\n") + if len(contents) == 0: + continue + elif len(contents) == 1 and contents[0] == "": + continue + for line in contents: + if line == "": + continue + instance = line.strip().split(" : ") + if len(instance) == 1: + continue + + if instance[0].endswith("cpu_usage"): + current_data["BASIC - cpu_usage(%, single-core)"] = float(instance[1]) * 100 + elif instance[0].endswith("memory_resident"): + current_data["BASIC - memory(MB)"] = int(instance[1]) / 1024 / 1024 + elif instance[0].endswith("disk_read_bytes_second"): + current_data["BLOCK_DEVICE_IO - block_device_io_read(rkB/s)"] = int(instance[1]) / 1024 + elif instance[0].endswith("disk_write_bytes_second"): + current_data["BLOCK_DEVICE_IO - block_device_io_write(wkB/s)"] = int(instance[1]) / 1024 + else: + continue + break + pid = -1 + + with open(pid_file_name, "r") as pf: + contents = pf.readlines() + for line in contents: + if line == "": + continue + instance = line.strip().split(" : ") + if len(instance) == 1: + continue + if instance[0].endswith("_pid"): + pid = int(instance[1]) + break + gpu_mem = gpu_memory_usage(pid) + + with open(latency_file_name, "r") as lf: + contents = lf.readlines() + has_proc_info = False + for line in contents: + if "proc_latency :" in line: + instance = line.split(" : ") + latency_name = instance[0].replace("mainboard_", "") + latency_val = float((instance[1].strip())) / 1000 + else: + continue + has_proc_info = True + current_data[f"E2E_LATENCY - {latency_name}(ms)"] = latency_val + if not has_proc_info: + return + with network_data_lock: + if pid in process_network_io: + current_data["ETHERNET_DEVICE_IO - ethernet_device_io_write(wkB/s)"] = process_network_io[pid]["tx"] + current_data["ETHERNET_DEVICE_IO - ethernet_device_io_read(rkB/s)"] = process_network_io[pid]["rx"] + else: + current_data["ETHERNET_DEVICE_IO - ethernet_device_io_write(wkB/s)"] = 0 + current_data["ETHERNET_DEVICE_IO - ethernet_device_io_read(rkB/s)"] = 0 + + current_data["BASIC - gpu_memory(MB)"] = gpu_mem / 1024 + + with data_lock: + if process_name not in data_history["data"]: + data_history["data"][process_name] = {} + data_history["data"][process_name]["time"] = Queue(maxsize = 20) + + for key in current_data: + if key not in data_history["data"][process_name]: + data_history["data"][process_name][key] = Queue(maxsize = 20) + + time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") + if data_history["data"][process_name]["time"].full(): + data_history["data"][process_name]["time"].get() + data_history["data"][process_name]["time"].put(time_format) + + for key, value in current_data.items(): + if data_history["data"][process_name][key].full(): + data_history["data"][process_name][key].get() + data_history["data"][process_name][key].put(value) + + +def sample_task(): + global data_history + global sample_times + global dumps_fio + global response + global autodrive + + p = subprocess.run( + "which tegrastats", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + tegrastats = None + if p.returncode == 0: + tegrastats = p.stdout.decode("utf-8").strip() + + system_info = { + "system-cpu": Queue(maxsize = 20), + "system-memory": Queue(maxsize = 20), + "system-gpu": Queue(maxsize = 20), + "time": Queue(maxsize = 20), + "system-io-usage": Queue(maxsize = 20), + "autodrive": Queue(maxsize = 20), + "block-device-io" : {}, + "ethernet-device-io": {} + } + + while True: + sample_times = sample_times + 1 + system_cpu = None + system_memory = None + system_gpu = None + system_io_usage = None + if tegrastats is not None: + time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") + p = subprocess.run( + " ".join(["timeout", "2", tegrastats]), shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip() + + cpu_usage_pattern = re.compile(r'\bCPU \[(.*?)\]') + match_result = cpu_usage_pattern.findall(stdout) + if len(match_result) > 0: + usages = re.findall(r'(\d+)%@', match_result[0]) + system_cpu = 0 + for usage in usages: + system_cpu += float(usage) + system_cpu = system_cpu / len(usages) + + gpu_usage_pattern = re.compile(r'GR3D_FREQ (\d+)%') + match_result = gpu_usage_pattern.findall(stdout) + if len(match_result) > 0: + system_gpu = float(match_result[0]) + + p = subprocess.run( + "vmstat 1 2 | awk '{print $16}' | tail -n 1", shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip() + system_io_usage = float(stdout) + else: + p = subprocess.run( + "top -bn2 | grep Cpu | awk '{print $8}' | tail -n 1", shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip() + time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") + system_cpu = 100 - float(stdout) + + system_gpu = 0 + + p = subprocess.run( + "vmstat | awk '{print $16}' | tail -n 1", shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip() + system_io_usage = float(stdout) + p = subprocess.run("cat /proc/meminfo", + shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip().splitlines() + meminfo = {} + for i in stdout: + k, v = i.split(":")[0].strip().lower(), i.split(":")[1].strip() + value = round(int(v.strip().split(' ')[0]) / 1024, 2) + meminfo[k] = value + + total = meminfo["memtotal"] + buffers = meminfo["buffers"] + cached = meminfo["cached"] + sreclaimable = meminfo["sreclaimable"] + free = meminfo["memfree"] + shm = meminfo["shmem"] + if "memavailable" not in meminfo: + used_without_shm = total - buffers - cached - sreclaimable + used = used_without_shm + shm + else: + available = meminfo["memavailable"] + used = total - available + system_memory = used + + if system_cpu is not None \ + and system_gpu is not None \ + and system_memory is not None \ + and system_io_usage is not None: + if system_info["time"].full(): + system_info["time"].get() + system_info["time"].put(time_format) + if system_info["system-cpu"].full(): + system_info["system-cpu"].get() + system_info["system-cpu"].put(system_cpu) + if system_info["system-gpu"].full(): + system_info["system-gpu"].get() + system_info["system-gpu"].put(system_gpu) + if system_info["system-memory"].full(): + system_info["system-memory"].get() + system_info["system-memory"].put(system_memory) + if system_info["system-io-usage"].full(): + system_info["system-io-usage"].get() + system_info["system-io-usage"].put(system_io_usage) + if system_info["autodrive"].full(): + system_info["autodrive"].get() + system_info["autodrive"].put(autodrive) + + p = subprocess.run( + "lsblk -o NAME,TYPE,SIZE,TRAN --json", shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip() + blk_devices = json.loads(stdout) + blk_monitor_devices = [] + try: + for dev in blk_devices["blockdevices"]: + if dev["type"] != "disk": + continue + + if dev["tran"] == "nvme" or dev["tran"] == "sata": + blk_monitor_devices.append(dev["name"]) + elif dev["tran"] == "null" and "children" in dev: + blk_monitor_devices.append(dev["name"]) + blk_monitor_devices = list(filter( + lambda x: os.path.exists(f"/dev/{x}"), blk_monitor_devices)) + except Exception as ex: + blk_monitor_devices = [] + + if len(blk_monitor_devices) > 0: + for dev in blk_monitor_devices: + if dev not in system_info["block-device-io"]: + system_info["block-device-io"][dev] = { + "rkB/s": Queue(maxsize = 20), + "wkB/s": Queue(maxsize = 20), + "r/s": Queue(maxsize = 20), + "w/s": Queue(maxsize = 20), + "r_await": Queue(maxsize = 20), + "w_await": Queue(maxsize = 20), + "aqu-sz": Queue(maxsize = 20) + } + + query_devices = " ".join(blk_monitor_devices) + stat_length = len(blk_monitor_devices) + 1 + query_cmd = f"iostat -xk 1 2 {query_devices} | grep -v '^$' | tail -n {stat_length}" + + p = subprocess.run(query_cmd, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip().splitlines() + + monitor_items = list(filter(lambda x: x != "", stdout[0].split(" "))) + for i in range(1, len(stdout)): + dev_res = list(filter(lambda x: x != "", stdout[i].split(" "))) + dev_name = dev_res[0] + for j in range(1, len(monitor_items)): + if monitor_items[j] not in system_info["block-device-io"][dev_name]: + continue + monitor_item = monitor_items[j] + if system_info["block-device-io"][dev_name][monitor_item].full(): + system_info["block-device-io"][dev_name][monitor_item].get() + system_info["block-device-io"][dev_name][monitor_item].put(dev_res[j]) + + eth_devices = [] + for i in os.listdir(iface_path): + if os.path.exists(os.path.join(iface_path, i, "device", "driver")): + eth_devices.append(i) + if len(eth_devices) > 0: + for dev in eth_devices: + if dev not in system_info["ethernet-device-io"]: + system_info["ethernet-device-io"][dev] = { + "rxkB/s": Queue(maxsize = 20), + "txkB/s": Queue(maxsize = 20), + "%ifutil": Queue(maxsize = 20) + } + query_cmd = "sar -n DEV 1 1 | grep --color=never Average" + p = subprocess.run(query_cmd, shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout = p.stdout.decode("utf-8").strip().splitlines() + + monitor_items = list(filter(lambda x: x != "", stdout[0].split(" "))) + for i in range(1, len(stdout)): + dev_res = list(filter(lambda x: x != "", stdout[i].split(" "))) + dev_name = dev_res[1] + if dev_name not in system_info["ethernet-device-io"]: + continue + for j in range(2, len(monitor_items)): + if monitor_items[j] not in system_info["ethernet-device-io"][dev_name]: + continue + monitor_item = monitor_items[j] + if system_info["ethernet-device-io"][dev_name][monitor_item].full(): + system_info["ethernet-device-io"][dev_name][monitor_item].get() + system_info["ethernet-device-io"][dev_name][monitor_item].put(dev_res[j]) + + # system metrics + response = { + "data": {"system": {}} + } + + # status + response["data"]["system"]["time"] = list(system_info["time"].queue) + response["data"]["system"]["autodrive"] = list(system_info["autodrive"].queue) + + # basic performance metrics + response["data"]["system"]["BASIC - system - cpu_usage(%, all-core)"] = list(system_info["system-cpu"].queue) + response["data"]["system"]["BASIC - system - gpu_usage(%)"] = list(system_info["system-gpu"].queue) + response["data"]["system"]["BASIC - system - memory(MB)"] = list(system_info["system-memory"].queue) + + # io metrics + response["data"]["system"]["BLOCK_DEVICE_IO - system - io_wait_usage(%)"] = list(system_info["system-io-usage"].queue) + for dev in system_info["block-device-io"]: + for io_metric in system_info["block-device-io"][dev]: + response["data"]["system"][f"BLOCK_DEVICE_IO - {dev} - {io_metric}"] = \ + list(system_info["block-device-io"][dev][io_metric].queue) + for dev in system_info["ethernet-device-io"]: + for io_metric in system_info["ethernet-device-io"][dev]: + response["data"]["system"][f"ETHERNET_DEVICE_IO - {dev} - {io_metric}"] = \ + list(system_info["ethernet-device-io"][dev][io_metric].queue) + + # process metrics + for p in data_history["data"]: + response["data"][p] = {} + for monitor_instance in data_history["data"][p]: + response["data"][p][monitor_instance] = list( + data_history["data"][p][monitor_instance].queue) + + if sample_times >= 20: + dumps_fio.write(json.dumps(response)) + dumps_fio.write('\n') + dumps_fio.flush() + sample_times = 0 + + time.sleep(update_time / 1000) +@app.route('/get_data', methods=['GET']) +def get_data(): + global response + + return jsonify(response) + +@app.route('/') +def index(): + return render_template_string(''' + + + + + + cyber_performance + + + + + + +
+ + + + + + ''') + +if __name__ == '__main__': + system_sample_thread = threading.Thread(target=sample_task) + system_sample_thread.daemon = True + system_sample_thread.start() + + watchdog_thread = threading.Thread(target=watcher_run) + watchdog_thread.daemon = True + watchdog_thread.start() + + if sudo_prv: + nethogs_process = subprocess.Popen( + ['sudo', 'nethogs', '-t'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE, bufsize=1, universal_newlines=True) + + def parse_nethogs_output(): + global nethogs_buf, process_network_io, network_data_lock + for line in iter(nethogs_process.stdout.readline, ''): + if line.startswith("Refreshing:"): + with network_data_lock: + process_network_io = {} + nethogs_buf_list = list(filter(lambda x: x!= "", nethogs_buf.split("\n"))) + for i in nethogs_buf_list: + raw_line = list(filter(lambda x: x != "", i.split(" "))) + raw_process_info = raw_line[0].split("\t") + process_info = raw_process_info[0].split("/") + if len(process_info) < 3 or int(process_info[-2]) == 0: + continue + process_network_io[int(process_info[-2])] = {} + process_network_io[int(process_info[-2])]["rx"] = float(raw_process_info[2]) + process_network_io[int(process_info[-2])]["tx"] = float(raw_process_info[1]) + nethogs_buf = "" + else: + nethogs_buf = nethogs_buf + line + + network_sample_thread = threading.Thread(target=parse_nethogs_output) + network_sample_thread.daemon = True + network_sample_thread.start() + + cyber_task() + + app.run(host="0.0.0.0", threaded=True) + diff --git a/cyber/tools/cyber_recorder/BUILD b/cyber/tools/cyber_recorder/BUILD index a53af19..14c1e0f 100644 --- a/cyber/tools/cyber_recorder/BUILD +++ b/cyber/tools/cyber_recorder/BUILD @@ -8,7 +8,11 @@ apollo_cc_binary( srcs = [ "main.cc", ], - linkopts = ["-pthread"], + linkopts = [ + "-pthread", + "-lprofiler", + "-ltcmalloc", + ], deps = [ ":recorder", "//cyber", @@ -34,7 +38,7 @@ apollo_cc_library( "//cyber", "//cyber/common:cyber_common", "//cyber/proto:record_cc_proto", - "@fastrtps", + "@fastdds", ], ) diff --git a/cyber/tools/cyber_recorder/main.cc b/cyber/tools/cyber_recorder/main.cc index b43396b..1136b98 100644 --- a/cyber/tools/cyber_recorder/main.cc +++ b/cyber/tools/cyber_recorder/main.cc @@ -15,12 +15,15 @@ *****************************************************************************/ #include +#include #include +#include #include #include #include #include +#include "cyber/common/environment.h" #include "cyber/common/file.h" #include "cyber/common/time_conversion.h" #include "cyber/init.h" @@ -30,6 +33,11 @@ #include "cyber/tools/cyber_recorder/recoverer.h" #include "cyber/tools/cyber_recorder/spliter.h" +#include "gflags/gflags.h" +#include "gperftools/heap-profiler.h" +#include "gperftools/malloc_extension.h" +#include "gperftools/profiler.h" + using apollo::cyber::common::GetFileName; using apollo::cyber::common::StringToUnixSeconds; using apollo::cyber::common::UnixSecondsToString; @@ -42,7 +50,7 @@ using apollo::cyber::record::Recoverer; using apollo::cyber::record::Spliter; const char INFO_OPTIONS[] = "h"; -const char RECORD_OPTIONS[] = "o:ac:k:i:m:h"; +const char RECORD_OPTIONS[] = "o:ac:k:i:m:hCH"; const char PLAY_OPTIONS[] = "f:ac:k:lr:b:e:s:d:p:h"; const char SPLIT_OPTIONS[] = "f:o:c:k:b:e:h"; const char RECOVER_OPTIONS[] = "f:o:h"; @@ -148,6 +156,13 @@ void DisplayUsage(const std::string& binary, const std::string& command, case 'h': std::cout << "\t-h, --help\t\t\t\tshow help message" << std::endl; break; + case 'H': + std::cout << "\t-H, --heap-profule\t\t\t\tprofile heap info" + << std::endl; + break; + case 'C': + std::cout << "\t-C, --cpu-profule\t\t\t\tprofile cpu info" << std::endl; + break; case ':': break; default: @@ -170,7 +185,7 @@ int main(int argc, char** argv) { } int long_index = 0; - const std::string short_opts = "f:c:k:o:alr:b:e:s:d:p:i:m:h"; + const std::string short_opts = "f:c:k:o:alr:b:e:s:d:p:i:m:hCH"; static const struct option long_opts[] = { {"files", required_argument, nullptr, 'f'}, {"white-channel", required_argument, nullptr, 'c'}, @@ -186,12 +201,16 @@ int main(int argc, char** argv) { {"preload", required_argument, nullptr, 'p'}, {"segment-interval", required_argument, nullptr, 'i'}, {"segment-size", required_argument, nullptr, 'm'}, - {"help", no_argument, nullptr, 'h'}}; + {"help", no_argument, nullptr, 'h'}, + {"cpu-profile", no_argument, nullptr, 'C'}, + {"heap-profule", no_argument, nullptr, 'H'}}; std::vector opt_file_vec; std::vector opt_output_vec; std::vector opt_white_channels; std::vector opt_black_channels; + static bool enable_cpu_profile = false; + static bool enable_heap_profile = false; bool opt_all = false; bool opt_loop = false; float opt_rate = 1.0f; @@ -209,11 +228,37 @@ int main(int argc, char** argv) { break; } switch (opt) { + case 'C': + enable_cpu_profile = true; + break; + case 'H': + enable_heap_profile = true; + break; case 'f': - opt_file_vec.emplace_back(std::string(optarg)); + if (!apollo::cyber::common::PathIsAbsolute(std::string(optarg))) { + auto opt_file_abs_path = + apollo::cyber::common::GetEnv("PWD") + "/" + std::string(optarg); + if (apollo::cyber::common::PathExists(opt_file_abs_path)) { + opt_file_vec.emplace_back(opt_file_abs_path); + } else { + opt_file_vec.emplace_back(std::string(optarg)); + } + } else { + opt_file_vec.emplace_back(std::string(optarg)); + } for (int i = optind; i < argc; i++) { if (*argv[i] != '-') { - opt_file_vec.emplace_back(std::string(argv[i])); + if (!apollo::cyber::common::PathIsAbsolute(std::string(argv[i]))) { + auto opt_file_abs_path = apollo::cyber::common::GetEnv("PWD") + + "/" + std::string(argv[i]); + if (apollo::cyber::common::PathExists(opt_file_abs_path)) { + opt_file_vec.emplace_back(opt_file_abs_path); + } else { + opt_file_vec.emplace_back(std::string(argv[i])); + } + } else { + opt_file_vec.emplace_back(std::string(argv[i])); + } } else { break; } @@ -240,7 +285,13 @@ int main(int argc, char** argv) { } break; case 'o': - opt_output_vec.push_back(std::string(optarg)); + if (!apollo::cyber::common::PathIsAbsolute(std::string(optarg))) { + auto opt_output_file_abs_path = + apollo::cyber::common::GetEnv("PWD") + "/" + std::string(optarg); + opt_output_vec.push_back(opt_output_file_abs_path); + } else { + opt_output_vec.push_back(std::string(optarg)); + } break; case 'a': opt_all = true; @@ -360,6 +411,13 @@ int main(int argc, char** argv) { std::cout << "usage: cyber_recorder info file" << std::endl; return -1; } + if (!apollo::cyber::common::PathIsAbsolute(file_path)) { + auto file_path_abs = + apollo::cyber::common::GetEnv("PWD") + "/" + std::string(file_path); + if (std::filesystem::exists(file_path_abs)) { + file_path = file_path_abs; + } + } ::apollo::cyber::Init(argv[0]); Info info; bool info_result = info.Display(file_path); @@ -388,7 +446,7 @@ int main(int argc, char** argv) { std::cout << "MUST specify file option (-f)." << std::endl; return -1; } - ::apollo::cyber::Init(argv[0]); + ::apollo::cyber::Init(argv[0], "cyber_recorder"); PlayParam play_param; play_param.is_play_all_channels = opt_all || opt_white_channels.empty(); play_param.is_loop_playback = opt_loop; @@ -419,6 +477,7 @@ int main(int argc, char** argv) { } if (opt_output_vec.empty()) { std::string default_output_file = + apollo::cyber::common::GetEnv("PWD") + "/" + UnixSecondsToString(time(nullptr), "%Y%m%d%H%M%S") + ".record"; opt_output_vec.push_back(default_output_file); } @@ -426,6 +485,35 @@ int main(int argc, char** argv) { auto recorder = std::make_shared(opt_output_vec[0], opt_all, opt_white_channels, opt_black_channels, opt_header); + std::signal(SIGTERM, [](int sig) { + apollo::cyber::OnShutdown(sig); + if (enable_cpu_profile) { + ProfilerStop(); + } + if (enable_heap_profile) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } + }); + + std::signal(SIGINT, [](int sig) { + apollo::cyber::OnShutdown(sig); + if (enable_cpu_profile) { + ProfilerStop(); + } + if (enable_heap_profile) { + HeapProfilerDump("Befor shutdown"); + HeapProfilerStop(); + } + }); + + auto base_name = std::string(argv[0]) + std::string(".prof"); + if (enable_cpu_profile) { + ProfilerStart(base_name.c_str()); + } + if (enable_heap_profile) { + HeapProfilerStart(base_name.c_str()); + } bool record_result = recorder->Start(); if (record_result) { while (!::apollo::cyber::IsShutdown()) { diff --git a/cyber/transport/BUILD b/cyber/transport/BUILD index eb81b20..1e920a0 100644 --- a/cyber/transport/BUILD +++ b/cyber/transport/BUILD @@ -1,53 +1,105 @@ load("//tools:cpplint.bzl", "cpplint") -load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package", "apollo_cc_test") +load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") package(default_visibility = ["//visibility:public"]) apollo_cc_library( name = "cyber_transport", srcs = [ - 'transport.cc', 'shm/segment.cc', 'shm/condition_notifier.cc', - 'shm/segment_factory.cc', 'shm/posix_segment.cc', 'shm/state.cc', - 'shm/multicast_notifier.cc', 'shm/block.cc', 'shm/shm_conf.cc', - 'shm/xsi_segment.cc', 'shm/readable_info.cc', 'shm/notifier_factory.cc', - 'qos/qos_profile_conf.cc', 'common/identity.cc', 'common/endpoint.cc', - 'dispatcher/intra_dispatcher.cc', 'dispatcher/shm_dispatcher.cc', - 'dispatcher/rtps_dispatcher.cc', 'dispatcher/dispatcher.cc', - 'message/message_info.cc', 'rtps/participant.cc', 'rtps/attributes_filler.cc', - 'rtps/sub_listener.cc', 'rtps/underlay_message_type.cc', - 'rtps/underlay_message.cc' + "common/endpoint.cc", + "common/identity.cc", + "dispatcher/dispatcher.cc", + "dispatcher/intra_dispatcher.cc", + "dispatcher/rtps_dispatcher.cc", + "dispatcher/subscriber_listener.cc", + "dispatcher/shm_dispatcher.cc", + "message/message_info.cc", + "qos/qos_profile_conf.cc", + "qos/qos_filler.cc", + "rtps/attributes_filler.cc", + "rtps/participant.cc", + "rtps/publisher.cc", + "rtps/subscriber.cc", + "rtps/underlay_message.cc", + "rtps/underlay_message_type.cc", + "shm/arena_address_allocator.cc", + "shm/block.cc", + "shm/condition_notifier.cc", + "shm/multicast_notifier.cc", + "shm/notifier_factory.cc", + "shm/posix_segment.cc", + "shm/protobuf_arena_manager.cc", + "shm/readable_info.cc", + "shm/segment.cc", + "shm/segment_factory.cc", + "shm/shm_conf.cc", + "shm/state.cc", + "shm/xsi_segment.cc", + "transport.cc", ], hdrs = [ - 'transport.h', 'shm/state.h', 'shm/xsi_segment.h', - 'shm/notifier_factory.h', 'shm/block.h', 'shm/shm_conf.h', - 'shm/readable_info.h', 'shm/posix_segment.h', 'shm/segment_factory.h', - 'shm/multicast_notifier.h', 'shm/segment.h', 'shm/notifier_base.h', - 'shm/condition_notifier.h', 'qos/qos_profile_conf.h', 'common/identity.h', - 'common/endpoint.h', 'receiver/hybrid_receiver.h', 'receiver/shm_receiver.h', - 'receiver/receiver.h', 'receiver/intra_receiver.h', 'receiver/rtps_receiver.h', - 'transmitter/rtps_transmitter.h', 'transmitter/transmitter.h', - 'transmitter/shm_transmitter.h', 'transmitter/hybrid_transmitter.h', - 'transmitter/intra_transmitter.h', 'dispatcher/dispatcher.h', - 'dispatcher/intra_dispatcher.h', 'dispatcher/rtps_dispatcher.h', - 'dispatcher/shm_dispatcher.h', 'message/history.h', 'message/listener_handler.h', - 'message/history_attributes.h', 'message/message_info.h', - 'rtps/attributes_filler.h', 'rtps/underlay_message.h', 'rtps/participant.h', - 'rtps/sub_listener.h', 'rtps/underlay_message_type.h' + "common/endpoint.h", + "common/identity.h", + "common/common_type.h", + "dispatcher/dispatcher.h", + "dispatcher/intra_dispatcher.h", + "dispatcher/rtps_dispatcher.h", + "dispatcher/shm_dispatcher.h", + "dispatcher/subscriber_listener.h", + "message/history.h", + "message/history_attributes.h", + "message/listener_handler.h", + "message/message_info.h", + "qos/qos_profile_conf.h", + "qos/qos_filler.h", + "receiver/hybrid_receiver.h", + "receiver/intra_receiver.h", + "receiver/receiver.h", + "receiver/rtps_receiver.h", + "receiver/shm_receiver.h", + "rtps/attributes_filler.h", + "rtps/participant.h", + "rtps/subscriber.h", + "rtps/publisher.h", + "rtps/underlay_message.h", + "rtps/underlay_message_type.h", + "shm/arena_address_allocator.h", + "shm/block.h", + "shm/condition_notifier.h", + "shm/multicast_notifier.h", + "shm/notifier_base.h", + "shm/notifier_factory.h", + "shm/posix_segment.h", + "shm/protobuf_arena_manager.h", + "shm/readable_info.h", + "shm/segment.h", + "shm/segment_factory.h", + "shm/shm_conf.h", + "shm/state.h", + "shm/xsi_segment.h", + "transmitter/hybrid_transmitter.h", + "transmitter/intra_transmitter.h", + "transmitter/rtps_transmitter.h", + "transmitter/shm_transmitter.h", + "transmitter/transmitter.h", + "transport.h", ], linkopts = ["-lrt"], deps = [ - "@fastrtps", - "@uuid", - "//cyber/service_discovery:cyber_service_discovery_role", - "//cyber/task:cyber_task", + "//cyber/base:cyber_base", "//cyber/common:cyber_common", - "//cyber/proto:role_attributes_cc_proto", + "//cyber/event:cyber_event", "//cyber/message:cyber_message", "//cyber/proto:proto_desc_cc_proto", - "//cyber/scheduler:cyber_scheduler", "//cyber/proto:qos_profile_cc_proto", - "//cyber/base:cyber_base", - "//cyber/event:cyber_event", + "//cyber/proto:role_attributes_cc_proto", + "//cyber/scheduler:cyber_scheduler", + "//cyber/service_discovery:cyber_service_discovery_role", + "//cyber/service_discovery:subscriber_listener", + "//cyber/statistics:apollo_statistics", + "//cyber/task:cyber_task", + "@fastdds", + "@uuid", ], ) @@ -55,12 +107,12 @@ apollo_cc_test( name = "condition_notifier_test", size = "small", srcs = ["shm/condition_notifier_test.cc"], + linkstatic = True, tags = ["exclusive"], deps = [ "//cyber", "@com_google_googletest//:gtest_main", ], - linkstatic = True, ) apollo_cc_test( @@ -70,7 +122,7 @@ apollo_cc_test( deps = [ "//cyber", "@com_google_googletest//:gtest_main", - "@fastrtps", + "@fastdds", ], ) @@ -78,22 +130,22 @@ apollo_cc_test( name = "message_info_test", size = "small", srcs = ["message/message_info_test.cc"], + linkstatic = True, deps = [ "//cyber", "@com_google_googletest//:gtest_main", ], - linkstatic = True, ) apollo_cc_test( name = "message_test", size = "small", srcs = ["message/message_test.cc"], + linkstatic = True, deps = [ "//cyber", "@com_google_googletest//:gtest_main", ], - linkstatic = True, ) apollo_cc_test( @@ -172,4 +224,5 @@ apollo_cc_test( ) apollo_package() + cpplint() diff --git a/cyber/transport/common/common_type.h b/cyber/transport/common/common_type.h new file mode 100644 index 0000000..b60365c --- /dev/null +++ b/cyber/transport/common/common_type.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_TRANSPORT_RTPS_COMMON_TYPE_H +#define CYBER_TRANSPORT_RTPS_COMMON_TYPE_H + +#include +#include +#include + +#include "cyber/transport/message/message_info.h" +namespace apollo { +namespace cyber { +namespace transport { +namespace rtps { +using subsciber_callback = + std::function& msg_str, + uint64_t channel_id, const MessageInfo& msg_info)>; +} // namespace rtps +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif // CYBER_TRANSPORT_RTPS_COMMON_TYPE_H diff --git a/cyber/transport/dispatcher/dispatcher.h b/cyber/transport/dispatcher/dispatcher.h index e37c366..0ea54ef 100644 --- a/cyber/transport/dispatcher/dispatcher.h +++ b/cyber/transport/dispatcher/dispatcher.h @@ -25,11 +25,12 @@ #include #include +#include "cyber/proto/role_attributes.pb.h" + #include "cyber/base/atomic_hash_map.h" #include "cyber/base/atomic_rw_lock.h" #include "cyber/common/global_data.h" #include "cyber/common/log.h" -#include "cyber/proto/role_attributes.pb.h" #include "cyber/transport/message/listener_handler.h" #include "cyber/transport/message/message_info.h" diff --git a/cyber/transport/dispatcher/intra_dispatcher.h b/cyber/transport/dispatcher/intra_dispatcher.h index 37bc046..82a40b0 100644 --- a/cyber/transport/dispatcher/intra_dispatcher.h +++ b/cyber/transport/dispatcher/intra_dispatcher.h @@ -29,6 +29,8 @@ #include "cyber/common/macros.h" #include "cyber/message/message_traits.h" #include "cyber/message/raw_message.h" +#include "cyber/statistics/statistics.h" +#include "cyber/time/time.h" #include "cyber/transport/dispatcher/dispatcher.h" namespace apollo { @@ -357,9 +359,12 @@ void IntraDispatcher::AddListener(const RoleAttributes& self_attr, auto handler = GetHandler(self_attr.channel_id()); if (handler && created) { - auto listener_wrapper = [this, self_id, channel_id, message_type]( + auto listener_wrapper = + [this, self_id, channel_id, message_type, self_attr]( const std::shared_ptr& message, const MessageInfo& message_info) { + auto recv_time = Time::Now().ToMicrosecond(); + statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); this->chain_->Run(self_id, channel_id, message_type, message, message_info); }; @@ -385,9 +390,12 @@ void IntraDispatcher::AddListener(const RoleAttributes& self_attr, auto handler = GetHandler(self_attr.channel_id()); if (handler && created) { - auto listener_wrapper = [this, self_id, oppo_id, channel_id, message_type]( + auto listener_wrapper = + [this, self_id, oppo_id, channel_id, message_type, self_attr]( const std::shared_ptr& message, const MessageInfo& message_info) { + auto recv_time = Time::Now().ToMicrosecond(); + statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); this->chain_->Run(self_id, oppo_id, channel_id, message_type, message, message_info); }; diff --git a/cyber/transport/dispatcher/rtps_dispatcher.cc b/cyber/transport/dispatcher/rtps_dispatcher.cc index 7e7da27..f2f494e 100644 --- a/cyber/transport/dispatcher/rtps_dispatcher.cc +++ b/cyber/transport/dispatcher/rtps_dispatcher.cc @@ -16,6 +16,11 @@ #include "cyber/transport/dispatcher/rtps_dispatcher.h" +#include "cyber/common/log.h" +#include "cyber/statistics/statistics.h" +#include "cyber/transport/common/endpoint.h" +#include "cyber/transport/dispatcher/dispatcher.h" + namespace apollo { namespace cyber { namespace transport { @@ -32,7 +37,7 @@ void RtpsDispatcher::Shutdown() { { std::lock_guard lock(subs_mutex_); for (auto& item : subs_) { - item.second.sub = nullptr; + item.second = nullptr; } } @@ -47,25 +52,27 @@ void RtpsDispatcher::AddSubscriber(const RoleAttributes& self_attr) { uint64_t channel_id = self_attr.channel_id(); std::lock_guard lock(subs_mutex_); + // subscriber exsit if (subs_.count(channel_id) > 0) { return; } - Subscriber new_sub; - eprosima::fastrtps::SubscriberAttributes sub_attr; + auto listener_adapter = + [this, self_attr](const std::shared_ptr& msg_str, + uint64_t channel_id, const MessageInfo& msg_info) { + statistics::Statistics::Instance()->AddRecvCount(self_attr, + msg_info.seq_num()); + statistics::Statistics::Instance()->SetTotalMsgsStatus( + self_attr, msg_info.seq_num()); + this->OnMessage(channel_id, msg_str, msg_info); + }; + auto& qos = self_attr.qos_profile(); - RETURN_IF(!AttributesFiller::FillInSubAttr(self_attr.channel_name(), qos, - &sub_attr)); - - new_sub.sub_listener = std::make_shared( - std::bind(&RtpsDispatcher::OnMessage, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3)); - - new_sub.sub = eprosima::fastrtps::Domain::createSubscriber( - participant_->fastrtps_participant(), sub_attr, - new_sub.sub_listener.get()); - RETURN_IF_NULL(new_sub.sub); - subs_[channel_id] = new_sub; + auto subscriber_ptr = participant_->CreateSubscriber(self_attr.channel_name(), + qos, listener_adapter); + RETURN_IF_NULL(subscriber_ptr); + + subs_[channel_id] = subscriber_ptr; } void RtpsDispatcher::OnMessage(uint64_t channel_id, diff --git a/cyber/transport/dispatcher/rtps_dispatcher.h b/cyber/transport/dispatcher/rtps_dispatcher.h index 656fea2..e73d571 100644 --- a/cyber/transport/dispatcher/rtps_dispatcher.h +++ b/cyber/transport/dispatcher/rtps_dispatcher.h @@ -17,6 +17,7 @@ #ifndef CYBER_TRANSPORT_DISPATCHER_RTPS_DISPATCHER_H_ #define CYBER_TRANSPORT_DISPATCHER_RTPS_DISPATCHER_H_ +#include #include #include #include @@ -26,25 +27,25 @@ #include "cyber/common/log.h" #include "cyber/common/macros.h" #include "cyber/message/message_traits.h" +#include "cyber/statistics/statistics.h" +#include "cyber/time/time.h" #include "cyber/transport/dispatcher/dispatcher.h" +#include "cyber/transport/dispatcher/subscriber_listener.h" +#include "cyber/transport/qos/qos_filler.h" #include "cyber/transport/rtps/attributes_filler.h" #include "cyber/transport/rtps/participant.h" -#include "cyber/transport/rtps/sub_listener.h" +#include "cyber/transport/rtps/subscriber.h" namespace apollo { namespace cyber { namespace transport { -struct Subscriber { - Subscriber() : sub(nullptr), sub_listener(nullptr) {} - - eprosima::fastrtps::Subscriber* sub; - SubListenerPtr sub_listener; -}; - class RtpsDispatcher; using RtpsDispatcherPtr = RtpsDispatcher*; +using ParticipantPtr = + std::shared_ptr; + class RtpsDispatcher : public Dispatcher { public: virtual ~RtpsDispatcher(); @@ -60,7 +61,7 @@ class RtpsDispatcher : public Dispatcher { const RoleAttributes& opposite_attr, const MessageListener& listener); - void set_participant(const ParticipantPtr& participant) { + void SetParticipant(const ParticipantPtr& participant) { participant_ = participant; } @@ -70,7 +71,9 @@ class RtpsDispatcher : public Dispatcher { const MessageInfo& msg_info); void AddSubscriber(const RoleAttributes& self_attr); // key: channel_id - std::unordered_map subs_; + std::unordered_map> + subs_; std::mutex subs_mutex_; ParticipantPtr participant_; @@ -81,11 +84,23 @@ class RtpsDispatcher : public Dispatcher { template void RtpsDispatcher::AddListener(const RoleAttributes& self_attr, const MessageListener& listener) { - auto listener_adapter = [listener]( + auto listener_adapter = [listener, self_attr]( const std::shared_ptr& msg_str, const MessageInfo& msg_info) { auto msg = std::make_shared(); RETURN_IF(!message::ParseFromString(*msg_str, msg.get())); + uint64_t recv_time = Time::Now().ToNanosecond(); + uint64_t send_time = msg_info.send_time(); + if (send_time > recv_time) { + AWARN << "The message is received (" << recv_time + << ") earlier than the message is sent (" << send_time << ")"; + } else { + uint64_t diff = recv_time - send_time; + // sample transport latency in microsecond + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); listener(msg, msg_info); }; @@ -97,11 +112,23 @@ template void RtpsDispatcher::AddListener(const RoleAttributes& self_attr, const RoleAttributes& opposite_attr, const MessageListener& listener) { - auto listener_adapter = [listener]( + auto listener_adapter = [listener, self_attr]( const std::shared_ptr& msg_str, const MessageInfo& msg_info) { auto msg = std::make_shared(); RETURN_IF(!message::ParseFromString(*msg_str, msg.get())); + uint64_t recv_time = Time::Now().ToNanosecond(); + uint64_t send_time = msg_info.send_time(); + if (send_time > recv_time) { + AWARN << "The message is received (" << recv_time + << ") earlier than the message is sent (" << send_time << ")"; + } else { + uint64_t diff = recv_time - send_time; + // sample transport latency in microsecond + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); listener(msg, msg_info); }; diff --git a/cyber/transport/dispatcher/shm_dispatcher.cc b/cyber/transport/dispatcher/shm_dispatcher.cc index 9032870..383091f 100644 --- a/cyber/transport/dispatcher/shm_dispatcher.cc +++ b/cyber/transport/dispatcher/shm_dispatcher.cc @@ -15,6 +15,7 @@ *****************************************************************************/ #include "cyber/transport/dispatcher/shm_dispatcher.h" + #include "cyber/common/global_data.h" #include "cyber/common/util.h" #include "cyber/scheduler/scheduler_factory.h" @@ -54,6 +55,7 @@ void ShmDispatcher::AddSegment(const RoleAttributes& self_attr) { auto segment = SegmentFactory::CreateSegment(channel_id); segments_[channel_id] = segment; previous_indexes_[channel_id] = UINT32_MAX; + arena_previous_indexes_[channel_id] = UINT32_MAX; } void ShmDispatcher::ReadMessage(uint64_t channel_id, uint32_t block_index) { @@ -82,6 +84,32 @@ void ShmDispatcher::ReadMessage(uint64_t channel_id, uint32_t block_index) { segments_[channel_id]->ReleaseReadBlock(*rb); } +void ShmDispatcher::ReadArenaMessage(uint64_t channel_id, + uint32_t arena_block_index) { + ADEBUG << "Reading sharedmem arena message: " + << GlobalData::GetChannelById(channel_id) + << " from block: " << arena_block_index; + auto rb = std::make_shared(); + rb->index = arena_block_index; + if (!segments_[channel_id]->AcquireArenaBlockToRead(rb.get())) { + AWARN << "fail to acquire block, channel: " + << GlobalData::GetChannelById(channel_id) + << " index: " << arena_block_index; + return; + } + + MessageInfo msg_info; + const char* msg_info_addr = + reinterpret_cast(rb->buf) + rb->block->msg_size(); + if (msg_info.DeserializeFrom(msg_info_addr, rb->block->msg_info_size())) { + OnArenaMessage(channel_id, rb, msg_info); + } else { + AERROR << "error msg info of channel:" + << GlobalData::GetChannelById(channel_id); + } + segments_[channel_id]->ReleaseArenaReadBlock(*rb); +} + void ShmDispatcher::OnMessage(uint64_t channel_id, const std::shared_ptr& rb, const MessageInfo& msg_info) { @@ -94,8 +122,29 @@ void ShmDispatcher::OnMessage(uint64_t channel_id, *handler_base); handler->Run(rb, msg_info); } else { - AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) - << "'s handler."; + if (!arena_msg_listeners_.Get(channel_id, &handler_base)) { + AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) + << "'s handler."; + } + } +} + +void ShmDispatcher::OnArenaMessage(uint64_t channel_id, + const std::shared_ptr& rb, + const MessageInfo& msg_info) { + if (is_shutdown_.load()) { + return; + } + ListenerHandlerBasePtr* handler_base = nullptr; + if (arena_msg_listeners_.Get(channel_id, &handler_base)) { + auto handler = std::dynamic_pointer_cast>( + *handler_base); + handler->Run(rb, msg_info); + } else { + if (!msg_listeners_.Get(channel_id, &handler_base)) { + AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) + << "'s handler."; + } } } @@ -113,33 +162,57 @@ void ShmDispatcher::ThreadFunc() { } uint64_t channel_id = readable_info.channel_id(); - uint32_t block_index = readable_info.block_index(); + int32_t block_index = readable_info.block_index(); + int32_t arena_block_index = readable_info.arena_block_index(); { ReadLockGuard lock(segments_lock_); if (segments_.count(channel_id) == 0) { continue; } - // check block index - if (previous_indexes_.count(channel_id) == 0) { - previous_indexes_[channel_id] = UINT32_MAX; - } - uint32_t& previous_index = previous_indexes_[channel_id]; - if (block_index != 0 && previous_index != UINT32_MAX) { - if (block_index == previous_index) { - ADEBUG << "Receive SAME index " << block_index << " of channel " - << channel_id; - } else if (block_index < previous_index) { - ADEBUG << "Receive PREVIOUS message. last: " << previous_index - << ", now: " << block_index; - } else if (block_index - previous_index > 1) { - ADEBUG << "Receive JUMP message. last: " << previous_index - << ", now: " << block_index; + + if (block_index != -1) { + // check block index + if (previous_indexes_.count(channel_id) == 0) { + previous_indexes_[channel_id] = UINT32_MAX; } + uint32_t& previous_index = previous_indexes_[channel_id]; + if (block_index != 0 && previous_index != UINT32_MAX) { + if (block_index == previous_index) { + ADEBUG << "Receive SAME index " << block_index << " of channel " + << channel_id; + } else if (block_index < previous_index) { + ADEBUG << "Receive PREVIOUS message. last: " << previous_index + << ", now: " << block_index; + } else if (block_index - previous_index > 1) { + ADEBUG << "Receive JUMP message. last: " << previous_index + << ", now: " << block_index; + } + } + previous_index = block_index; + ReadMessage(channel_id, block_index); } - previous_index = block_index; - ReadMessage(channel_id, block_index); + if (arena_block_index != -1) { + if (arena_previous_indexes_.count(channel_id) == 0) { + arena_previous_indexes_[channel_id] = UINT32_MAX; + } + uint32_t& arena_previous_index = arena_previous_indexes_[channel_id]; + if (arena_block_index != 0 && arena_previous_index != UINT32_MAX) { + if (arena_block_index == arena_previous_index) { + ADEBUG << "Receive SAME index " << arena_block_index + << " of channel " << channel_id; + } else if (arena_block_index < arena_previous_index) { + ADEBUG << "Receive PREVIOUS message. last: " << arena_previous_index + << ", now: " << arena_block_index; + } else if (arena_block_index - arena_previous_index > 1) { + ADEBUG << "Receive JUMP message. last: " << arena_previous_index + << ", now: " << arena_block_index; + } + } + arena_previous_index = arena_block_index; + ReadArenaMessage(channel_id, arena_block_index); + } } } } @@ -149,6 +222,7 @@ bool ShmDispatcher::Init() { notifier_ = NotifierFactory::CreateNotifier(); thread_ = std::thread(&ShmDispatcher::ThreadFunc, this); scheduler::Instance()->SetInnerThreadAttr("shm_disp", &thread_); + // statistics::Statistics::Instance()->CreateSpan("protobuf_parse_time"); return true; } diff --git a/cyber/transport/dispatcher/shm_dispatcher.h b/cyber/transport/dispatcher/shm_dispatcher.h index 35d8f03..da29289 100644 --- a/cyber/transport/dispatcher/shm_dispatcher.h +++ b/cyber/transport/dispatcher/shm_dispatcher.h @@ -27,9 +27,14 @@ #include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/common/macros.h" +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/message_traits.h" +#include "cyber/message/raw_message.h" +#include "cyber/statistics/statistics.h" +#include "cyber/time/time.h" #include "cyber/transport/dispatcher/dispatcher.h" #include "cyber/transport/shm/notifier_factory.h" +#include "cyber/transport/shm/protobuf_arena_manager.h" #include "cyber/transport/shm/segment_factory.h" namespace apollo { @@ -60,17 +65,32 @@ class ShmDispatcher : public Dispatcher { const RoleAttributes& opposite_attr, const MessageListener& listener); + template + void AddArenaListener(const RoleAttributes& self_attr, + const MessageListener& listener); + + template + void AddArenaListener(const RoleAttributes& self_attr, + const RoleAttributes& opposite_attr, + const MessageListener& listener); + private: void AddSegment(const RoleAttributes& self_attr); void ReadMessage(uint64_t channel_id, uint32_t block_index); void OnMessage(uint64_t channel_id, const std::shared_ptr& rb, const MessageInfo& msg_info); + void ReadArenaMessage(uint64_t channel_id, uint32_t arena_block_index); + void OnArenaMessage(uint64_t channel_id, + const std::shared_ptr& rb, + const MessageInfo& msg_info); void ThreadFunc(); bool Init(); uint64_t host_id_; SegmentContainer segments_; std::unordered_map previous_indexes_; + std::unordered_map arena_previous_indexes_; + AtomicHashMap arena_msg_listeners_; AtomicRWLock segments_lock_; std::thread thread_; NotifierPtr notifier_; @@ -78,19 +98,174 @@ class ShmDispatcher : public Dispatcher { DECLARE_SINGLETON(ShmDispatcher) }; +template +void ShmDispatcher::AddArenaListener( + const RoleAttributes& self_attr, + const MessageListener& listener) { + if (is_shutdown_.load()) { + return; + } + uint64_t channel_id = self_attr.channel_id(); + + std::shared_ptr> handler; + ListenerHandlerBasePtr* handler_base = nullptr; + if (arena_msg_listeners_.Get(channel_id, &handler_base)) { + handler = + std::dynamic_pointer_cast>(*handler_base); + if (handler == nullptr) { + AERROR << "please ensure that readers with the same channel[" + << self_attr.channel_name() + << "] in the same process have the same message type"; + return; + } + } else { + ADEBUG << "new reader for channel:" + << GlobalData::GetChannelById(channel_id); + handler.reset(new ListenerHandler()); + arena_msg_listeners_.Set(channel_id, handler); + } + handler->Connect(self_attr.id(), listener); +} + +template +void ShmDispatcher::AddArenaListener( + const RoleAttributes& self_attr, const RoleAttributes& opposite_attr, + const MessageListener& listener) { + if (is_shutdown_.load()) { + return; + } + uint64_t channel_id = self_attr.channel_id(); + std::shared_ptr> handler; + ListenerHandlerBasePtr* handler_base = nullptr; + if (arena_msg_listeners_.Get(channel_id, &handler_base)) { + handler = + std::dynamic_pointer_cast>(*handler_base); + if (handler == nullptr) { + AERROR << "please ensuore that readers with the same channel[" + << self_attr.channel_name() + << "] in the same process have the same message type"; + return; + } + } else { + ADEBUG << "new reader for channel:" + << GlobalData::GetChannelById(channel_id); + handler.reset(new ListenerHandler()); + arena_msg_listeners_.Set(channel_id, handler); + } + handler->Connect(self_attr.id(), listener); +} + template void ShmDispatcher::AddListener(const RoleAttributes& self_attr, const MessageListener& listener) { // FIXME: make it more clean - auto listener_adapter = [listener](const std::shared_ptr& rb, - const MessageInfo& msg_info) { - auto msg = std::make_shared(); - RETURN_IF(!message::ParseFromArray( - rb->buf, static_cast(rb->block->msg_size()), msg.get())); - listener(msg, msg_info); - }; - - Dispatcher::AddListener(self_attr, listener_adapter); + if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( + self_attr.channel_id()) && + self_attr.message_type() != message::MessageType() && + self_attr.message_type() != + message::MessageType()) { + auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& rb, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + // TODO(ALL): read config from msg_info + auto arena_manager = ProtobufArenaManager::Instance(); + auto msg_wrapper = arena_manager->CreateMessageWrapper(); + memcpy(msg_wrapper->GetData(), rb->buf, 1024); + MessageT* msg_p; + if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(), + &msg_p)) { + AERROR << "ParseFromArenaMessageWrapper failed"; + } + // msg->CopyFrom(*msg_p); + // msg = arena_manager->LoadMessage(msg_wrapper.get()) + auto segment = arena_manager->GetSegment(self_attr.channel_id()); + auto msg_addr = reinterpret_cast(msg_p); + msg.reset(reinterpret_cast(msg_addr), + [arena_manager, segment, msg_wrapper](MessageT* p) { + // fprintf(stderr, "msg deleter invoked\n"); + // auto related_blocks = + // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + // for (auto block_index : related_blocks) { + // // segment->ReleaseBlockForReadByIndex(block_index); + // segment->RemoveBlockReadLock(block_index); + // } + }); + auto related_blocks_for_lock = + arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + for (int i = 0; i < related_blocks_for_lock.size(); ++i) { + auto block_index = related_blocks_for_lock[i]; + if (!segment->AddBlockReadLock(block_index)) { + AWARN << "failed to acquire block for read, channel: " + << self_attr.channel_id() << " index: " << block_index; + for (int j = 0; j < i; ++j) { + // restore the lock + segment->RemoveBlockReadLock(related_blocks_for_lock[j]); + } + return; + } + } + + auto send_time = msg_info.send_time(); + + statistics::Statistics::Instance()->AddRecvCount(self_attr, + msg_info.seq_num()); + statistics::Statistics::Instance()->SetTotalMsgsStatus( + self_attr, msg_info.seq_num()); + + auto recv_time = Time::Now().ToNanosecond(); + + // sampling in microsecond + auto tran_diff = (recv_time - send_time) / 1000; + if (tran_diff > 0) { + // sample transport latency in microsecond + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, tran_diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, + recv_time / 1000); + listener(msg, msg_info); + auto related_blocks = + arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + for (auto block_index : related_blocks) { + // segment->ReleaseBlockForReadByIndex(block_index); + segment->RemoveBlockReadLock(block_index); + } + }; + + AddArenaListener(self_attr, listener_adapter); + } else { + auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& rb, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + // TODO(ALL): read config from msg_info + RETURN_IF(!message::ParseFromArray( + rb->buf, static_cast(rb->block->msg_size()), msg.get())); + + auto send_time = msg_info.send_time(); + + statistics::Statistics::Instance()->AddRecvCount(self_attr, + msg_info.seq_num()); + statistics::Statistics::Instance()->SetTotalMsgsStatus( + self_attr, msg_info.seq_num()); + + auto recv_time = Time::Now().ToNanosecond(); + + // sampling in microsecond + auto tran_diff = (recv_time - send_time) / 1000; + if (tran_diff > 0) { + // sample transport latency in microsecond + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, tran_diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, + recv_time / 1000); + listener(msg, msg_info); + }; + + Dispatcher::AddListener(self_attr, listener_adapter); + } AddSegment(self_attr); } @@ -99,16 +274,112 @@ void ShmDispatcher::AddListener(const RoleAttributes& self_attr, const RoleAttributes& opposite_attr, const MessageListener& listener) { // FIXME: make it more clean - auto listener_adapter = [listener](const std::shared_ptr& rb, - const MessageInfo& msg_info) { - auto msg = std::make_shared(); - RETURN_IF(!message::ParseFromArray( - rb->buf, static_cast(rb->block->msg_size()), msg.get())); - listener(msg, msg_info); - }; - - Dispatcher::AddListener(self_attr, opposite_attr, - listener_adapter); + if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( + self_attr.channel_id()) && + self_attr.message_type() != message::MessageType() && + self_attr.message_type() != + message::MessageType()) { + auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& rb, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + auto arena_manager = ProtobufArenaManager::Instance(); + auto msg_wrapper = arena_manager->CreateMessageWrapper(); + memcpy(msg_wrapper->GetData(), rb->buf, 1024); + MessageT* msg_p; + if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(), + &msg_p)) { + AERROR << "ParseFromArenaMessageWrapper failed"; + } + // msg->CopyFrom(*msg_p); + // msg = arena_manager->LoadMessage(msg_wrapper.get()) + auto segment = arena_manager->GetSegment(self_attr.channel_id()); + auto msg_addr = reinterpret_cast(msg_p); + msg.reset(reinterpret_cast(msg_addr), + [arena_manager, segment, msg_wrapper](MessageT* p) { + // fprintf(stderr, "msg deleter invoked\n"); + // auto related_blocks = + // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + // for (auto block_index : related_blocks) { + // // segment->ReleaseBlockForReadByIndex(block_index); + // segment->RemoveBlockReadLock(block_index); + // } + }); + auto related_blocks_for_lock = + arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + for (int i = 0; i < related_blocks_for_lock.size(); ++i) { + auto block_index = related_blocks_for_lock[i]; + if (!segment->AddBlockReadLock(block_index)) { + AWARN << "failed to acquire block for read, channel: " + << self_attr.channel_id() << " index: " << block_index; + for (int j = 0; j < i; ++j) { + // restore the lock + segment->RemoveBlockReadLock(related_blocks_for_lock[j]); + } + return; + } + } + + auto send_time = msg_info.send_time(); + + statistics::Statistics::Instance()->AddRecvCount(self_attr, + msg_info.seq_num()); + statistics::Statistics::Instance()->SetTotalMsgsStatus( + self_attr, msg_info.seq_num()); + + auto recv_time = Time::Now().ToNanosecond(); + + // sampling in microsecond + auto tran_diff = (recv_time - send_time) / 1000; + if (tran_diff > 0) { + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, tran_diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, + recv_time / 1000); + + listener(msg, msg_info); + auto related_blocks = + arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + for (auto block_index : related_blocks) { + // segment->ReleaseBlockForReadByIndex(block_index); + segment->RemoveBlockReadLock(block_index); + } + }; + + AddArenaListener(self_attr, opposite_attr, listener_adapter); + } else { + auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& rb, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + RETURN_IF(!message::ParseFromArray( + rb->buf, static_cast(rb->block->msg_size()), msg.get())); + + auto send_time = msg_info.send_time(); + auto msg_seq_num = msg_info.seq_num(); + + statistics::Statistics::Instance()->AddRecvCount(self_attr, msg_seq_num); + statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr, + msg_seq_num); + + auto recv_time = Time::Now().ToNanosecond(); + + // sampling in microsecond + auto tran_diff = (recv_time - send_time) / 1000; + if (tran_diff > 0) { + statistics::Statistics::Instance()->SamplingTranLatency( + self_attr, tran_diff); + } + statistics::Statistics::Instance()->SetProcStatus(self_attr, + recv_time / 1000); + + listener(msg, msg_info); + }; + + Dispatcher::AddListener(self_attr, opposite_attr, + listener_adapter); + } AddSegment(self_attr); } diff --git a/cyber/transport/dispatcher/shm_dispatcher_test.cc b/cyber/transport/dispatcher/shm_dispatcher_test.cc index 2c7cee5..fa5f6e5 100644 --- a/cyber/transport/dispatcher/shm_dispatcher_test.cc +++ b/cyber/transport/dispatcher/shm_dispatcher_test.cc @@ -20,7 +20,6 @@ #include "gtest/gtest.h" #include "cyber/common/global_data.h" -#include "cyber/common/log.h" #include "cyber/common/util.h" #include "cyber/init.h" #include "cyber/message/raw_message.h" diff --git a/cyber/transport/dispatcher/subscriber_listener.cc b/cyber/transport/dispatcher/subscriber_listener.cc new file mode 100644 index 0000000..6254ed1 --- /dev/null +++ b/cyber/transport/dispatcher/subscriber_listener.cc @@ -0,0 +1,76 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/transport/dispatcher/subscriber_listener.h" + +#include "cyber/common/log.h" +#include "cyber/transport/message/message_info.h" + +namespace apollo { +namespace cyber { +namespace transport { +namespace dispatcher { + +SubscriberListener::SubscriberListener(const rtps::subsciber_callback& callback) + : callback_(callback) {} + +SubscriberListener::~SubscriberListener() {} + +void SubscriberListener::on_data_available( + eprosima::fastdds::dds::DataReader* reader) { + RETURN_IF_NULL(reader); + RETURN_IF_NULL(callback_); + + // fetch channel name + auto channel_id = common::Hash(reader->get_topicdescription()->get_name()); + eprosima::fastdds::dds::SampleInfo m_info; + UnderlayMessage m; + + while (reader->take_next_sample(reinterpret_cast(&m), &m_info) == + eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { + if (m_info.valid_data) { + char* ptr = reinterpret_cast( + &m_info.related_sample_identity.writer_guid()); + Identity sender_id(false); + sender_id.set_data(ptr); + msg_info_.set_sender_id(sender_id); + + Identity spare_id(false); + spare_id.set_data(ptr + ID_SIZE); + msg_info_.set_spare_id(spare_id); + + msg_info_.set_seq_num(m.seq()); + msg_info_.set_send_time(m.timestamp()); + // callback + callback_(std::make_shared(m.data()), channel_id, msg_info_); + } else { + AERROR << "Remote writer for topic " + << reader->get_topicdescription()->get_name() << " is dead"; + } + } +} + +void SubscriberListener::on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) { + (void)reader; + (void)info; +} + +} // namespace dispatcher +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/rtps/sub_listener.h b/cyber/transport/dispatcher/subscriber_listener.h similarity index 54% rename from cyber/transport/rtps/sub_listener.h rename to cyber/transport/dispatcher/subscriber_listener.h index fc16abf..f379fa9 100644 --- a/cyber/transport/rtps/sub_listener.h +++ b/cyber/transport/dispatcher/subscriber_listener.h @@ -14,8 +14,8 @@ * limitations under the License. *****************************************************************************/ -#ifndef CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ -#define CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ +#ifndef CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ +#define CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ #include #include @@ -23,42 +23,43 @@ #include #include +#include "cyber/base/macros.h" + +#include "fastdds/dds/subscriber/DataReader.hpp" +#include "fastdds/dds/subscriber/SampleInfo.hpp" +#include "fastdds/dds/subscriber/SubscriberListener.hpp" +#include "fastdds/dds/topic/TopicDescription.hpp" + +#include "cyber/common/util.h" #include "cyber/transport/message/message_info.h" +#include "cyber/transport/common/common_type.h" #include "cyber/transport/rtps/underlay_message.h" #include "cyber/transport/rtps/underlay_message_type.h" -#include "fastrtps/Domain.h" -#include "fastrtps/subscriber/SampleInfo.h" -#include "fastrtps/subscriber/Subscriber.h" -#include "fastrtps/subscriber/SubscriberListener.h" namespace apollo { namespace cyber { namespace transport { - -class SubListener; -using SubListenerPtr = std::shared_ptr; - -class SubListener : public eprosima::fastrtps::SubscriberListener { +namespace dispatcher { +class SubscriberListener : public eprosima::fastdds::dds::SubscriberListener { public: - using NewMsgCallback = std::function& msg_str, - const MessageInfo& msg_info)>; - - explicit SubListener(const NewMsgCallback& callback); - virtual ~SubListener(); + explicit SubscriberListener(const rtps::subsciber_callback& callback); + virtual ~SubscriberListener(); - void onNewDataMessage(eprosima::fastrtps::Subscriber* sub); - void onSubscriptionMatched(eprosima::fastrtps::Subscriber* sub, - eprosima::fastrtps::MatchingInfo& info); // NOLINT + void on_data_available(eprosima::fastdds::dds::DataReader* reader) override; + void on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) + override; // NOLINT private: - NewMsgCallback callback_; + rtps::subsciber_callback callback_; MessageInfo msg_info_; std::mutex mutex_; }; +} // namespace dispatcher } // namespace transport } // namespace cyber } // namespace apollo -#endif // CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ +#endif // CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ diff --git a/cyber/transport/message/listener_handler.h b/cyber/transport/message/listener_handler.h index b4b662a..a99051d 100644 --- a/cyber/transport/message/listener_handler.h +++ b/cyber/transport/message/listener_handler.h @@ -25,6 +25,7 @@ #include "cyber/base/atomic_rw_lock.h" #include "cyber/base/signal.h" #include "cyber/common/log.h" +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/message_traits.h" #include "cyber/message/raw_message.h" #include "cyber/transport/message/message_info.h" diff --git a/cyber/transport/message/message_info.cc b/cyber/transport/message/message_info.cc index 185375e..00fe0ae 100644 --- a/cyber/transport/message/message_info.cc +++ b/cyber/transport/message/message_info.cc @@ -24,7 +24,9 @@ namespace apollo { namespace cyber { namespace transport { -const std::size_t MessageInfo::kSize = 2 * ID_SIZE + sizeof(uint64_t); +const std::size_t MessageInfo::kSize = 2 * ID_SIZE + sizeof(uint64_t) + \ + sizeof(uint64_t) + sizeof(int32_t) + \ + sizeof(uint64_t); MessageInfo::MessageInfo() : sender_id_(false), spare_id_(false) {} @@ -67,9 +69,13 @@ bool MessageInfo::SerializeTo(std::string* dst) const { RETURN_VAL_IF_NULL(dst, false); dst->assign(sender_id_.data(), ID_SIZE); - dst->append(reinterpret_cast(&seq_num_), sizeof(seq_num_)); + dst->append( + reinterpret_cast(&channel_id_), sizeof(channel_id_)); + dst->append( + reinterpret_cast(&seq_num_), sizeof(seq_num_)); dst->append(spare_id_.data(), ID_SIZE); - + dst->append(reinterpret_cast( + &send_time_), sizeof(send_time_)); return true; } @@ -81,10 +87,16 @@ bool MessageInfo::SerializeTo(char* dst, std::size_t len) const { char* ptr = dst; std::memcpy(ptr, sender_id_.data(), ID_SIZE); ptr += ID_SIZE; - std::memcpy(ptr, reinterpret_cast(&seq_num_), sizeof(seq_num_)); + std::memcpy(ptr, + reinterpret_cast(&channel_id_), sizeof(channel_id_)); + ptr += sizeof(channel_id_); + std::memcpy(ptr, + reinterpret_cast(&seq_num_), sizeof(seq_num_)); ptr += sizeof(seq_num_); std::memcpy(ptr, spare_id_.data(), ID_SIZE); - + ptr += ID_SIZE; + std::memcpy(ptr, + reinterpret_cast(&send_time_), sizeof(send_time_)); return true; } @@ -102,10 +114,16 @@ bool MessageInfo::DeserializeFrom(const char* src, std::size_t len) { char* ptr = const_cast(src); sender_id_.set_data(ptr); ptr += ID_SIZE; - std::memcpy(reinterpret_cast(&seq_num_), ptr, sizeof(seq_num_)); + std::memcpy( + reinterpret_cast(&channel_id_), ptr, sizeof(channel_id_)); + ptr += sizeof(channel_id_); + std::memcpy( + reinterpret_cast(&seq_num_), ptr, sizeof(seq_num_)); ptr += sizeof(seq_num_); spare_id_.set_data(ptr); - + ptr += ID_SIZE; + std::memcpy( + reinterpret_cast(&send_time_), ptr, sizeof(send_time_)); return true; } diff --git a/cyber/transport/message/message_info.h b/cyber/transport/message/message_info.h index 3e869fb..0ef633c 100644 --- a/cyber/transport/message/message_info.h +++ b/cyber/transport/message/message_info.h @@ -60,11 +60,15 @@ class MessageInfo { static const std::size_t kSize; + uint64_t send_time() const { return send_time_; } + void set_send_time(uint64_t send_time) { send_time_ = send_time; } + private: Identity sender_id_; uint64_t channel_id_ = 0; uint64_t seq_num_ = 0; Identity spare_id_; + uint64_t send_time_; }; } // namespace transport diff --git a/cyber/transport/qos/qos_filler.cc b/cyber/transport/qos/qos_filler.cc new file mode 100644 index 0000000..5a11d1b --- /dev/null +++ b/cyber/transport/qos/qos_filler.cc @@ -0,0 +1,339 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/transport/qos/qos_filler.h" + +#include "cyber/common/log.h" +#include "cyber/transport/qos/qos_profile_conf.h" + +#include "fastrtps/attributes/PublisherAttributes.h" +#include "fastrtps/attributes/SubscriberAttributes.h" + +namespace apollo { +namespace cyber { +namespace transport { + +using proto::QosDurabilityPolicy; +using proto::QosHistoryPolicy; +using proto::QosProfile; +using proto::QosReliabilityPolicy; +using transport::QosProfileConf; + +bool GetDefaultPubAttributes( + const std::string& channel_name, const QosProfile& qos, + eprosima::fastrtps::PublisherAttributes* pub_attr) { + RETURN_VAL_IF_NULL2(pub_attr, false); + pub_attr->topic.topicName = channel_name; + pub_attr->topic.topicDataType = "UnderlayMessage"; + pub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; + switch (qos.history()) { + case QosHistoryPolicy::HISTORY_KEEP_LAST: + pub_attr->topic.historyQos.kind = + eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; + break; + case QosHistoryPolicy::HISTORY_KEEP_ALL: + pub_attr->topic.historyQos.kind = + eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; + break; + default: + break; + } + switch (qos.durability()) { + case QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL: + pub_attr->qos.m_durability.kind = + eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS; + break; + case QosDurabilityPolicy::DURABILITY_VOLATILE: + pub_attr->qos.m_durability.kind = + eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; + break; + default: + break; + } + + switch (qos.reliability()) { + case QosReliabilityPolicy::RELIABILITY_BEST_EFFORT: + pub_attr->qos.m_reliability.kind = + eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS; + break; + case QosReliabilityPolicy::RELIABILITY_RELIABLE: + pub_attr->qos.m_reliability.kind = + eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS; + break; + default: + break; + } + if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { + pub_attr->topic.historyQos.depth = static_cast(qos.depth()); + } + + // ensure the history depth is at least the requested queue size + RETURN_VAL_IF2(pub_attr->topic.historyQos.depth < 0, false); + + // tranform messages per second to rtps heartbeat + // set default heartbeat period + pub_attr->times.heartbeatPeriod.seconds = 0; + pub_attr->times.heartbeatPeriod.fraction(300 * 4294967); // 300ms + if (qos.mps() != 0) { + uint64_t mps = qos.mps(); + + // adapt heartbeat period + if (mps > 1024) { + mps = 1024; + } else if (mps < 64) { + mps = 64; + } + + uint64_t fractions = (256ull << 32) / mps; + uint32_t fraction = fractions & 0xffffffff; + int32_t seconds = static_cast(fractions >> 32); + + pub_attr->times.heartbeatPeriod.seconds = seconds; + pub_attr->times.heartbeatPeriod.fraction(fraction); + } + + pub_attr->qos.m_publishMode.kind = + eprosima::fastdds::dds::ASYNCHRONOUS_PUBLISH_MODE; + pub_attr->historyMemoryPolicy = + eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; + AINFO << channel_name << "qos: [history: " << pub_attr->topic.historyQos.kind + << "] [durability: " << pub_attr->qos.m_durability.kind + << "] [reliability: " << pub_attr->qos.m_reliability.kind + << "] [depth: " << pub_attr->topic.historyQos.depth + << "] [samples: " << pub_attr->topic.resourceLimitsQos.max_samples + << "]"; + + return true; +} + +bool GetDefaultSubAttributes( + const std::string& channel_name, const QosProfile& qos, + eprosima::fastrtps::SubscriberAttributes* sub_attr) { + RETURN_VAL_IF_NULL2(sub_attr, false); + sub_attr->topic.topicName = channel_name; + sub_attr->topic.topicDataType = "UnderlayMessage"; + sub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; + + switch (qos.history()) { + case QosHistoryPolicy::HISTORY_KEEP_LAST: + sub_attr->topic.historyQos.kind = + eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; + break; + case QosHistoryPolicy::HISTORY_KEEP_ALL: + sub_attr->topic.historyQos.kind = + eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; + break; + default: + break; + } + switch (qos.durability()) { + case QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL: + sub_attr->qos.m_durability.kind = + eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS; + break; + case QosDurabilityPolicy::DURABILITY_VOLATILE: + sub_attr->qos.m_durability.kind = + eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; + break; + default: + break; + } + + switch (qos.reliability()) { + case QosReliabilityPolicy::RELIABILITY_BEST_EFFORT: + sub_attr->qos.m_reliability.kind = + eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS; + break; + case QosReliabilityPolicy::RELIABILITY_RELIABLE: + sub_attr->qos.m_reliability.kind = + eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS; + break; + default: + break; + } + if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { + sub_attr->topic.historyQos.depth = static_cast(qos.depth()); + } + + // ensure the history depth is at least the requested queue size + RETURN_VAL_IF2(sub_attr->topic.historyQos.depth < 0, false); + + sub_attr->historyMemoryPolicy = + eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; + AINFO << channel_name << "qos: [history: " << sub_attr->topic.historyQos.kind + << "] [durability: " << sub_attr->qos.m_durability.kind + << "] [reliability: " << sub_attr->qos.m_reliability.kind + << "] [depth: " << sub_attr->topic.historyQos.depth + << "] [samples: " << sub_attr->topic.resourceLimitsQos.max_samples + << "]"; + + return true; +} + +bool GetDefaultTopicAttributes( + const std::string& channel_name, const QosProfile& qos, + eprosima::fastrtps::TopicAttributes* topic_attr) { + RETURN_VAL_IF_NULL2(topic_attr, false); + topic_attr->topicName = channel_name; + topic_attr->topicDataType = "UnderlayMessage"; + topic_attr->topicKind = eprosima::fastrtps::rtps::NO_KEY; + + switch (qos.history()) { + case QosHistoryPolicy::HISTORY_KEEP_LAST: + topic_attr->historyQos.kind = + eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; + break; + case QosHistoryPolicy::HISTORY_KEEP_ALL: + topic_attr->historyQos.kind = + eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; + break; + default: + break; + } + + if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { + topic_attr->historyQos.depth = static_cast(qos.depth()); + } + + // ensure the history depth is at least the requested queue size + RETURN_VAL_IF2(topic_attr->historyQos.depth < 0, false); + + return true; +} + +/////////////////////////////////////////////////////////////////////////// +bool QosFiller::FillInPubQos(const std::string& channel_name, + const QosProfile& qos, + eprosima::fastdds::dds::PublisherQos* pub_qos) { + RETURN_VAL_IF_NULL2(pub_qos, false); + eprosima::fastrtps::PublisherAttributes pub_attr; + if (!GetDefaultPubAttributes(channel_name, qos, &pub_attr)) { + return false; + } + pub_qos->group_data().setValue(pub_attr.qos.m_groupData); + pub_qos->partition() = pub_attr.qos.m_partition; + pub_qos->presentation() = pub_attr.qos.m_presentation; + return true; +} + +bool QosFiller::FillInWriterQos( + const std::string& channel_name, const QosProfile& qos, + eprosima::fastdds::dds::DataWriterQos* writer_qos) { + RETURN_VAL_IF_NULL2(writer_qos, false); + eprosima::fastrtps::PublisherAttributes pub_attr; + if (!GetDefaultPubAttributes(channel_name, qos, &pub_attr)) { + return false; + } + writer_qos->writer_resource_limits().matched_subscriber_allocation = + pub_attr.matched_subscriber_allocation; + writer_qos->properties() = pub_attr.properties; + writer_qos->throughput_controller() = pub_attr.throughputController; + writer_qos->endpoint().unicast_locator_list = pub_attr.unicastLocatorList; + writer_qos->endpoint().multicast_locator_list = pub_attr.multicastLocatorList; + writer_qos->endpoint().remote_locator_list = pub_attr.remoteLocatorList; + writer_qos->endpoint().history_memory_policy = pub_attr.historyMemoryPolicy; + writer_qos->endpoint().user_defined_id = pub_attr.getUserDefinedID(); + writer_qos->endpoint().entity_id = pub_attr.getEntityID(); + writer_qos->reliable_writer_qos().times = pub_attr.times; + writer_qos->reliable_writer_qos().disable_positive_acks = + pub_attr.qos.m_disablePositiveACKs; + writer_qos->durability() = pub_attr.qos.m_durability; + writer_qos->durability_service() = pub_attr.qos.m_durabilityService; + writer_qos->deadline() = pub_attr.qos.m_deadline; + writer_qos->latency_budget() = pub_attr.qos.m_latencyBudget; + writer_qos->liveliness() = pub_attr.qos.m_liveliness; + writer_qos->reliability() = pub_attr.qos.m_reliability; + writer_qos->lifespan() = pub_attr.qos.m_lifespan; + writer_qos->user_data().setValue(pub_attr.qos.m_userData); + writer_qos->ownership() = pub_attr.qos.m_ownership; + writer_qos->ownership_strength() = pub_attr.qos.m_ownershipStrength; + writer_qos->destination_order() = pub_attr.qos.m_destinationOrder; + writer_qos->representation() = pub_attr.qos.representation; + writer_qos->publish_mode() = pub_attr.qos.m_publishMode; + writer_qos->history() = pub_attr.topic.historyQos; + writer_qos->resource_limits() = pub_attr.topic.resourceLimitsQos; + return true; +} + +bool QosFiller::FillInSubQos(const std::string& channel_name, + const QosProfile& qos, + eprosima::fastdds::dds::SubscriberQos* sub_qos) { + RETURN_VAL_IF_NULL2(sub_qos, false); + eprosima::fastrtps::SubscriberAttributes sub_attr; + if (!GetDefaultSubAttributes(channel_name, qos, &sub_attr)) { + return false; + } + sub_qos->group_data().setValue(sub_attr.qos.m_groupData); + sub_qos->partition() = sub_attr.qos.m_partition; + sub_qos->presentation() = sub_attr.qos.m_presentation; + return true; +} + +bool QosFiller::FillInReaderQos( + const std::string& channel_name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DataReaderQos* reader_qos) { + RETURN_VAL_IF_NULL2(reader_qos, false); + eprosima::fastrtps::SubscriberAttributes sub_attr; + if (!GetDefaultSubAttributes(channel_name, qos, &sub_attr)) { + return false; + } + reader_qos->reader_resource_limits().matched_publisher_allocation = + sub_attr.matched_publisher_allocation; + reader_qos->properties() = sub_attr.properties; + reader_qos->expects_inline_qos(sub_attr.expectsInlineQos); + reader_qos->endpoint().unicast_locator_list = sub_attr.unicastLocatorList; + reader_qos->endpoint().multicast_locator_list = sub_attr.multicastLocatorList; + reader_qos->endpoint().remote_locator_list = sub_attr.remoteLocatorList; + reader_qos->endpoint().history_memory_policy = sub_attr.historyMemoryPolicy; + reader_qos->endpoint().user_defined_id = sub_attr.getUserDefinedID(); + reader_qos->endpoint().entity_id = sub_attr.getEntityID(); + reader_qos->reliable_reader_qos().times = sub_attr.times; + reader_qos->reliable_reader_qos().disable_positive_ACKs = + sub_attr.qos.m_disablePositiveACKs; + reader_qos->durability() = sub_attr.qos.m_durability; + reader_qos->durability_service() = sub_attr.qos.m_durabilityService; + reader_qos->deadline() = sub_attr.qos.m_deadline; + reader_qos->latency_budget() = sub_attr.qos.m_latencyBudget; + reader_qos->liveliness() = sub_attr.qos.m_liveliness; + reader_qos->reliability() = sub_attr.qos.m_reliability; + reader_qos->lifespan() = sub_attr.qos.m_lifespan; + reader_qos->user_data().setValue(sub_attr.qos.m_userData); + reader_qos->ownership() = sub_attr.qos.m_ownership; + reader_qos->destination_order() = sub_attr.qos.m_destinationOrder; + reader_qos->type_consistency().type_consistency = + sub_attr.qos.type_consistency; + reader_qos->type_consistency().representation = sub_attr.qos.representation; + reader_qos->time_based_filter() = sub_attr.qos.m_timeBasedFilter; + reader_qos->history() = sub_attr.topic.historyQos; + reader_qos->resource_limits() = sub_attr.topic.resourceLimitsQos; + return true; +} + +bool QosFiller::FillInTopicQos(const std::string& channel_name, + const proto::QosProfile& qos, + eprosima::fastdds::dds::TopicQos* topic_qos) { + RETURN_VAL_IF_NULL2(topic_qos, false); + eprosima::fastrtps::TopicAttributes topic_attr; + if (!GetDefaultTopicAttributes(channel_name, qos, &topic_attr)) { + return false; + } + topic_qos->history() = topic_attr.historyQos; + topic_qos->resource_limits() = topic_attr.resourceLimitsQos; + return true; +} +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/qos/qos_filler.h b/cyber/transport/qos/qos_filler.h new file mode 100644 index 0000000..f7104b8 --- /dev/null +++ b/cyber/transport/qos/qos_filler.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ +#define CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ + +#include + +#include "cyber/base/macros.h" + +#include "fastdds/dds/publisher/qos/DataWriterQos.hpp" +#include "fastdds/dds/publisher/qos/PublisherQos.hpp" +#include "fastdds/dds/subscriber/qos/DataReaderQos.hpp" +#include "fastdds/dds/subscriber/qos/SubscriberQos.hpp" +#include "fastdds/dds/topic/qos/TopicQos.hpp" +#include "cyber/proto/qos_profile.pb.h" + +namespace apollo { +namespace cyber { +namespace transport { + +class QosFiller { + public: + static bool FillInPubQos(const std::string& channel_name, + const proto::QosProfile& qos, + eprosima::fastdds::dds::PublisherQos* pub_qos); + + static bool FillInWriterQos( + const std::string& channel_name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DataWriterQos* writer_qos); + + static bool FillInSubQos(const std::string& channel_name, + const proto::QosProfile& qos, + eprosima::fastdds::dds::SubscriberQos* sub_qos); + + static bool FillInReaderQos( + const std::string& channel_name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DataReaderQos* reader_qos); + + static bool FillInTopicQos(const std::string& channel_name, + const proto::QosProfile& qos, + eprosima::fastdds::dds::TopicQos* topic_qos); +}; + +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif // CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ diff --git a/cyber/transport/receiver/shm_receiver.h b/cyber/transport/receiver/shm_receiver.h index e39890b..ae18ed9 100644 --- a/cyber/transport/receiver/shm_receiver.h +++ b/cyber/transport/receiver/shm_receiver.h @@ -22,6 +22,7 @@ #include "cyber/common/log.h" #include "cyber/transport/dispatcher/shm_dispatcher.h" #include "cyber/transport/receiver/receiver.h" +#include "cyber/transport/shm/protobuf_arena_manager.h" namespace apollo { namespace cyber { @@ -63,6 +64,17 @@ void ShmReceiver::Enable() { return; } + if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( + this->attr_.channel_id()) && message::MessageType() != \ + message::MessageType()) { + auto arena_manager = ProtobufArenaManager::Instance(); + if (!arena_manager->Enable() || + !arena_manager->EnableSegment(this->attr_.channel_id())) { + AERROR << "arena manager enable failed."; + return; + } + } + dispatcher_->AddListener( this->attr_, std::bind(&ShmReceiver::OnNewMessage, this, std::placeholders::_1, std::placeholders::_2)); @@ -81,6 +93,16 @@ void ShmReceiver::Disable() { template void ShmReceiver::Enable(const RoleAttributes& opposite_attr) { + if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( + this->attr_.channel_id()) && message::MessageType() != \ + message::MessageType()) { + auto arena_manager = ProtobufArenaManager::Instance(); + if (!arena_manager->Enable() || + !arena_manager->EnableSegment(this->attr_.channel_id())) { + AERROR << "arena manager enable failed."; + return; + } + } dispatcher_->AddListener( this->attr_, opposite_attr, std::bind(&ShmReceiver::OnNewMessage, this, std::placeholders::_1, diff --git a/cyber/transport/rtps/attributes_filler.cc b/cyber/transport/rtps/attributes_filler.cc index 411e12d..3a203f7 100644 --- a/cyber/transport/rtps/attributes_filler.cc +++ b/cyber/transport/rtps/attributes_filler.cc @@ -35,7 +35,7 @@ bool AttributesFiller::FillInPubAttr( pub_attr->topic.topicName = channel_name; pub_attr->topic.topicDataType = "UnderlayMessage"; - pub_attr->topic.topicKind = eprosima::fastrtps::NO_KEY; + pub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; switch (qos.history()) { case QosHistoryPolicy::HISTORY_KEEP_LAST: @@ -88,7 +88,7 @@ bool AttributesFiller::FillInPubAttr( // transform messages per second to rtps heartbeat // set default heartbeat period pub_attr->times.heartbeatPeriod.seconds = 1; - pub_attr->times.heartbeatPeriod.fraction = 0; + pub_attr->times.heartbeatPeriod.fraction(0); if (qos.mps() != 0) { uint64_t mps = qos.mps(); @@ -104,13 +104,13 @@ bool AttributesFiller::FillInPubAttr( int32_t seconds = static_cast(fractions >> 32); pub_attr->times.heartbeatPeriod.seconds = seconds; - pub_attr->times.heartbeatPeriod.fraction = fraction; + pub_attr->times.heartbeatPeriod.fraction(fraction); } pub_attr->qos.m_publishMode.kind = eprosima::fastrtps::ASYNCHRONOUS_PUBLISH_MODE; pub_attr->historyMemoryPolicy = - eprosima::fastrtps::DYNAMIC_RESERVE_MEMORY_MODE; + eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; pub_attr->topic.resourceLimitsQos.max_samples = 10000; return true; @@ -122,7 +122,7 @@ bool AttributesFiller::FillInSubAttr( RETURN_VAL_IF_NULL(sub_attr, false); sub_attr->topic.topicName = channel_name; sub_attr->topic.topicDataType = "UnderlayMessage"; - sub_attr->topic.topicKind = eprosima::fastrtps::NO_KEY; + sub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; switch (qos.history()) { case QosHistoryPolicy::HISTORY_KEEP_LAST: @@ -173,7 +173,7 @@ bool AttributesFiller::FillInSubAttr( } sub_attr->historyMemoryPolicy = - eprosima::fastrtps::DYNAMIC_RESERVE_MEMORY_MODE; + eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; sub_attr->topic.resourceLimitsQos.max_samples = 10000; return true; diff --git a/cyber/transport/rtps/attributes_filler.h b/cyber/transport/rtps/attributes_filler.h index 44ab135..df57571 100644 --- a/cyber/transport/rtps/attributes_filler.h +++ b/cyber/transport/rtps/attributes_filler.h @@ -19,6 +19,8 @@ #include +#include "cyber/base/macros.h" + #include "cyber/proto/qos_profile.pb.h" #include "fastrtps/attributes/PublisherAttributes.h" #include "fastrtps/attributes/SubscriberAttributes.h" diff --git a/cyber/transport/rtps/participant.cc b/cyber/transport/rtps/participant.cc index 169ac48..6a362be 100644 --- a/cyber/transport/rtps/participant.cc +++ b/cyber/transport/rtps/participant.cc @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2018 The Apollo Authors. All Rights Reserved. + * Copyright 2024 The Apollo Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,130 +13,207 @@ * See the License for the specific language governing permissions and * limitations under the License. *****************************************************************************/ - #include "cyber/transport/rtps/participant.h" -#include "cyber/common/global_data.h" -#include "cyber/common/log.h" -#include "cyber/proto/transport_conf.pb.h" +#include namespace apollo { namespace cyber { namespace transport { -Participant::Participant(const std::string& name, int send_port, - eprosima::fastrtps::ParticipantListener* listener) +auto Participant::CreateSubscriber(const std::string& channel_name, + const proto::QosProfile& qos, + const rtps::subsciber_callback& callback) + -> std::shared_ptr { + if (!participant_) { + AWARN << "DDSParticipant already released when the subscriber created, " + "channel:" + << channel_name; + return nullptr; + } + auto subscriber_ptr = std::make_shared( + channel_name, qos, participant_, callback); + RETURN_VAL_IF(!subscriber_ptr->Init(), nullptr); + std::lock_guard lock(subscriber_mutex_); + subscriber_map_.emplace(channel_name, subscriber_ptr); + return subscriber_ptr; +} + +Participant::Participant( + const std::string& name, int send_port, + eprosima::fastdds::dds::DomainParticipantListener* listener) : shutdown_(false), name_(name), send_port_(send_port), listener_(listener), - fastrtps_participant_(nullptr) {} + type_support_(new UnderlayMessageType()), + participant_(nullptr) {} Participant::~Participant() {} +bool Participant::Init() { + return CreateParticipant(name_, send_port_, listener_); +} + void Participant::Shutdown() { if (shutdown_.exchange(true)) { return; } - std::lock_guard lk(mutex_); - if (fastrtps_participant_ != nullptr) { - eprosima::fastrtps::Domain::removeParticipant(fastrtps_participant_); - fastrtps_participant_ = nullptr; + publisher_map_.clear(); + subscriber_map_.clear(); + if (listener_ != nullptr) { + delete listener_; listener_ = nullptr; } } -eprosima::fastrtps::Participant* Participant::fastrtps_participant() { - if (shutdown_.load()) { +auto Participant::CreatePublisher(const std::string& channel_name, + const proto::QosProfile& qos) + -> std::shared_ptr { + if (!participant_) { + AWARN << "DDSParticipant already released when the publisher created, " + "channel:" + << channel_name; return nullptr; } + auto publisher_ptr = + std::make_shared(channel_name, qos, participant_); - std::lock_guard lk(mutex_); - if (fastrtps_participant_ != nullptr) { - return fastrtps_participant_; - } - - CreateFastRtpsParticipant(name_, send_port_, listener_); - return fastrtps_participant_; + RETURN_VAL_IF(!publisher_ptr->Init(), nullptr); + std::lock_guard lock(publisher_mutex_); + publisher_map_.emplace(channel_name, publisher_ptr); + return publisher_ptr; } -void Participant::CreateFastRtpsParticipant( +bool Participant::CreateParticipant( const std::string& name, int send_port, - eprosima::fastrtps::ParticipantListener* listener) { + eprosima::fastdds::dds::DomainParticipantListener* listener) { uint32_t domain_id = 80; - const char* val = ::getenv("CYBER_DOMAIN_ID"); if (val != nullptr) { try { domain_id = std::stoi(val); } catch (const std::exception& e) { AERROR << "convert domain_id error " << e.what(); - return; + return false; } } - auto part_attr_conf = std::make_shared(); - auto& global_conf = common::GlobalData::Instance()->Config(); - if (global_conf.has_transport_conf() && - global_conf.transport_conf().has_participant_attr()) { - part_attr_conf->CopyFrom(global_conf.transport_conf().participant_attr()); - } - - eprosima::fastrtps::ParticipantAttributes attr; - attr.rtps.defaultSendPort = send_port; - attr.rtps.port.domainIDGain = - static_cast(part_attr_conf->domain_id_gain()); - attr.rtps.port.portBase = static_cast(part_attr_conf->port_base()); - attr.rtps.use_IP6_to_send = false; - attr.rtps.builtin.use_SIMPLE_RTPSParticipantDiscoveryProtocol = true; - attr.rtps.builtin.use_SIMPLE_EndpointDiscoveryProtocol = true; - attr.rtps.builtin.m_simpleEDP.use_PublicationReaderANDSubscriptionWriter = - true; - attr.rtps.builtin.m_simpleEDP.use_PublicationWriterANDSubscriptionReader = - true; - attr.rtps.builtin.domainId = domain_id; - - /** - * The user should set the lease_duration and the announcement_period with - * values that differ in at least 30%. Values too close to each other may - * cause the failure of the writer liveliness assertion in networks with high - * latency or with lots of communication errors. - */ - attr.rtps.builtin.leaseDuration.seconds = part_attr_conf->lease_duration(); - attr.rtps.builtin.leaseDuration_announcementperiod.seconds = - part_attr_conf->announcement_period(); - - attr.rtps.setName(name.c_str()); - std::string ip_env("127.0.0.1"); const char* ip_val = ::getenv("CYBER_IP"); if (ip_val != nullptr) { ip_env = ip_val; if (ip_env.empty()) { AERROR << "invalid CYBER_IP (an empty string)"; - return; + return false; } } - ADEBUG << "cyber ip: " << ip_env; + auto part_attr_conf = std::make_shared(); + auto& global_conf = common::GlobalData::Instance()->Config(); + + if (!global_conf.has_transport_conf() || + !global_conf.transport_conf().has_participant_attr()) { + AERROR << "No rtps participant attr conf."; + return false; + } + + part_attr_conf->CopyFrom(global_conf.transport_conf().participant_attr()); + + // set wire protocol + eprosima::fastdds::dds::WireProtocolConfigQos wire_protocol; + wire_protocol.port.domainIDGain = + static_cast(part_attr_conf->domain_id_gain()); + wire_protocol.port.portBase = + static_cast(part_attr_conf->port_base()); + wire_protocol.builtin.discovery_config.discoveryProtocol = + eprosima::fastrtps::rtps::DiscoveryProtocol_t::SIMPLE; + wire_protocol.builtin.discovery_config.use_SIMPLE_EndpointDiscoveryProtocol = + true; + wire_protocol.builtin.discovery_config.m_simpleEDP + .use_PublicationReaderANDSubscriptionWriter = true; + wire_protocol.builtin.discovery_config.m_simpleEDP + .use_PublicationWriterANDSubscriptionReader = true; + wire_protocol.builtin.discovery_config.leaseDuration.seconds = + part_attr_conf->lease_duration(); + wire_protocol.builtin.discovery_config.leaseDuration_announcementperiod + .seconds = part_attr_conf->announcement_period(); + wire_protocol.builtin.discovery_config.ignoreParticipantFlags = static_cast< + eprosima::fastrtps::rtps::ParticipantFilteringFlags>( + eprosima::fastrtps::rtps::ParticipantFilteringFlags::FILTER_SAME_PROCESS); + + // set transport locator eprosima::fastrtps::rtps::Locator_t locator; locator.port = 0; - RETURN_IF(!locator.set_IP4_address(ip_env)); - + RETURN_VAL_IF(!eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, ip_env), + false); locator.kind = LOCATOR_KIND_UDPv4; + wire_protocol.default_unicast_locator_list.push_back(locator); + wire_protocol.builtin.metatrafficUnicastLocatorList.push_back(locator); + eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, 239, 255, 0, 1); + wire_protocol.builtin.metatrafficMulticastLocatorList.push_back(locator); + + // set participant qos + eprosima::fastdds::dds::PropertyPolicyQos properties; + eprosima::fastdds::dds::DomainParticipantQos participant_qos; + participant_qos.name(this->name_.c_str()); + participant_qos.wire_protocol(wire_protocol); + participant_qos.properties(properties); + + // UDP + auto udp_transport = + std::make_shared(); + udp_transport->sendBufferSize = 1024 * 1025 * 10; + udp_transport->receiveBufferSize = 1024 * 1025 * 10; + udp_transport->interfaceWhiteList.push_back(ip_env); + participant_qos.transport().user_transports.push_back(udp_transport); + participant_qos.transport().use_builtin_transports = false; + AINFO << "part name: " << participant_qos.name() << ", port: " << send_port_; + + participant_ = + eprosima::fastdds::dds::DomainParticipantFactory::get_instance() + ->create_participant(domain_id, participant_qos, listener_, + eprosima::fastdds::dds::StatusMask::none()); + RETURN_VAL_IF_NULL(participant_, false); + if (type_support_.register_type(participant_) != ReturnCode_t::RETCODE_OK) { + AERROR << "Register type failed!"; + return false; + } + return true; +} - attr.rtps.defaultUnicastLocatorList.push_back(locator); - attr.rtps.defaultOutLocatorList.push_back(locator); - attr.rtps.builtin.metatrafficUnicastLocatorList.push_back(locator); - - locator.set_IP4_address(239, 255, 0, 1); - attr.rtps.builtin.metatrafficMulticastLocatorList.push_back(locator); +bool Participant::CheckIPVaild(std::string ip_env) { + struct ifaddrs *ifap, *ifa; + struct sockaddr_in* sa; + char ip_address[INET_ADDRSTRLEN]; + if (getifaddrs(&ifap) == -1) { + AERROR << "getifaddrs error"; + return false; + } + std::vector ip_vec; + std::stringstream ip_info; + ip_info << "All ip info: \n"; + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) { + sa = (struct sockaddr_in*)ifa->ifa_addr; + inet_ntop(AF_INET, &sa->sin_addr, ip_address, sizeof(ip_address)); + ip_info << " " << ifa->ifa_name << " " << ip_address << "\n"; + ip_vec.push_back(ip_address); + } + } + AINFO << ip_info.str(); + freeifaddrs(ifap); - fastrtps_participant_ = - eprosima::fastrtps::Domain::createParticipant(attr, listener); - RETURN_IF_NULL(fastrtps_participant_); - eprosima::fastrtps::Domain::registerType(fastrtps_participant_, &type_); + for (std::string ip_interface : ip_vec) { + if (ip_interface == ip_env) { + AINFO << "Find same the ip interface in host as cyber ip: " << ip_env; + return true; + } + } + AERROR << "The same ip interface in host as cyber ip was not found: " + << ip_env; + return false; } } // namespace transport diff --git a/cyber/transport/rtps/participant.h b/cyber/transport/rtps/participant.h index 455c897..9950cbe 100644 --- a/cyber/transport/rtps/participant.h +++ b/cyber/transport/rtps/participant.h @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright 2018 The Apollo Authors. All Rights Reserved. + * Copyright 2024 The Apollo Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,47 +17,81 @@ #ifndef CYBER_TRANSPORT_RTPS_PARTICIPANT_H_ #define CYBER_TRANSPORT_RTPS_PARTICIPANT_H_ +#include +#include + #include #include #include #include +#include + +#include "fastdds/dds/domain/DomainParticipantFactory.hpp" +#include "fastdds/dds/domain/DomainParticipantListener.hpp" +#include "fastdds/rtps/transport/TCPv4TransportDescriptor.h" +#include "fastdds/rtps/transport/UDPv4TransportDescriptor.h" +#include "fastrtps/utils/IPLocator.h" + +#include "cyber/base/macros.h" +#include "cyber/proto/qos_profile.pb.h" +#include "cyber/proto/transport_conf.pb.h" + +#include "cyber/common/global_data.h" +#include "cyber/common/log.h" +#include "cyber/transport/rtps/publisher.h" +#include "cyber/transport/rtps/subscriber.h" #include "cyber/transport/rtps/underlay_message_type.h" -#include "fastrtps/Domain.h" -#include "fastrtps/attributes/ParticipantAttributes.h" -#include "fastrtps/participant/Participant.h" -#include "fastrtps/participant/ParticipantListener.h" -#include "fastrtps/rtps/common/Locator.h" namespace apollo { namespace cyber { namespace transport { -class Participant; -using ParticipantPtr = std::shared_ptr; - class Participant { public: - Participant(const std::string& name, int send_port, - eprosima::fastrtps::ParticipantListener* listener = nullptr); + Participant( + const std::string& name, int send_port, + eprosima::fastdds::dds::DomainParticipantListener* listener = nullptr); virtual ~Participant(); void Shutdown(); + bool Init(); + auto CreatePublisher(const std::string& channel_name, + const proto::QosProfile& qos) + -> std::shared_ptr; + + auto CreateSubscriber(const std::string& channel_name, + const proto::QosProfile& qos, + const rtps::subsciber_callback& callback = nullptr) + -> std::shared_ptr; - eprosima::fastrtps::Participant* fastrtps_participant(); bool is_shutdown() const { return shutdown_.load(); } private: - void CreateFastRtpsParticipant( + Participant(const Participant&) = delete; + Participant& operator=(const Participant&) = delete; + bool CreateParticipant( const std::string& name, int send_port, - eprosima::fastrtps::ParticipantListener* listener); + eprosima::fastdds::dds::DomainParticipantListener* listener); + bool CheckIPVaild(std::string ip_env); std::atomic shutdown_; std::string name_; int send_port_; - eprosima::fastrtps::ParticipantListener* listener_; - UnderlayMessageType type_; - eprosima::fastrtps::Participant* fastrtps_participant_; + + using PublisherPtrMap = + std::unordered_multimap>; + using SubscriberPtrMap = + std::unordered_multimap>; + + std::mutex publisher_mutex_; + PublisherPtrMap publisher_map_; + std::mutex subscriber_mutex_; + SubscriberPtrMap subscriber_map_; + + eprosima::fastdds::dds::DomainParticipantListener* listener_; + eprosima::fastdds::dds::TypeSupport type_support_; + eprosima::fastdds::dds::DomainParticipant* participant_; std::mutex mutex_; }; diff --git a/cyber/transport/rtps/publisher.cc b/cyber/transport/rtps/publisher.cc new file mode 100644 index 0000000..ab2effa --- /dev/null +++ b/cyber/transport/rtps/publisher.cc @@ -0,0 +1,136 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include "cyber/transport/rtps/publisher.h" +#include "cyber/common/log.h" + +namespace apollo { +namespace cyber { +namespace transport { + +Publisher::Publisher(const std::string& channel_name, + const proto::QosProfile& qos, + eprosima::fastdds::dds::DomainParticipant* participant) + : channel_name_(channel_name), + qos_(qos), + shutdown_(false), + participant_(participant), + publisher_(nullptr), + topic_(nullptr), + writer_(nullptr) {} + +Publisher::~Publisher() { Shutdown(); } + +bool Publisher::Init() { + eprosima::fastdds::dds::PublisherQos pub_qos; + RETURN_VAL_IF( + !QosFiller::FillInPubQos(this->channel_name_, this->qos_, &pub_qos), + false); + publisher_ = participant_->create_publisher(pub_qos, nullptr); + if (publisher_ == nullptr) { + AINFO << "something went wrong while creating the publisher..."; + return false; + } + + if (!EnsureCreateTopic(this->channel_name_)) { + AINFO << "something went wrong while creating the topic..."; + return false; + } + + eprosima::fastdds::dds::DataWriterQos writer_qos; + RETURN_VAL_IF( + !QosFiller::FillInWriterQos(this->channel_name_, this->qos_, &writer_qos), + false); + writer_ = publisher_->create_datawriter(topic_, writer_qos, nullptr); + if (writer_ == nullptr) { + AINFO << "something went wrong while creating the datawriter..."; + return false; + } + + return true; +} + +bool Publisher::Write(const UnderlayMessage& msg, bool is_topo_msg) { + RETURN_VAL_IF(shutdown_.load(), false); + if (is_topo_msg) { + AINFO << "FastDDSPublisher::Write data size: " << msg.data().size(); + } + return writer_->write( + reinterpret_cast(const_cast(&msg))); +} + +bool Publisher::Write(const UnderlayMessage& msg, const MessageInfo& msg_info, + bool is_topo_msg) { + RETURN_VAL_IF(shutdown_.load(), false); + if (is_topo_msg) { + AINFO << "FastDDSPublisher::Write data size: " << msg.data().size(); + } + + eprosima::fastrtps::rtps::WriteParams wparams; + + char* ptr = + reinterpret_cast(&wparams.related_sample_identity().writer_guid()); + + memcpy(ptr, msg_info.sender_id().data(), ID_SIZE); + memcpy(ptr + ID_SIZE, msg_info.spare_id().data(), ID_SIZE); + + wparams.related_sample_identity().sequence_number().high = + (int32_t)((msg_info.seq_num() & 0xFFFFFFFF00000000) >> 32); + wparams.related_sample_identity().sequence_number().low = + (int32_t)(msg_info.seq_num() & 0xFFFFFFFF); + + return writer_->write( + reinterpret_cast(const_cast(&msg)), wparams); +} + +void Publisher::Shutdown() { + RETURN_IF(shutdown_.exchange(true)); + + if (publisher_ != nullptr && writer_ != nullptr) { + publisher_->delete_datawriter(writer_); + writer_ = nullptr; + } + if (participant_ != nullptr && publisher_ != nullptr) { + if (participant_->delete_publisher(publisher_) == + eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { + publisher_ = nullptr; + } else { + AERROR << channel_name_ << ": Failed to delete the publisher."; + } + } + if (participant_ != nullptr && topic_ != nullptr) { + participant_->delete_topic(topic_); + topic_ = nullptr; + } +} + +bool Publisher::EnsureCreateTopic(const std::string& channel_name) { + topic_ = dynamic_cast( + participant_->lookup_topicdescription(channel_name)); + if (topic_ == nullptr) { + eprosima::fastdds::dds::TopicQos topic_qos; + RETURN_VAL_IF( + !QosFiller::FillInTopicQos(channel_name, this->qos_, &topic_qos), + false); + topic_ = + participant_->create_topic(channel_name, "UnderlayMessage", topic_qos); + } + return (topic_ != nullptr); +} + +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/rtps/publisher.h b/cyber/transport/rtps/publisher.h new file mode 100644 index 0000000..720fee5 --- /dev/null +++ b/cyber/transport/rtps/publisher.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_TRANSPORT_RTPS_PUBLISHER_H +#define CYBER_TRANSPORT_RTPS_PUBLISHER_H + +#include +#include + +#include "fastdds/dds/domain/DomainParticipant.hpp" +#include "fastdds/dds/domain/DomainParticipantFactory.hpp" +#include "fastdds/dds/publisher/DataWriter.hpp" +#include "fastdds/dds/publisher/DataWriterListener.hpp" +#include "fastdds/dds/publisher/Publisher.hpp" +#include "fastdds/dds/topic/Topic.hpp" +#include "fastdds/dds/topic/TypeSupport.hpp" +#include "cyber/proto/qos_profile.pb.h" +#include "cyber/base/macros.h" +#include "cyber/common/log.h" +#include "cyber/transport/message/message_info.h" +#include "cyber/transport/qos/qos_filler.h" +#include "cyber/transport/rtps/underlay_message.h" + +namespace apollo { +namespace cyber { +namespace transport { + +class Publisher; +using PublisherPtr = std::shared_ptr; +class Publisher { + public: + Publisher(const std::string& channel_name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DomainParticipant* participant); + virtual ~Publisher(); + + bool Init(); + bool Write(const UnderlayMessage& msg, bool is_topo_msg = false); + bool Write(const UnderlayMessage& msg, const MessageInfo& msg_info, + bool is_topo_msg = false); + void Shutdown(); + + private: + Publisher(const Publisher&) = delete; + Publisher& operator=(const Publisher&) = delete; + bool EnsureCreateTopic(const std::string& channel_name); + + std::string channel_name_; + proto::QosProfile qos_; + std::atomic shutdown_; + + eprosima::fastdds::dds::DomainParticipant* participant_; + eprosima::fastdds::dds::Publisher* publisher_; + eprosima::fastdds::dds::Topic* topic_; + eprosima::fastdds::dds::DataWriter* writer_; +}; + +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif // CYBER_TRANSPORT_RTPS_PUBLISHER_H diff --git a/cyber/transport/rtps/rtps_test.cc b/cyber/transport/rtps/rtps_test.cc index 0f6cab4..1e6401b 100644 --- a/cyber/transport/rtps/rtps_test.cc +++ b/cyber/transport/rtps/rtps_test.cc @@ -14,142 +14,159 @@ * limitations under the License. *****************************************************************************/ +#include #include #include -#include "fastcdr/Cdr.h" -#include "fastcdr/exceptions/BadParamException.h" #include "gtest/gtest.h" -#include "cyber/common/global_data.h" #include "cyber/common/log.h" +#include "cyber/transport/qos/qos_filler.h" #include "cyber/transport/qos/qos_profile_conf.h" #include "cyber/transport/rtps/attributes_filler.h" -#include "cyber/transport/rtps/participant.h" #include "cyber/transport/rtps/underlay_message.h" -#include "cyber/transport/rtps/underlay_message_type.h" namespace apollo { namespace cyber { namespace transport { -TEST(AttributesFillerTest, fill_in_pub_attr_test) { +TEST(QosFillerTest, fill_in_pub_qos_test) { QosProfile qos; - AttributesFiller filler; - eprosima::fastrtps::PublisherAttributes attrs; + QosFiller filler; + eprosima::fastdds::dds::PublisherQos pub_qos; + eprosima::fastdds::dds::DataWriterQos writer_qos; qos.set_history(QosHistoryPolicy::HISTORY_KEEP_LAST); qos.set_durability(QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); qos.set_mps(32); - filler.FillInPubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_LAST_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::TRANSIENT_LOCAL_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::BEST_EFFORT_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); - AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " - << attrs.times.heartbeatPeriod.fraction; + filler.FillInPubQos("channel", qos, &pub_qos); + filler.FillInWriterQos("channel", qos, &writer_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, + writer_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, + writer_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, + writer_qos.reliability().kind); + AINFO << "heartbeat period: " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds + << ", " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; qos.set_depth(1024); - attrs.topic.historyQos.depth = 512; - filler.FillInPubAttr("channel", qos, &attrs); + filler.FillInPubQos("channel", qos, &pub_qos); + filler.FillInWriterQos("channel", qos, &writer_qos); AINFO << qos.depth() << ", " << QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT << ", " - << attrs.topic.historyQos.depth; - EXPECT_EQ(qos.depth(), attrs.topic.historyQos.depth); + << writer_qos.history().depth; + EXPECT_EQ(qos.depth(), writer_qos.history().depth); qos.set_history(QosHistoryPolicy::HISTORY_KEEP_ALL); qos.set_durability(QosDurabilityPolicy::DURABILITY_VOLATILE); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_RELIABLE); qos.set_mps(65); - filler.FillInPubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); - AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " - << attrs.times.heartbeatPeriod.fraction; + filler.FillInPubQos("channel", qos, &pub_qos); + filler.FillInWriterQos("channel", qos, &writer_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS, + writer_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, + writer_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, + writer_qos.reliability().kind); + AINFO << "heartbeat period: " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds + << ", " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; qos.set_history(QosHistoryPolicy::HISTORY_SYSTEM_DEFAULT); qos.set_durability(QosDurabilityPolicy::DURABILITY_SYSTEM_DEFAULT); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_SYSTEM_DEFAULT); qos.set_mps(1025); - filler.FillInPubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); - AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " - << attrs.times.heartbeatPeriod.fraction; + filler.FillInPubQos("channel", qos, &pub_qos); + filler.FillInWriterQos("channel", qos, &writer_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, + writer_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, + writer_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, + writer_qos.reliability().kind); + AINFO << "heartbeat period: " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds + << ", " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; qos.set_mps(0); - filler.FillInPubAttr("channel", qos, &attrs); - AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " - << attrs.times.heartbeatPeriod.fraction; + filler.FillInPubQos("channel", qos, &pub_qos); + filler.FillInWriterQos("channel", qos, &writer_qos); + AINFO << "heartbeat period: " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds + << ", " + << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; + qos.set_depth(-1); + EXPECT_FALSE(filler.FillInPubQos("channel", qos, &pub_qos)); + EXPECT_FALSE(filler.FillInWriterQos("channel", qos, &writer_qos)); } TEST(AttributesFillerTest, fill_in_sub_attr_test) { QosProfile qos; - AttributesFiller filler; - eprosima::fastrtps::SubscriberAttributes attrs; + QosFiller filler; + eprosima::fastdds::dds::SubscriberQos sub_qos; + eprosima::fastdds::dds::DataReaderQos reader_qos; qos.set_history(QosHistoryPolicy::HISTORY_KEEP_LAST); qos.set_durability(QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); qos.set_mps(32); - filler.FillInSubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_LAST_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::TRANSIENT_LOCAL_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::BEST_EFFORT_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); + filler.FillInSubQos("channel", qos, &sub_qos); + filler.FillInReaderQos("channel", qos, &reader_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, + reader_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, + reader_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, + reader_qos.reliability().kind); qos.set_depth(1024); - attrs.topic.historyQos.depth = 512; - filler.FillInSubAttr("channel", qos, &attrs); - EXPECT_EQ(qos.depth(), attrs.topic.historyQos.depth); + // attrs.topic.historyQos.depth = 512; + filler.FillInSubQos("channel", qos, &sub_qos); + filler.FillInReaderQos("channel", qos, &reader_qos); + EXPECT_EQ(qos.depth(), reader_qos.history().depth); qos.set_history(QosHistoryPolicy::HISTORY_KEEP_ALL); qos.set_durability(QosDurabilityPolicy::DURABILITY_VOLATILE); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_RELIABLE); qos.set_mps(65); - filler.FillInSubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); + filler.FillInSubQos("channel", qos, &sub_qos); + filler.FillInReaderQos("channel", qos, &reader_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS, + reader_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, + reader_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, + reader_qos.reliability().kind); qos.set_history(QosHistoryPolicy::HISTORY_SYSTEM_DEFAULT); qos.set_durability(QosDurabilityPolicy::DURABILITY_SYSTEM_DEFAULT); qos.set_reliability(QosReliabilityPolicy::RELIABILITY_SYSTEM_DEFAULT); qos.set_mps(1025); - filler.FillInSubAttr("channel", qos, &attrs); - EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, - attrs.topic.historyQos.kind); - EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, - attrs.qos.m_durability.kind); - EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, - attrs.qos.m_reliability.kind); -} - -TEST(ParticipantTest, participant_test) { - eprosima::fastrtps::ParticipantListener listener; - eprosima::fastrtps::ParticipantListener listener1; + filler.FillInSubQos("channel", qos, &sub_qos); + filler.FillInReaderQos("channel", qos, &reader_qos); + EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, + reader_qos.history().kind); + EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, + reader_qos.durability().kind); + EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, + reader_qos.reliability().kind); + + qos.set_depth(-1); + EXPECT_FALSE(filler.FillInSubQos("channel", qos, &sub_qos)); + EXPECT_FALSE(filler.FillInReaderQos("channel", qos, &reader_qos)); } TEST(UnderlayMessageTest, underlay_message_test) { UnderlayMessage message; message.timestamp(1024); - int32_t& t = message.timestamp(); + uint64_t& t = message.timestamp(); t = 256; EXPECT_EQ(256, message.timestamp()); message.seq(1024); - int32_t& seq = message.seq(); + uint64_t& seq = message.seq(); seq = 256; EXPECT_EQ(256, message.seq()); @@ -160,51 +177,35 @@ TEST(UnderlayMessageTest, underlay_message_test) { message.data(std::forward("data forward")); EXPECT_EQ("data forward", message.data()); - message.datatype("datatype"); - std::string& datatype = message.datatype(); - datatype = "datatype string"; - EXPECT_EQ(datatype, message.datatype()); - message.datatype("datatype assign"); - EXPECT_EQ("datatype assign", message.datatype()); - message.datatype(std::forward("datatype forward")); - EXPECT_EQ("datatype forward", message.datatype()); - const UnderlayMessage const_message(message); std::string data1 = const_message.data(); - std::string datatype1 = const_message.datatype(); EXPECT_EQ(256, const_message.timestamp()); EXPECT_EQ(256, const_message.seq()); EXPECT_EQ("data forward", const_message.data()); - EXPECT_EQ("datatype forward", const_message.datatype()); UnderlayMessage message2; message2 = message; EXPECT_EQ(256, message2.timestamp()); EXPECT_EQ(256, message2.seq()); EXPECT_EQ("data forward", message2.data()); - EXPECT_EQ("datatype forward", message2.datatype()); UnderlayMessage message3; message3 = std::forward(message2); EXPECT_EQ(256, message3.timestamp()); EXPECT_EQ(256, message3.seq()); EXPECT_EQ("data forward", message3.data()); - EXPECT_EQ("datatype forward", message3.datatype()); UnderlayMessage message4(message3); EXPECT_EQ(256, message4.timestamp()); EXPECT_EQ(256, message4.seq()); EXPECT_EQ("data forward", message4.data()); - EXPECT_EQ("datatype forward", message4.datatype()); UnderlayMessage message5(std::forward(message4)); EXPECT_EQ(256, message5.timestamp()); EXPECT_EQ(256, message5.seq()); EXPECT_EQ("data forward", message5.data()); - EXPECT_EQ("datatype forward", message5.datatype()); EXPECT_EQ("", message4.data()); - EXPECT_EQ("", message4.datatype()); } } // namespace transport diff --git a/cyber/transport/rtps/sub_listener.cc b/cyber/transport/rtps/sub_listener.cc deleted file mode 100644 index e623f5b..0000000 --- a/cyber/transport/rtps/sub_listener.cc +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * Copyright 2018 The Apollo Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *****************************************************************************/ - -#include "cyber/transport/rtps/sub_listener.h" - -#include "cyber/common/log.h" -#include "cyber/common/util.h" - -namespace apollo { -namespace cyber { -namespace transport { - -SubListener::SubListener(const NewMsgCallback& callback) - : callback_(callback) {} - -SubListener::~SubListener() {} - -void SubListener::onNewDataMessage(eprosima::fastrtps::Subscriber* sub) { - RETURN_IF_NULL(sub); - RETURN_IF_NULL(callback_); - std::lock_guard lock(mutex_); - - // fetch channel name - auto channel_id = common::Hash(sub->getAttributes().topic.getTopicName()); - eprosima::fastrtps::SampleInfo_t m_info; - UnderlayMessage m; - - RETURN_IF(!sub->takeNextData(reinterpret_cast(&m), &m_info)); - RETURN_IF(m_info.sampleKind != eprosima::fastrtps::ALIVE); - - // fetch MessageInfo - char* ptr = - reinterpret_cast(&m_info.related_sample_identity.writer_guid()); - Identity sender_id(false); - sender_id.set_data(ptr); - msg_info_.set_sender_id(sender_id); - - Identity spare_id(false); - spare_id.set_data(ptr + ID_SIZE); - msg_info_.set_spare_id(spare_id); - - uint64_t seq_num = - ((int64_t)m_info.related_sample_identity.sequence_number().high) << 32 | - m_info.related_sample_identity.sequence_number().low; - msg_info_.set_seq_num(seq_num); - - // fetch message string - std::shared_ptr msg_str = - std::make_shared(m.data()); - - // callback - callback_(channel_id, msg_str, msg_info_); -} - -void SubListener::onSubscriptionMatched( - eprosima::fastrtps::Subscriber* sub, - eprosima::fastrtps::MatchingInfo& info) { - (void)sub; - (void)info; -} - -} // namespace transport -} // namespace cyber -} // namespace apollo diff --git a/cyber/transport/rtps/subscriber.cc b/cyber/transport/rtps/subscriber.cc new file mode 100644 index 0000000..52fbfdb --- /dev/null +++ b/cyber/transport/rtps/subscriber.cc @@ -0,0 +1,113 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#include "cyber/transport/rtps/subscriber.h" + +namespace apollo { +namespace cyber { +namespace transport { + +Subscriber::Subscriber(const std::string& name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DomainParticipant* participant, + const rtps::subsciber_callback& callback) + : channel_name_(name), + qos_(qos), + shutdown_(false), + callback_(callback), + subscriber_listener_(nullptr), + participant_(participant), + subscriber_(nullptr), + topic_(nullptr), + reader_(nullptr) {} + +Subscriber::~Subscriber() {} + +bool Subscriber::Init() { + eprosima::fastdds::dds::SubscriberQos sub_qos; + RETURN_VAL_IF( + !QosFiller::FillInSubQos(this->channel_name_, this->qos_, &sub_qos), + false); + subscriber_ = participant_->create_subscriber(sub_qos); + if (subscriber_ == nullptr) { + AINFO << "something went wrong while creating the fastdds subscriber..."; + return false; + } + + if (!EnsureCreateTopic(this->channel_name_)) { + AINFO << "something went wrong while creating the fastdds topic..."; + return false; + } + + eprosima::fastdds::dds::DataReaderQos reader_qos; + RETURN_VAL_IF( + !QosFiller::FillInReaderQos(this->channel_name_, this->qos_, &reader_qos), + false); + subscriber_listener_ = new dispatcher::SubscriberListener(this->callback_); + + reader_ = + subscriber_->create_datareader(topic_, reader_qos, subscriber_listener_); + if (reader_ == nullptr) { + AINFO << "something went wrong while creating the fastdds datareader..."; + return false; + } + + ADEBUG << "dds reader: " << reader_ << ", subscriber: " << this + << ", reader guid: " << reader_->guid() + << ", channel: " << this->channel_name_; + return true; +} + +void Subscriber::Shutdown() { + RETURN_IF(shutdown_.exchange(true)); + + if (subscriber_ != nullptr && reader_ != nullptr) { + subscriber_->delete_datareader(reader_); + reader_ = nullptr; + } + if (participant_ != nullptr && subscriber_ != nullptr) { + if (participant_->delete_subscriber(subscriber_) == + eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { + subscriber_ = nullptr; + } else { + AERROR << channel_name_ << ": Failed to delete the subscriber."; + } + } + if (participant_ != nullptr && topic_ != nullptr) { + participant_->delete_topic(topic_); + topic_ = nullptr; + } + + if (subscriber_listener_ != nullptr) { + delete subscriber_listener_; + } +} + +bool Subscriber::EnsureCreateTopic(const std::string& channel_name) { + topic_ = dynamic_cast( + participant_->lookup_topicdescription(channel_name)); + if (topic_ == nullptr) { + eprosima::fastdds::dds::TopicQos topic_qos; + RETURN_VAL_IF( + !QosFiller::FillInTopicQos(channel_name, this->qos_, &topic_qos), + false); + topic_ = + participant_->create_topic(channel_name, "UnderlayMessage", topic_qos); + } + return (topic_ != nullptr); +} + +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/rtps/subscriber.h b/cyber/transport/rtps/subscriber.h new file mode 100644 index 0000000..1cb5904 --- /dev/null +++ b/cyber/transport/rtps/subscriber.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_TRANSPORT_RTPS_SUBSCRIBER_H +#define CYBER_TRANSPORT_RTPS_SUBSCRIBER_H + +#include +#include +#include + +#include "cyber/base/macros.h" + +#include "fastdds/dds/domain/DomainParticipant.hpp" +#include "fastdds/dds/domain/DomainParticipantFactory.hpp" +#include "fastdds/dds/subscriber/DataReader.hpp" +#include "fastdds/dds/subscriber/DataReaderListener.hpp" +#include "fastdds/dds/subscriber/Subscriber.hpp" +#include "fastdds/dds/topic/Topic.hpp" +#include "fastdds/dds/topic/TypeSupport.hpp" + +#include "cyber/proto/qos_profile.pb.h" + +#include "cyber/common/log.h" +#include "cyber/service_discovery/communication/subscriber_listener.h" +#include "cyber/transport/dispatcher/subscriber_listener.h" +#include "cyber/transport/message/message_info.h" +#include "cyber/transport/qos/qos_filler.h" +#include "cyber/transport/rtps/underlay_message.h" + +namespace apollo { +namespace cyber { +namespace transport { +class Subscriber { + public: + Subscriber(const std::string& name, const proto::QosProfile& qos, + eprosima::fastdds::dds::DomainParticipant* participant, + const rtps::subsciber_callback& callback); + virtual ~Subscriber(); + + bool Init(); + void Shutdown(); + + private: + Subscriber(const Subscriber&) = delete; + Subscriber& operator=(const Subscriber&) = delete; + bool EnsureCreateTopic(const std::string& channel_name); + + std::string channel_name_; + proto::QosProfile qos_; + std::atomic shutdown_; + rtps::subsciber_callback callback_; + + eprosima::fastdds::dds::SubscriberListener* subscriber_listener_; + eprosima::fastdds::dds::DomainParticipant* participant_; + eprosima::fastdds::dds::Subscriber* subscriber_; + eprosima::fastdds::dds::Topic* topic_; + eprosima::fastdds::dds::DataReader* reader_; +}; +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif // CYBER_TRANSPORT_RTPS_SUBSCRIBER_H diff --git a/cyber/transport/rtps/underlay_message.cc b/cyber/transport/rtps/underlay_message.cc index 581af65..e1fbcf2 100644 --- a/cyber/transport/rtps/underlay_message.cc +++ b/cyber/transport/rtps/underlay_message.cc @@ -22,15 +22,17 @@ #include "cyber/transport/rtps/underlay_message.h" -#include "fastcdr/exceptions/BadParamException.h" - namespace apollo { namespace cyber { namespace transport { +#define UnderlayMessage_max_cdr_typesize 276ULL; +#define UnderlayMessage_max_key_cdr_typesize 0ULL; + UnderlayMessage::UnderlayMessage() { m_timestamp = 0; m_seq = 0; + m_data = ""; } UnderlayMessage::~UnderlayMessage() {} @@ -39,21 +41,18 @@ UnderlayMessage::UnderlayMessage(const UnderlayMessage& x) { m_timestamp = x.m_timestamp; m_seq = x.m_seq; m_data = x.m_data; - m_datatype = x.m_datatype; } UnderlayMessage::UnderlayMessage(UnderlayMessage&& x) { m_timestamp = x.m_timestamp; m_seq = x.m_seq; m_data = std::move(x.m_data); - m_datatype = std::move(x.m_datatype); } UnderlayMessage& UnderlayMessage::operator=(const UnderlayMessage& x) { m_timestamp = x.m_timestamp; m_seq = x.m_seq; m_data = x.m_data; - m_datatype = x.m_datatype; return *this; } @@ -62,27 +61,12 @@ UnderlayMessage& UnderlayMessage::operator=(UnderlayMessage&& x) { m_timestamp = x.m_timestamp; m_seq = x.m_seq; m_data = std::move(x.m_data); - m_datatype = std::move(x.m_datatype); return *this; } size_t UnderlayMessage::getMaxCdrSerializedSize(size_t current_alignment) { - size_t initial_alignment = current_alignment; - - current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); - - current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); - - current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + 255 + 1; - - current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + 255 + 1; - - return current_alignment - initial_alignment; + return UnderlayMessage_max_cdr_typesize; } size_t UnderlayMessage::getCdrSerializedSize(const UnderlayMessage& data, @@ -90,41 +74,32 @@ size_t UnderlayMessage::getCdrSerializedSize(const UnderlayMessage& data, size_t initial_alignment = current_alignment; current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + 8 + eprosima::fastcdr::Cdr::alignment(current_alignment, 8); current_alignment += - 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + 8 + eprosima::fastcdr::Cdr::alignment(current_alignment, 8); current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + data.data().size() + 1; - current_alignment += 4 + - eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + - data.datatype().size() + 1; - return current_alignment - initial_alignment; } void UnderlayMessage::serialize(eprosima::fastcdr::Cdr& scdr) const { scdr << m_timestamp; - scdr << m_seq; - scdr << m_data; - scdr << m_datatype; } void UnderlayMessage::deserialize(eprosima::fastcdr::Cdr& dcdr) { dcdr >> m_timestamp; dcdr >> m_seq; dcdr >> m_data; - dcdr >> m_datatype; } size_t UnderlayMessage::getKeyMaxCdrSerializedSize(size_t current_alignment) { - size_t current_align = current_alignment; - return current_align; + return UnderlayMessage_max_key_cdr_typesize; } bool UnderlayMessage::isKeyDefined() { return false; } diff --git a/cyber/transport/rtps/underlay_message.h b/cyber/transport/rtps/underlay_message.h index b80e32e..e279df2 100644 --- a/cyber/transport/rtps/underlay_message.h +++ b/cyber/transport/rtps/underlay_message.h @@ -24,6 +24,8 @@ #include #include +#include "cyber/base/macros.h" + #include "fastcdr/Cdr.h" namespace apollo { @@ -75,36 +77,36 @@ class UnderlayMessage { * @brief This function sets a value in member timestamp * @param _timestamp New value for member timestamp */ - inline void timestamp(int32_t _timestamp) { m_timestamp = _timestamp; } + inline void timestamp(uint64_t _timestamp) { m_timestamp = _timestamp; } /*! * @brief This function returns the value of member timestamp * @return Value of member timestamp */ - inline int32_t timestamp() const { return m_timestamp; } + inline uint64_t timestamp() const { return m_timestamp; } /*! * @brief This function returns a reference to member timestamp * @return Reference to member timestamp */ - inline int32_t& timestamp() { return m_timestamp; } + inline uint64_t& timestamp() { return m_timestamp; } /*! * @brief This function sets a value in member seq * @param _seq New value for member seq */ - inline void seq(int32_t _seq) { m_seq = _seq; } + inline void seq(uint64_t _seq) { m_seq = _seq; } /*! * @brief This function returns the value of member seq * @return Value of member seq */ - inline int32_t seq() const { return m_seq; } + inline uint64_t seq() const { return m_seq; } /*! * @brief This function returns a reference to member seq * @return Reference to member seq */ - inline int32_t& seq() { return m_seq; } + inline uint64_t& seq() { return m_seq; } /*! * @brief This function copies the value in member data * @param _data New value to be copied in member data @@ -128,31 +130,6 @@ class UnderlayMessage { * @return Reference to member data */ inline std::string& data() { return m_data; } - /*! - * @brief This function copies the value in member datatype - * @param _datatype New value to be copied in member datatype - */ - inline void datatype(const std::string& _datatype) { m_datatype = _datatype; } - - /*! - * @brief This function moves the value in member datatype - * @param _datatype New value to be moved in member datatype - */ - inline void datatype(std::string&& _datatype) { - m_datatype = std::move(_datatype); - } - - /*! - * @brief This function returns a constant reference to member datatype - * @return Constant reference to member datatype - */ - inline const std::string& datatype() const { return m_datatype; } - - /*! - * @brief This function returns a reference to member datatype - * @return Reference to member datatype - */ - inline std::string& datatype() { return m_datatype; } /*! * @brief This function returns the maximum serialized size of an object @@ -206,10 +183,9 @@ class UnderlayMessage { void serializeKey(eprosima::fastcdr::Cdr& cdr) const; // NOLINT private: - int32_t m_timestamp; - int32_t m_seq; + uint64_t m_timestamp; + uint64_t m_seq; std::string m_data; - std::string m_datatype; }; } // namespace transport diff --git a/cyber/transport/rtps/underlay_message_type.cc b/cyber/transport/rtps/underlay_message_type.cc index 8af2601..8c0c425 100644 --- a/cyber/transport/rtps/underlay_message_type.cc +++ b/cyber/transport/rtps/underlay_message_type.cc @@ -21,6 +21,8 @@ #include "cyber/transport/rtps/underlay_message_type.h" +#include + #include "fastcdr/Cdr.h" #include "fastcdr/FastBuffer.h" @@ -32,13 +34,16 @@ namespace transport { UnderlayMessageType::UnderlayMessageType() { setName("UnderlayMessage"); - m_typeSize = (uint32_t)UnderlayMessage::getMaxCdrSerializedSize() + - 4 /*encapsulation*/; + auto type_size = UnderlayMessage::getMaxCdrSerializedSize(); + type_size += eprosima::fastcdr::Cdr::alignment( + type_size, 4); /* possible submessage alignment */ + m_typeSize = static_cast(type_size) + 4; /*encapsulation*/ m_isGetKeyDefined = UnderlayMessage::isKeyDefined(); - m_keyBuffer = - (unsigned char*)malloc(UnderlayMessage::getKeyMaxCdrSerializedSize() > 16 - ? UnderlayMessage::getKeyMaxCdrSerializedSize() - : 16); + size_t keyLength = UnderlayMessage::getKeyMaxCdrSerializedSize() > 16 + ? UnderlayMessage::getKeyMaxCdrSerializedSize() + : 16; + m_keyBuffer = (unsigned char*)malloc(keyLength); + memset(m_keyBuffer, 0, keyLength); } UnderlayMessageType::~UnderlayMessageType() { @@ -47,41 +52,61 @@ UnderlayMessageType::~UnderlayMessageType() { } } -bool UnderlayMessageType::serialize(void* data, SerializedPayload_t* payload) { +bool UnderlayMessageType::serialize( + void* data, eprosima::fastrtps::rtps::SerializedPayload_t* payload) { UnderlayMessage* p_type = reinterpret_cast(data); eprosima::fastcdr::FastBuffer fastbuffer( reinterpret_cast(payload->data), payload->max_size); // Object that manages the raw buffer. eprosima::fastcdr::Cdr ser( fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, - eprosima::fastcdr::Cdr::DDS_CDR); // Object that serializes the data. + eprosima::fastcdr::CdrVersion::DDS_CDR); // Object that serializes the + // data. payload->encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; - // Serialize encapsulation - ser.serialize_encapsulation(); - p_type->serialize(ser); // Serialize the object: + try { + // Serialize encapsulation + ser.serialize_encapsulation(); + // Serialize the object. + p_type->serialize(ser); + } catch (eprosima::fastcdr::exception::Exception& e) { + AERROR << "serialize exception: " << e.what(); + return false; + } + payload->length = - (uint32_t)ser.getSerializedDataLength(); // Get the serialized length + (uint32_t)ser.get_serialized_data_length(); // Get the serialized length return true; } -bool UnderlayMessageType::deserialize(SerializedPayload_t* payload, - void* data) { - UnderlayMessage* p_type = reinterpret_cast( - data); // Convert DATA to pointer of your type - eprosima::fastcdr::FastBuffer fastbuffer( - reinterpret_cast(payload->data), - payload->length); // Object that manages the raw buffer. - eprosima::fastcdr::Cdr deser( - fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, - eprosima::fastcdr::Cdr::DDS_CDR); // Object that deserializes the data. - // Deserialize encapsulation. - deser.read_encapsulation(); - payload->encapsulation = - deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE - : CDR_LE; - p_type->deserialize(deser); // Deserialize the object: +bool UnderlayMessageType::deserialize( + eprosima::fastrtps::rtps::SerializedPayload_t* payload, void* data) { + try { + // Convert DATA to pointer of your type + UnderlayMessage* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer( + reinterpret_cast(payload->data), payload->length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, + eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + eprosima::fastcdr::CdrVersion::DDS_CDR); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload->encapsulation = + deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE + : CDR_LE; + + // Deserialize the object. + p_type->deserialize(deser); + } catch (eprosima::fastcdr::exception::Exception& e) { + AERROR << "deserialize exception: " << e.what(); + return false; + } return true; } @@ -90,7 +115,7 @@ std::function UnderlayMessageType::getSerializedSizeProvider( return [data]() -> uint32_t { return (uint32_t)type::getCdrSerializedSize( *static_cast(data)) + - 4 /*encapsulation*/; + 4u /*encapsulation*/; }; } @@ -102,21 +127,23 @@ void UnderlayMessageType::deleteData(void* data) { delete (reinterpret_cast(data)); } -bool UnderlayMessageType::getKey(void* data, InstanceHandle_t* handle) { - RETURN_VAL_IF((!m_isGetKeyDefined), false); +bool UnderlayMessageType::getKey( + void* data, eprosima::fastrtps::rtps::InstanceHandle_t* handle, + bool force_md5) { + RETURN_VAL_IF(!m_isGetKeyDefined, false); UnderlayMessage* p_type = reinterpret_cast(data); eprosima::fastcdr::FastBuffer fastbuffer( reinterpret_cast(m_keyBuffer), UnderlayMessage::getKeyMaxCdrSerializedSize()); // Object that manages // the raw buffer. - eprosima::fastcdr::Cdr ser( - fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS); // Object that - // serializes the - // data. + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, + eprosima::fastcdr::Cdr::BIG_ENDIANNESS); p_type->serializeKey(ser); - if (UnderlayMessage::getKeyMaxCdrSerializedSize() > 16) { + if (force_md5 || UnderlayMessage::getKeyMaxCdrSerializedSize() > 16) { m_md5.init(); - m_md5.update(m_keyBuffer, (unsigned int)ser.getSerializedDataLength()); + m_md5.update(m_keyBuffer, + static_cast(ser.get_serialized_data_length())); m_md5.finalize(); for (uint8_t i = 0; i < 16; ++i) { handle->value[i] = m_md5.digest[i]; diff --git a/cyber/transport/rtps/underlay_message_type.h b/cyber/transport/rtps/underlay_message_type.h index 01db001..a57a012 100644 --- a/cyber/transport/rtps/underlay_message_type.h +++ b/cyber/transport/rtps/underlay_message_type.h @@ -17,8 +17,11 @@ #ifndef CYBER_TRANSPORT_RTPS_UNDERLAY_MESSAGE_TYPE_H_ #define CYBER_TRANSPORT_RTPS_UNDERLAY_MESSAGE_TYPE_H_ +#include "cyber/base/macros.h" + +#include "fastdds/dds/topic/TopicDataType.hpp" +#include "fastrtps/utils/md5.h" #include "cyber/transport/rtps/underlay_message.h" -#include "fastrtps/TopicDataType.h" namespace apollo { namespace cyber { @@ -29,18 +32,25 @@ namespace transport { * defined by the user in the IDL file. * @ingroup UNDERLAYMESSAGE */ -class UnderlayMessageType : public eprosima::fastrtps::TopicDataType { +class UnderlayMessageType : public eprosima::fastdds::dds::TopicDataType { public: using type = UnderlayMessage; UnderlayMessageType(); virtual ~UnderlayMessageType(); - bool serialize(void* data, SerializedPayload_t* payload); - bool deserialize(SerializedPayload_t* payload, void* data); - std::function getSerializedSizeProvider(void* data); - bool getKey(void* data, InstanceHandle_t* ihandle); - void* createData(); - void deleteData(void* data); + virtual bool serialize( // NOLINT + void* data, + eprosima::fastrtps::rtps::SerializedPayload_t* payload) override; + virtual bool deserialize( // NOLINT + eprosima::fastrtps::rtps::SerializedPayload_t* payload, + void* data) override; + virtual std::function getSerializedSizeProvider( // NOLINT + void* data) override; + virtual bool getKey(void* data, // NOLINT + eprosima::fastrtps::rtps::InstanceHandle_t* ihandle, + bool force_md5 = false) override; + virtual void* createData() override; // NOLINT + virtual void deleteData(void* data) override; // NOLINT MD5 m_md5; unsigned char* m_keyBuffer; }; diff --git a/cyber/transport/shm/arena_address_allocator.cc b/cyber/transport/shm/arena_address_allocator.cc new file mode 100644 index 0000000..bd94084 --- /dev/null +++ b/cyber/transport/shm/arena_address_allocator.cc @@ -0,0 +1,458 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#include "cyber/transport/shm/arena_address_allocator.h" + +#include +#include +#include +#include + +#include "cyber/base/pthread_rw_lock.h" +#include "cyber/base/rw_lock_guard.h" + +namespace apollo { +namespace cyber { +namespace transport { + +ArenaAddressAllocator::ArenaAddressAllocator() + : meta_shm_key_( + std::hash{}("/apollo/__arena__/__address__/__meta__")), + node_shm_key_( + std::hash{}("/apollo/__arena__/__address__/__node__")), + meta_(nullptr), + nodes_(nullptr), + reclaim_stack_(nullptr) { + // TODO(all): configurable and address management for shared memory of cyber + meta_shm_address_ = nullptr; + // use fixed address + node_shm_address_ = reinterpret_cast(0x7f0000000000); + + // ensure the allocator's segment size is larger + // than the actual arena's segment size + // otherwise the shmat will fail + Init(1024, reinterpret_cast( + 0x710000000000), 2ULL * 1024 * 1024 * 1024); +} + +ArenaAddressAllocator::~ArenaAddressAllocator() { + if (meta_ && meta_->struct_.ref_count_.fetch_sub(1) == 0) { + shmdt(meta_); + shmctl(shmget(meta_shm_key_, 0, 0), IPC_RMID, nullptr); + shmdt(nodes_); + shmctl(shmget(node_shm_key_, 0, 0), IPC_RMID, nullptr); + } +} + +bool ArenaAddressAllocator::Init(uint64_t capacity, void* base_address, + uint64_t address_segment_size) { + if (!OpenMetaShm(capacity, base_address, address_segment_size)) { + return false; + } + if (!OpenNodeShm(capacity, base_address, address_segment_size)) { + return false; + } + meta_->struct_.occupied_.store(false); + return true; +} + +bool ArenaAddressAllocator::Open(uint64_t key, void* base_address, + void** shm_address) { + auto shmid = shmget(static_cast(key), 0, 0); + + shmid = shmget(static_cast(key), 0, 0); + if (shmid == -1) { + // open failed + return false; + } + *shm_address = shmat(shmid, base_address, 0); + if (*shm_address == reinterpret_cast(-1)) { + // shmat failed + return false; + } + return true; +} + +bool ArenaAddressAllocator::OpenOrCreate(uint64_t key, uint64_t size, + void* base_address, void** shm_address, + bool* is_created) { + auto shmid = + shmget(static_cast(key), size, 0644 | IPC_CREAT | IPC_EXCL); + + if (shmid == -1) { + if (errno == EINVAL) { + // TODO(all): recreate larger shm + } else if (errno == EEXIST) { + *is_created = false; + return Open(key, base_address, shm_address); + } else { + return false; + } + } + *shm_address = shmat(shmid, base_address, 0); + if (*shm_address == reinterpret_cast(-1)) { + // shmat failed + return false; + } + *is_created = true; + return true; +} + +bool ArenaAddressAllocator::OpenMetaShm(uint64_t capacity, void* base_address, + uint64_t address_segment_size) { + bool is_created = false; + bool ret = false; + for (uint32_t retry = 0; retry < 2 && !ret; + ++retry, ret = OpenOrCreate( + meta_shm_key_, sizeof(ArenaAddressAllocatorMeta), + meta_shm_address_, reinterpret_cast(&meta_), + &is_created)) { + } + if (!ret) { + // create or open failed + return false; + } + if (!is_created) { + meta_->struct_.ref_count_.fetch_add(1); + } else { + meta_->struct_.version_ = 1; + meta_->struct_.capacity_ = capacity; + meta_->struct_.base_address_ = base_address; + meta_->struct_.address_segment_size_ = address_segment_size; + meta_->struct_.root_ = nullptr; + meta_->struct_.allocated_index_ = 0; + meta_->struct_.reclaim_stack_top_ = 0; + meta_->struct_.ref_count_.store(1); + } + return true; +} + +bool ArenaAddressAllocator::OpenNodeShm(uint64_t capacity, void* base_address, + uint64_t address_segment_size) { + uint64_t size = sizeof(ArenaAddressAllocatorMeta) + + sizeof(ArenaAddressNode) * (capacity + 1) + + sizeof(uint64_t) * capacity; + bool is_created = false; + bool ret = false; + for (uint32_t retry = 0; retry < 2 && !ret; + ++retry, ret = OpenOrCreate(node_shm_key_, size, node_shm_address_, + reinterpret_cast(&nodes_), + &is_created)) { + } + if (!ret) { + // create or open failed + return false; + } + + reclaim_stack_ = reinterpret_cast( + reinterpret_cast(nodes_) + sizeof(ArenaAddressNode) * capacity); + return true; +} + +ArenaAddressNode* ArenaAddressAllocator::NewNode(uint64_t key) { + if (meta_->struct_.reclaim_stack_top_ > 0) { + uint64_t index = reclaim_stack_[--meta_->struct_.reclaim_stack_top_]; + nodes_[index].left_ = nullptr; + nodes_[index].right_ = nullptr; + nodes_[index].key_ = key; + return &nodes_[index]; + } + if (meta_->struct_.allocated_index_ >= meta_->struct_.capacity_) { + // TODO(all): expand nodes + return nullptr; + } + nodes_[meta_->struct_.allocated_index_].left_ = nullptr; + nodes_[meta_->struct_.allocated_index_].right_ = nullptr; + nodes_[meta_->struct_.allocated_index_].key_ = key; + nodes_[meta_->struct_.allocated_index_].index_ = + meta_->struct_.allocated_index_; + return &nodes_[meta_->struct_.allocated_index_++]; +} + +void ArenaAddressAllocator::ReclaimNode(ArenaAddressNode* node) { + nodes_[node->index_].left_ = nullptr; + nodes_[node->index_].right_ = nullptr; + nodes_[node->index_].parent_ = nullptr; + reclaim_stack_[meta_->struct_.reclaim_stack_top_++] = node->index_; +} + +ArenaAddressNode* ArenaAddressAllocator::FindNode(ArenaAddressNode* node, + uint64_t key) { + if (node == nullptr) { + return nullptr; + } + if (key < node->key_) { + return FindNode(node->left_, key); + } else if (key > node->key_) { + return FindNode(node->right_, key); + } + return node; +} + +ArenaAddressNode* ArenaAddressAllocator::FindOrInsertNode( + ArenaAddressNode* node, ArenaAddressNode** node_p, ArenaAddressNode* parent, + uint64_t key) { + if (node == nullptr) { + auto target = NewNode(key); + *node_p = target; + target->parent_ = parent; + return target; + } + if (key < node->key_) { + auto target = FindOrInsertNode(node->left_, &(node->left_), node, key); + TreeRebalance(node->left_, &(node->left_)); + return target; + } else if (key > node->key_) { + auto target = FindOrInsertNode(node->right_, &(node->right_), node, key); + TreeRebalance(node->right_, &(node->right_)); + return target; + } + // key == node->key_ + return node; +} + +void ArenaAddressAllocator::RemoveNode(ArenaAddressNode* node, + ArenaAddressNode** node_p, + uint64_t key) { + if (!node) { + return; + } + if (!FindNode(node, key)) { + return; + } + if (key < node->key_) { + RemoveNode(node->left_, &(node->left_), key); + if (TreeBalanceFactor(node) < -1) { + TreeRebalance(meta_->struct_.root_, &(meta_->struct_.root_)); + } + return; + } else if (key > node->key_) { + RemoveNode(node->right_, &(node->right_), key); + if (TreeBalanceFactor(node) > 1) { + TreeRebalance(meta_->struct_.root_, &(meta_->struct_.root_)); + } + return; + } + // node->key_ == key + // left and right both exist + if (node->left_ && node->right_) { + if (TreeBalanceFactor(node) > 0) { + auto max_p = &(node->left_); + auto max = TreeMax(node->left_, &max_p); + SwapNodePosition(node, node_p, max, max_p); + RemoveNode(max->left_, &(max->left_), key); + return; + } else { + auto min_p = &(node->right_); + auto min = TreeMin(node->right_, &min_p); + SwapNodePosition(node, node_p, min, min_p); + RemoveNode(min->right_, &(min->right_), key); + return; + } + } + // left or right exist + *node_p = node->left_ ? node->left_ : node->right_; + ReclaimNode(node); +} + +void ArenaAddressAllocator::SwapNodePosition(ArenaAddressNode* x, + ArenaAddressNode** x_p, + ArenaAddressNode* y, + ArenaAddressNode** y_p) { + if (x == nullptr || y == nullptr) { + // cannot swap nullptr + return; + } + + // swap address + *x_p = y; + *y_p = x; + // swap parent + auto parent_x = x->parent_; + auto parent_y = y->parent_; + x->parent_ = parent_y; + y->parent_ = parent_x; + + ArenaAddressNode* tmp = nullptr; + + // swap left + tmp = x->left_; + x->left_ = y->left_; + if (x->left_) { + x->left_->parent_ = x; + } + y->left_ = tmp; + if (y->left_) { + y->left_->parent_ = y; + } + + // swap right + tmp = x->right_; + x->right_ = y->right_; + if (x->right_) { + x->right_->parent_ = x; + } + y->right_ = tmp; + if (y->right_) { + y->right_->parent_ = y; + } +} + +uint64_t ArenaAddressAllocator::TreeHeight(ArenaAddressNode* node) { + if (node == nullptr) { + return 0; + } + return 1 + std::max(TreeHeight(node->left_), TreeHeight(node->right_)); +} + +ArenaAddressNode* ArenaAddressAllocator::TreeMax(ArenaAddressNode* node, + ArenaAddressNode*** node_pp) { + if (node == nullptr) { + return nullptr; + } + for (; node->right_;) { + *node_pp = &(node->right_); + node = node->right_; + } + return node; +} + +ArenaAddressNode* ArenaAddressAllocator::TreeMin(ArenaAddressNode* node, + ArenaAddressNode*** node_pp) { + if (node == nullptr) { + return nullptr; + } + for (; node->left_;) { + *node_pp = &(node->left_); + node = node->left_; + } + return node; +} + +int64_t ArenaAddressAllocator::TreeBalanceFactor(ArenaAddressNode* node) { + if (node == nullptr) { + return 0; + } + return TreeHeight(node->left_) - TreeHeight(node->right_); +} + +ArenaAddressNode* ArenaAddressAllocator::TreeRotateLeft( + ArenaAddressNode* node, ArenaAddressNode** node_p) { + auto parent = node->parent_; + auto right = node->right_; + + node->right_ = right->left_; + right->left_ = node; + node->parent_ = right; + *node_p = right; + right->parent_ = parent; + + return right; +} + +ArenaAddressNode* ArenaAddressAllocator::TreeRotateRight( + ArenaAddressNode* node, ArenaAddressNode** node_p) { + auto parent = node->parent_; + auto left = node->left_; + + node->left_ = left->right_; + left->right_ = node; + node->parent_ = left; + *node_p = left; + left->parent_ = parent; + + return left; +} + +ArenaAddressNode* ArenaAddressAllocator::TreeRotateLeftRight( + ArenaAddressNode* node, ArenaAddressNode** node_p) { + TreeRotateLeft(node->left_, &(node->left_)); + return TreeRotateRight(node, node_p); +} + +ArenaAddressNode* ArenaAddressAllocator::TreeRotateRightLeft( + ArenaAddressNode* node, ArenaAddressNode** node_p) { + TreeRotateRight(node->right_, &(node->right_)); + return TreeRotateLeft(node, node_p); +} + +ArenaAddressNode* ArenaAddressAllocator::TreeRebalance( + ArenaAddressNode* node, ArenaAddressNode** node_p) { + if (node == nullptr) { + return nullptr; + } + auto balance_factor = TreeBalanceFactor(node); + if (balance_factor > 1) { + if (TreeBalanceFactor(node->left_) > 0) { + return TreeRotateRight(node, node_p); + } else { + return TreeRotateLeftRight(node, node_p); + } + } else if (balance_factor < -1) { + if (TreeBalanceFactor(node->right_) < 0) { + return TreeRotateLeft(node, node_p); + } else { + return TreeRotateRightLeft(node, node_p); + } + } + return node; +} + +void* ArenaAddressAllocator::Allocate(uint64_t key) { + bool idle_status = false; + bool occupied_status = true; + while (!meta_->struct_.occupied_.compare_exchange_strong( + idle_status, occupied_status)) { + // exchange failed, idle_status is set to true. + idle_status = false; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + } + auto node = FindOrInsertNode(meta_->struct_.root_, &(meta_->struct_.root_), + nullptr, key); + meta_->struct_.occupied_.store(false); + if (node == nullptr) { + return nullptr; + } + + node->ref_count_.fetch_add(1); + + return reinterpret_cast( + reinterpret_cast(meta_->struct_.base_address_) + + meta_->struct_.address_segment_size_ * node->index_); +} + +void ArenaAddressAllocator::Deallocate(uint64_t key) { + bool idle_status = false; + bool occupied_status = true; + while (!meta_->struct_.occupied_.compare_exchange_strong( + idle_status, occupied_status)) { + // exchange failed, idle_status is set to true. + idle_status = false; + std::this_thread::sleep_for(std::chrono::microseconds(1000)); + } + auto node = FindNode(meta_->struct_.root_, key); + meta_->struct_.occupied_.store(false); + if (node == nullptr) { + return; + } + + if (node->ref_count_.fetch_sub(1) == 0) { + RemoveNode(meta_->struct_.root_, &(meta_->struct_.root_), key); + } +} + +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/shm/arena_address_allocator.h b/cyber/transport/shm/arena_address_allocator.h new file mode 100644 index 0000000..7ddc3c1 --- /dev/null +++ b/cyber/transport/shm/arena_address_allocator.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_TRANSPORT_SHM_ARENA_ADDRESS_ALLOCATOR_H_ +#define CYBER_TRANSPORT_SHM_ARENA_ADDRESS_ALLOCATOR_H_ + +#include +#include + +#include "cyber/base/pthread_rw_lock.h" +#include "cyber/common/macros.h" + +namespace apollo { +namespace cyber { +namespace transport { + +struct ArenaAddressNode { + uint64_t key_; + uint64_t index_; + std::atomic ref_count_; + struct ArenaAddressNode* parent_; + struct ArenaAddressNode* left_; + struct ArenaAddressNode* right_; +}; + +union ArenaAddressAllocatorMeta { + struct { + uint64_t version_; + uint64_t capacity_; + std::atomic ref_count_; + void* base_address_; + // TODO(ALL): support multiple size + uint64_t address_segment_size_; + ArenaAddressNode* root_; + uint64_t allocated_index_; + uint64_t reclaim_stack_top_; + // base::PthreadRWLock mutex_; + std::atomic occupied_; + } struct_; + uint8_t bytes_[128]; +}; + +class ArenaAddressAllocator { + public: + ArenaAddressAllocator(); + ~ArenaAddressAllocator(); + + bool Init(uint64_t capacity, void* base_address, + uint64_t address_segment_size); + + bool OpenOrCreate(uint64_t key, uint64_t size, void* base_address, + void** shm_address, bool* is_created); + bool Open(uint64_t key, void* base_address, void** shm_address); + + bool OpenOrCreate(uint64_t capacity, void* base_address, + uint64_t address_segment_size); + + bool OpenMetaShm(uint64_t capacity, void* base_address, + uint64_t address_segment_size); + + bool OpenNodeShm(uint64_t capacity, void* base_address, + uint64_t address_segment_size); + + ArenaAddressNode* NewNode(uint64_t key); + void ReclaimNode(ArenaAddressNode* node); + ArenaAddressNode* FindNode(ArenaAddressNode* node, uint64_t key); + ArenaAddressNode* FindOrInsertNode(ArenaAddressNode* node, + ArenaAddressNode** node_p, + ArenaAddressNode* parent, uint64_t key); + void RemoveNode(ArenaAddressNode* node, ArenaAddressNode** node_addr, + uint64_t key); + void SwapNodePosition(ArenaAddressNode* x, ArenaAddressNode** x_p, + ArenaAddressNode* y, ArenaAddressNode** y_p); + uint64_t TreeHeight(ArenaAddressNode* node); + ArenaAddressNode* TreeMax(ArenaAddressNode* node, + ArenaAddressNode*** node_pp); + ArenaAddressNode* TreeMin(ArenaAddressNode* node, + ArenaAddressNode*** node_pp); + int64_t TreeBalanceFactor(ArenaAddressNode* node); + ArenaAddressNode* TreeRebalance(ArenaAddressNode* node, + ArenaAddressNode** node_p); + ArenaAddressNode* TreeRotateLeft(ArenaAddressNode* node, + ArenaAddressNode** node_p); + ArenaAddressNode* TreeRotateRight(ArenaAddressNode* node, + ArenaAddressNode** node_p); + ArenaAddressNode* TreeRotateLeftRight(ArenaAddressNode* node, + ArenaAddressNode** node_p); + ArenaAddressNode* TreeRotateRightLeft(ArenaAddressNode* node, + ArenaAddressNode** node_p); + void* Allocate(uint64_t key); + void Deallocate(uint64_t key); + + private: + uint64_t meta_shm_key_; + uint64_t node_shm_key_; + void* meta_shm_address_; + void* node_shm_address_; + ArenaAddressAllocatorMeta* meta_; + ArenaAddressNode* nodes_; + ArenaAddressNode* root_; + uint64_t* reclaim_stack_; + // DECLARE_SINGLETON(ArenaAddressAllocator) +}; + +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif diff --git a/cyber/transport/shm/posix_segment.cc b/cyber/transport/shm/posix_segment.cc index c1519ed..d9d963b 100644 --- a/cyber/transport/shm/posix_segment.cc +++ b/cyber/transport/shm/posix_segment.cc @@ -96,13 +96,28 @@ bool PosixSegment::OpenOrCreate() { return false; } + // create field arena_blocks_ + arena_blocks_ = new (static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block)) Block[ + ShmConf::ARENA_BLOCK_NUM]; + if (arena_blocks_ == nullptr) { + AERROR << "create blocks failed."; + state_->~State(); + state_ = nullptr; + munmap(managed_shm_, conf_.managed_shm_size()); + managed_shm_ = nullptr; + shm_unlink(shm_name_.c_str()); + return false; + } + // create block buf uint32_t i = 0; for (; i < conf_.block_num(); ++i) { uint8_t* addr = - new (static_cast(managed_shm_) + sizeof(State) + - conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()) - uint8_t[conf_.block_buf_size()]; + new (static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + \ + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ + i * conf_.block_buf_size()) uint8_t[conf_.block_buf_size()]; if (addr == nullptr) { break; @@ -112,15 +127,38 @@ bool PosixSegment::OpenOrCreate() { block_buf_addrs_[i] = addr; } - if (i != conf_.block_num()) { - AERROR << "create block buf failed."; + // create arena block buf + uint32_t ai = 0; + for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { + uint8_t* addr = \ + new(static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + \ + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ + conf_.block_num() * conf_.block_buf_size() + \ + ai * ShmConf::ARENA_MESSAGE_SIZE) uint8_t[ + ShmConf::ARENA_MESSAGE_SIZE]; + if (addr == nullptr) { + break; + } + + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_[ai] = addr; + } + + if (ai != ShmConf::ARENA_BLOCK_NUM || i != conf_.block_num()) { + AERROR << "create arena block buf failed."; state_->~State(); state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard lg(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard lg(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } munmap(managed_shm_, conf_.managed_shm_size()); managed_shm_ = nullptr; shm_unlink(shm_name_.c_str()); @@ -183,26 +221,64 @@ bool PosixSegment::OpenOnly() { return false; } + // get field arena_blocks_ + arena_blocks_ = reinterpret_cast( + static_cast(managed_shm_) + sizeof(State) + + sizeof(Block) * conf_.block_num()); + if (blocks_ == nullptr) { + AERROR << "get arena blocks failed."; + state_ = nullptr; + munmap(managed_shm_, conf_.managed_shm_size()); + managed_shm_ = nullptr; + return false; + } + // get block buf uint32_t i = 0; for (; i < conf_.block_num(); ++i) { uint8_t* addr = reinterpret_cast( static_cast(managed_shm_) + sizeof(State) + - conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()); + conf_.block_num() * sizeof(Block) + + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + + i * conf_.block_buf_size()); + if (addr == nullptr) { + break; + } std::lock_guard lg(block_buf_lock_); block_buf_addrs_[i] = addr; } - if (i != conf_.block_num()) { + // get arena block buf + uint32_t ai = 0; + for (; i < ShmConf::ARENA_BLOCK_NUM; ++ai) { + uint8_t* addr = reinterpret_cast( + static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + ShmConf::ARENA_BLOCK_NUM * \ + sizeof(Block) + conf_.block_num() * conf_.block_buf_size() + \ + ai * ShmConf::ARENA_MESSAGE_SIZE); + + if (addr == nullptr) { + break; + } + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_[ai] = addr; + } + + if (i != conf_.block_num() || ai != ShmConf::ARENA_BLOCK_NUM) { AERROR << "open only failed."; state_->~State(); state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard lg(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard lg(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } munmap(managed_shm_, conf_.managed_shm_size()); managed_shm_ = nullptr; shm_unlink(shm_name_.c_str()); @@ -226,10 +302,15 @@ bool PosixSegment::Remove() { void PosixSegment::Reset() { state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard lg(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard lg(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } if (managed_shm_ != nullptr) { munmap(managed_shm_, conf_.managed_shm_size()); managed_shm_ = nullptr; diff --git a/cyber/transport/shm/protobuf_arena_manager.cc b/cyber/transport/shm/protobuf_arena_manager.cc new file mode 100644 index 0000000..30db9b7 --- /dev/null +++ b/cyber/transport/shm/protobuf_arena_manager.cc @@ -0,0 +1,564 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#include "cyber/transport/shm/protobuf_arena_manager.h" + +#include +#include + +#include +#include + +#include +#include + +#include "cyber/transport/shm/segment_factory.h" + +namespace apollo { +namespace cyber { +namespace transport { + +const int32_t ArenaSegmentBlock::kRWLockFree = 0; +const int32_t ArenaSegmentBlock::kWriteExclusive = -1; +const int32_t ArenaSegmentBlock::kMaxTryLockTimes = 5; + +ArenaSegment::ArenaSegment() + : channel_id_(0), key_id_(0), base_address_(nullptr) {} + +ArenaSegment::ArenaSegment(uint64_t channel_id) + : channel_id_(channel_id), + key_id_(std::hash{}("/apollo/__arena__/" + + std::to_string(channel_id))) {} + +ArenaSegment::ArenaSegment(uint64_t channel_id, void* base_address) + : channel_id_(channel_id), + key_id_(std::hash{}("/apollo/__arena__/" + + std::to_string(channel_id))), + base_address_(base_address) {} + +ArenaSegment::ArenaSegment(uint64_t channel_id, uint64_t message_size, + uint64_t block_num, void* base_address) + : channel_id_(channel_id), + key_id_(std::hash{}("/apollo/__arena__/" + + std::to_string(channel_id))), + base_address_(base_address) { + Init(message_size, block_num); +} + +ArenaSegment::~ArenaSegment() {} + +bool ArenaSegment::Init(uint64_t message_size, uint64_t block_num) { + uint64_t key_id = std::hash{}("/apollo/__arena__/" + + std::to_string(channel_id_)); + // fprintf(stderr, "channel_id: %lx, key_id: %lx\n", channel_id_, key_id); + + for (uint32_t retry = 0; retry < 2 && !OpenOrCreate(message_size, block_num); + ++retry) { + } + + return true; +} + +bool ArenaSegment::OpenOrCreate(uint64_t message_size, uint64_t block_num) { + auto arena_conf = + cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id_); + auto shared_buffer_size = arena_conf.shared_buffer_size(); + auto size = sizeof(ArenaSegmentState) + + sizeof(ArenaSegmentBlockDescriptor) * block_num + + message_size * block_num + shared_buffer_size; + auto shmid = + shmget(static_cast(key_id_), size, 0644 | IPC_CREAT | IPC_EXCL); + if (shmid == -1) { + if (errno == EINVAL) { + // TODO(all): need larger space, recreate + } else if (errno == EEXIST) { + // TODO(all): shm already exist, open only + return Open(message_size, block_num); + } else { + // create or open shm failed + return false; + } + } + message_capacity_ = message_size; + shm_address_ = shmat(shmid, base_address_, 0); + if (shm_address_ == reinterpret_cast(-1)) { + // shmat failed + return false; + } + + arenas_.resize(block_num, nullptr); + if (shared_buffer_size == 0) { + shared_buffer_arena_ = nullptr; + } else { + google::protobuf::ArenaOptions options; + options.start_block_size = shared_buffer_size; + options.max_block_size = shared_buffer_size; + options.initial_block = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + block_num * message_size); + options.initial_block_size = shared_buffer_size; + shared_buffer_arena_ = std::make_shared(options); + } + for (size_t i = 0; i < block_num; i++) { + arena_block_address_.push_back( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + i * message_size); + } + + state_ = reinterpret_cast(shm_address_); + state_->struct_.ref_count_.store(1); + state_->struct_.auto_extended_.store(false); + state_->struct_.message_size_.store(message_size); + state_->struct_.block_num_.store(block_num); + state_->struct_.message_seq_.store(0); + blocks_ = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState)); + for (uint64_t i = 0; i < block_num; ++i) { + blocks_[i].size_ = message_size; + // blocks_[i].writing_ref_count_.store(0); + // blocks_[i].reading_ref_count_.store(0); + blocks_[i].lock_num_.store(0); + } + return true; +} + +bool ArenaSegment::Open(uint64_t message_size, uint64_t block_num) { + auto arena_conf = + cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id_); + auto shared_buffer_size = arena_conf.shared_buffer_size(); + auto shmid = shmget(static_cast(key_id_), 0, 0644); + if (shmid == -1) { + // shm not exist + return false; + } + shm_address_ = shmat(shmid, base_address_, 0); + if (shm_address_ == reinterpret_cast(-1)) { + // shmat failed + return false; + } + message_capacity_ = message_size; + state_ = reinterpret_cast(shm_address_); + state_->struct_.ref_count_.fetch_add(1); + blocks_ = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState)); + + arenas_.resize(block_num, nullptr); + if (shared_buffer_size == 0) { + shared_buffer_arena_ = nullptr; + } else { + google::protobuf::ArenaOptions options; + options.start_block_size = shared_buffer_size; + options.max_block_size = shared_buffer_size; + options.initial_block = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + block_num * message_size); + options.initial_block_size = shared_buffer_size; + shared_buffer_arena_ = std::make_shared(options); + } + for (size_t i = 0; i < block_num; i++) { + arena_block_address_.push_back( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + i * message_size); + } + return true; +} + +void* ArenaSegment::GetShmAddress() { return shm_address_; } + +uint64_t ArenaSegment::GetNextWritableBlockIndex() { + const auto block_num = state_->struct_.block_num_.load(); + while (1) { + uint64_t next_idx = state_->struct_.message_seq_.fetch_add(1) % block_num; + if (AddBlockWriteLock(next_idx)) { + return next_idx; + } + } + return 0; +} + +bool ArenaSegment::AddBlockWriteLock(uint64_t block_index) { + // base::WriteLockGuard lock( + // blocks_[block_index].read_write_mutex_); + // if (blocks_[block_index].writing_ref_count_.load() > 0) { + // return false; + // } + // if (blocks_[block_index].reading_ref_count_.load() > 0) { + // return false; + // } + // blocks_[block_index].writing_ref_count_.fetch_add(1); + auto& block = blocks_[block_index]; + int32_t rw_lock_free = ArenaSegmentBlock::kRWLockFree; + if (!block.lock_num_.compare_exchange_weak( + rw_lock_free, ArenaSegmentBlock::kWriteExclusive, + std::memory_order_acq_rel, std::memory_order_relaxed)) { + ADEBUG << "lock num: " << block.lock_num_.load(); + return false; + } + return true; +} + +void ArenaSegment::RemoveBlockWriteLock(uint64_t block_index) { + blocks_[block_index].lock_num_.fetch_add(1); +} + +bool ArenaSegment::AddBlockReadLock(uint64_t block_index) { + // when multiple readers are reading an arena channel + // at the same time, using write locks can cause one + // or more readers to hang at the lock, whereas + // read locks do not have this problem + // base::ReadLockGuard lock( + // blocks_[block_index].read_write_mutex_); + // if (blocks_[block_index].writing_ref_count_.load() > 0) { + // return false; + // } + // blocks_[block_index].reading_ref_count_.fetch_add(1); + auto& block = blocks_[block_index]; + int32_t lock_num = block.lock_num_.load(); + if (lock_num < ArenaSegmentBlock::kRWLockFree) { + AINFO << "block is being written."; + return false; + } + + int32_t try_times = 0; + while (!block.lock_num_.compare_exchange_weak(lock_num, lock_num + 1, + std::memory_order_acq_rel, + std::memory_order_relaxed)) { + ++try_times; + if (try_times == ArenaSegmentBlock::kMaxTryLockTimes) { + AINFO << "fail to add read lock num, curr num: " << lock_num; + return false; + } + + lock_num = block.lock_num_.load(); + if (lock_num < ArenaSegmentBlock::kRWLockFree) { + AINFO << "block is being written."; + return false; + } + } + return true; +} + +void ArenaSegment::RemoveBlockReadLock(uint64_t block_index) { + blocks_[block_index].lock_num_.fetch_sub(1); +} + +bool ArenaSegment::AcquireBlockToWrite(uint64_t size, + ArenaSegmentBlockInfo* block_info) { + if (!block_info) { + return false; + } + if (!state_ || !blocks_) { + return false; + } + + // TODO(all): support dynamic block size + + uint64_t block_num = state_->struct_.block_num_.load(); + uint64_t block_size = state_->struct_.message_size_.load(); + uint64_t block_index = GetNextWritableBlockIndex(); + block_info->block_index_ = block_index; + block_info->block_ = &blocks_[block_index]; + block_info->block_buffer_address_ = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + block_index * block_size); + return true; +} + +void ArenaSegment::ReleaseWrittenBlock( + const ArenaSegmentBlockInfo& block_info) { + if (!state_ || !blocks_) { + return; + } + if (block_info.block_index_ >= state_->struct_.block_num_.load()) { + return; + } + RemoveBlockWriteLock(block_info.block_index_); +} + +bool ArenaSegment::AcquireBlockToRead(ArenaSegmentBlockInfo* block_info) { + if (!block_info) { + return false; + } + if (!state_ || !blocks_) { + return false; + } + + if (block_info->block_index_ >= state_->struct_.block_num_.load()) { + return false; + } + + // TODO(all): support dynamic block size + + if (!AddBlockReadLock(block_info->block_index_)) { + return false; + } + uint64_t block_num = state_->struct_.block_num_.load(); + uint64_t block_size = state_->struct_.message_size_.load(); + + block_info->block_ = &blocks_[block_info->block_index_]; + block_info->block_buffer_address_ = reinterpret_cast( + reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + + block_num * sizeof(ArenaSegmentBlock) + + block_info->block_index_ * block_size); + return true; +} + +void ArenaSegment::ReleaseReadBlock(const ArenaSegmentBlockInfo& block_info) { + if (!state_ || !blocks_) { + return; + } + if (block_info.block_index_ >= state_->struct_.block_num_.load()) { + return; + } + RemoveBlockReadLock(block_info.block_index_); +} + +ProtobufArenaManager::ProtobufArenaManager() { + address_allocator_ = std::make_shared(); +} + +ProtobufArenaManager::~ProtobufArenaManager() { Destroy(); } + +uint64_t ProtobufArenaManager::GetBaseAddress( + const message::ArenaMessageWrapper* wrapper) { + return 0; +} + +std::shared_ptr ProtobufArenaManager::GetSegment( + uint64_t channel_id) { + std::lock_guard lock(segments_mutex_); + if (segments_.find(channel_id) == segments_.end()) { + return nullptr; + } + return segments_[channel_id]; +} + +void* ProtobufArenaManager::SetMessage(message::ArenaMessageWrapper* wrapper, + const void* message) { + auto input_msg = reinterpret_cast(message); + auto channel_id = GetMessageChannelId(wrapper); + auto segment = GetSegment(channel_id); + auto arena_ptr = input_msg->GetArena(); + google::protobuf::ArenaOptions options; + + if (!segment) { + return nullptr; + } + + void* msg_output = nullptr; + if (arena_ptr == nullptr) { + auto arena_conf = + cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); + google::protobuf::ArenaOptions options; + options.start_block_size = arena_conf.max_msg_size(); + options.max_block_size = arena_conf.max_msg_size(); + + if (!segment) { + return nullptr; + } + + ResetMessageRelatedBlocks(wrapper); + + ArenaSegmentBlockInfo wb; + // TODO(all): AcquireBlockToWrite for dynamic adjust block + // auto size = input_msg->ByteSizeLong(); + uint64_t size = 0; + if (!segment->AcquireBlockToWrite(size, &wb)) { + return nullptr; + } + this->AddMessageRelatedBlock(wrapper, wb.block_index_); + options.initial_block = + reinterpret_cast(segment->arena_block_address_[wb.block_index_]); + options.initial_block_size = segment->message_capacity_; + if (segment->arenas_[wb.block_index_] != nullptr) { + segment->arenas_[wb.block_index_] = nullptr; + } + segment->arenas_[wb.block_index_] = + std::make_shared(options); + auto msg = input_msg->New(segment->arenas_[wb.block_index_].get()); + msg->CopyFrom(*input_msg); + SetMessageAddressOffset( + wrapper, reinterpret_cast(msg) - + reinterpret_cast(segment->GetShmAddress())); + msg_output = reinterpret_cast(msg); + segment->ReleaseWrittenBlock(wb); + } else { + ArenaSegmentBlockInfo wb; + int block_index = -1; + for (size_t i = 0; i < segment->message_capacity_; i++) { + if (segment->arenas_[i].get() == arena_ptr) { + block_index = i; + break; + } + } + if (block_index == -1) { + return nullptr; + } + wb.block_index_ = block_index; + ResetMessageRelatedBlocks(wrapper); + this->AddMessageRelatedBlock(wrapper, block_index); + SetMessageAddressOffset( + wrapper, reinterpret_cast(input_msg) - + reinterpret_cast(segment->GetShmAddress())); + msg_output = reinterpret_cast( + const_cast(input_msg)); + segment->ReleaseWrittenBlock(wb); + } + + return msg_output; +} + +void* ProtobufArenaManager::GetMessage(message::ArenaMessageWrapper* wrapper) { + auto segment = GetSegment(GetMessageChannelId(wrapper)); + if (!segment) { + return nullptr; + } + + auto address = reinterpret_cast(segment->GetShmAddress()) + + GetMessageAddressOffset(wrapper); + + return reinterpret_cast(address); +} + +bool ProtobufArenaManager::Enable() { + if (init_) { + return true; + } + + // do something + + init_ = true; + return true; +} + +bool ProtobufArenaManager::EnableSegment(uint64_t channel_id) { + if (segments_.find(channel_id) != segments_.end()) { + if (arena_buffer_callbacks_.find(channel_id) != + arena_buffer_callbacks_.end()) { + arena_buffer_callbacks_[channel_id](); + } + return true; + } + + // uint64_t asociated_channel_id = channel_id + 1; + // auto segment = SegmentFactory::CreateSegment(asociated_channel_id); + // segment->InitOnly(10 * 1024); + auto cyber_config = apollo::cyber::common::GlobalData::Instance()->Config(); + if (!cyber_config.has_transport_conf()) { + return false; + } + if (!cyber_config.transport_conf().has_shm_conf()) { + return false; + } + if (!cyber_config.transport_conf().shm_conf().has_arena_shm_conf()) { + return false; + } + if (!cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( + channel_id)) { + return false; + } + auto arena_conf = + cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); + auto segment_shm_address = address_allocator_->Allocate(channel_id); + auto segment = std::make_shared( + channel_id, arena_conf.max_msg_size(), arena_conf.max_pool_size(), + reinterpret_cast(segment_shm_address)); + segments_[channel_id] = segment; + if (arena_buffer_callbacks_.find(channel_id) != + arena_buffer_callbacks_.end()) { + arena_buffer_callbacks_[channel_id](); + } + return true; +} + +bool ProtobufArenaManager::Destroy() { + if (!init_) { + return true; + } + + for (auto& segment : segments_) { + address_allocator_->Deallocate(segment.first); + } + for (auto& buffer : non_arena_buffers_) { + delete buffer.second; + } + segments_.clear(); + + init_ = false; + return true; +} + +void ProtobufArenaManager::SetMessageChannelId( + message::ArenaMessageWrapper* wrapper, uint64_t channel_id) { + wrapper->GetExtended()->meta_.channel_id_ = channel_id; +} + +uint64_t ProtobufArenaManager::GetMessageChannelId( + message::ArenaMessageWrapper* wrapper) { + return wrapper->GetExtended()->meta_.channel_id_; +} + +void ProtobufArenaManager::SetMessageAddressOffset( + message::ArenaMessageWrapper* wrapper, uint64_t address_offset) { + wrapper->GetExtended()->meta_.address_offset_ = + address_offset; +} + +uint64_t ProtobufArenaManager::GetMessageAddressOffset( + message::ArenaMessageWrapper* wrapper) { + return wrapper->GetExtended()->meta_.address_offset_; +} + +std::vector ProtobufArenaManager::GetMessageRelatedBlocks( + message::ArenaMessageWrapper* wrapper) { + std::vector related_blocks; + auto extended = wrapper->GetExtended(); + for (uint64_t i = 0; i < extended->meta_.related_blocks_size_; ++i) { + related_blocks.push_back(extended->meta_.related_blocks_[i]); + } + return related_blocks; +} + +void ProtobufArenaManager::ResetMessageRelatedBlocks( + message::ArenaMessageWrapper* wrapper) { + auto extended = wrapper->GetExtended(); + extended->meta_.related_blocks_size_ = 0; + // memset(extended->meta_.related_blocks_, 0, + // sizeof(extended->meta_.related_blocks_)); +} + +void ProtobufArenaManager::AddMessageRelatedBlock( + message::ArenaMessageWrapper* wrapper, uint64_t block_index) { + auto extended = wrapper->GetExtended(); + if (extended->meta_.related_blocks_size_ >= + sizeof(extended->meta_.related_blocks_) / sizeof(uint64_t)) { + return; + } + extended->meta_.related_blocks_[extended->meta_.related_blocks_size_++] = + block_index; +} + +ProtobufArenaManager::ArenaAllocCallback ProtobufArenaManager::arena_alloc_cb_ = + nullptr; + +void* ProtobufArenaManager::ArenaAlloc(uint64_t size) { + return arena_alloc_cb_ ? arena_alloc_cb_(size) : nullptr; +} + +void ProtobufArenaManager::ArenaDealloc(void* addr, uint64_t size) {} + +} // namespace transport +} // namespace cyber +} // namespace apollo diff --git a/cyber/transport/shm/protobuf_arena_manager.h b/cyber/transport/shm/protobuf_arena_manager.h new file mode 100644 index 0000000..d250ccc --- /dev/null +++ b/cyber/transport/shm/protobuf_arena_manager.h @@ -0,0 +1,319 @@ +/****************************************************************************** + * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_ +#define CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_ + +#include +#include +#include +#include + +#include + +#include "cyber/base/arena_queue.h" +#include "cyber/base/pthread_rw_lock.h" +#include "cyber/common/global_data.h" +#include "cyber/common/macros.h" +#include "cyber/message/arena_manager_base.h" +#include "cyber/message/arena_message_wrapper.h" +#include "cyber/transport/shm/arena_address_allocator.h" +#include "cyber/transport/shm/segment.h" + +namespace apollo { +namespace cyber { +namespace transport { + +union ArenaSegmentState { + struct { + std::atomic ref_count_; + std::atomic auto_extended_; + std::atomic message_size_; + std::atomic block_num_; + std::atomic message_seq_; + std::mutex mutex_; + } struct_; + uint8_t bytes_[128]; +}; + +union ArenaSegmentBlockDescriptor { + struct { + uint64_t size_; + std::atomic writing_ref_count_; + std::atomic reading_ref_count_; + base::PthreadRWLock read_write_mutex_; + } struct_; + uint8_t bytes_[128]; +}; + +struct ArenaSegmentBlock { + uint64_t size_; + // std::atomic writing_ref_count_; + // std::atomic reading_ref_count_; + // base::PthreadRWLock read_write_mutex_; + static const int32_t kRWLockFree; + static const int32_t kWriteExclusive; + static const int32_t kMaxTryLockTimes; + std::atomic lock_num_ = {0}; +}; + +struct ArenaSegmentBlockInfo { + uint64_t block_index_; + ArenaSegmentBlock* block_; + void* block_buffer_address_; +}; + +class ArenaSegment { + public: + ArenaSegment(); + explicit ArenaSegment(uint64_t channel_id); + ArenaSegment(uint64_t channel_id, void* base_address); + ArenaSegment(uint64_t channel_id, uint64_t message_size, uint64_t block_num, + void* base_address); + ~ArenaSegment(); + + bool Init(uint64_t message_size, uint64_t block_num); + // bool Create(uint64_t message_size, uint64_t block_num); + bool Open(uint64_t message_size, uint64_t block_num); + bool OpenOrCreate(uint64_t message_size, uint64_t block_num); + + void* GetShmAddress(); + + uint64_t GetNextWritableBlockIndex(); + bool AddBlockWriteLock(uint64_t block_index); + void RemoveBlockWriteLock(uint64_t block_index); + bool AddBlockReadLock(uint64_t block_index); + void RemoveBlockReadLock(uint64_t block_index); + + bool AcquireBlockToWrite(uint64_t size, ArenaSegmentBlockInfo* block_info); + void ReleaseWrittenBlock(const ArenaSegmentBlockInfo& block_info); + + bool AcquireBlockToRead(ArenaSegmentBlockInfo* block_info); + void ReleaseReadBlock(const ArenaSegmentBlockInfo& block_info); + + // uint64_t GetCapicity(); + + public: + ArenaSegmentState* state_; + ArenaSegmentBlock* blocks_; + std::vector> arenas_; + std::vector arena_block_address_; + uint64_t channel_id_; + uint64_t key_id_; + void* base_address_; + void* shm_address_; + std::shared_ptr shared_buffer_arena_; + void* arena_buffer_address_ = nullptr; + + uint64_t message_capacity_; +}; + +union ExtendedStruct { + struct { + uint64_t channel_id_; + uint64_t address_offset_; + uint64_t related_blocks_[4]; + uint64_t related_blocks_size_ = 0; + } meta_; + uint8_t bytes_[256]; +}; + +union ProtobufArenaManagerMeta { + struct { + uint64_t version_; + uint64_t base_address_; + uint64_t segment_size_; + uint64_t block_size_; + uint64_t block_num_; + uint64_t message_size_; + uint64_t message_num_; + uint64_t message_seq_; + uint64_t extended_struct_size_; + uint64_t extended_struct_num_; + uint64_t extended_struct_seq_; + } struct_; + uint8_t bytes_[256]; +}; + +class ProtobufArenaManager : public message::ArenaManagerBase { + public: + using ArenaAllocCallback = std::function; + + ~ProtobufArenaManager(); + + uint64_t GetBaseAddress(const message::ArenaMessageWrapper* wrapper) override; + + bool Enable(); + bool EnableSegment(uint64_t channel_id); + bool Destroy(); + // bool Shutdown(); + + void SetMessageChannelId(message::ArenaMessageWrapper* wrapper, + uint64_t channel_id); + uint64_t GetMessageChannelId(message::ArenaMessageWrapper* wrapper); + void SetMessageAddressOffset(message::ArenaMessageWrapper* wrapper, + uint64_t offset); + uint64_t GetMessageAddressOffset(message::ArenaMessageWrapper* wrapper); + std::vector GetMessageRelatedBlocks( + message::ArenaMessageWrapper* wrapper); + void ResetMessageRelatedBlocks(message::ArenaMessageWrapper* wrapper); + void AddMessageRelatedBlock(message::ArenaMessageWrapper* wrapper, + uint64_t block_index); + + std::shared_ptr GetSegment(uint64_t channel_id); + + void* SetMessage(message::ArenaMessageWrapper* wrapper, + const void* message) override; + void* GetMessage(message::ArenaMessageWrapper* wrapper) override; + + void* GetAvailableBuffer(uint64_t channel_id) { + auto segment = this->GetSegment(channel_id); + if (!segment) { + if (non_arena_buffers_.find(channel_id) == non_arena_buffers_.end()) { + return nullptr; + } + return non_arena_buffers_[channel_id]; + } + if (segment->arena_buffer_address_ != nullptr) { + return segment->arena_buffer_address_; + } + return non_arena_buffers_[channel_id]; + } + + template + bool RegisterQueue(uint64_t channel_id, uint64_t size) { + if (non_arena_buffers_.find(channel_id) == non_arena_buffers_.end() || + arena_buffer_callbacks_.find(channel_id) == + arena_buffer_callbacks_.end()) { + auto non_arena_buffer_ptr = new apollo::cyber::base::ArenaQueue(); + non_arena_buffer_ptr->Init(size); + non_arena_buffers_[channel_id] = non_arena_buffer_ptr; + arena_buffer_callbacks_[channel_id] = [this, channel_id, size]() { + auto segment = this->GetSegment(channel_id); + if (!segment) { + ADEBUG << "channel id '" << channel_id << "' not enable"; + ADEBUG << "fallback to use nomarl queue"; + return; + } + if (segment->shared_buffer_arena_ == nullptr) { + ADEBUG << "Not enable arena shared buffer in channel id '" + << channel_id << "'"; + ADEBUG << "fallback to use nomarl queue"; + return; + } + if (segment->arena_buffer_address_ == nullptr) { + auto ptr = google::protobuf::Arena::Create>( + segment->shared_buffer_arena_.get()); + ptr->Init(size, segment->shared_buffer_arena_.get()); + segment->arena_buffer_address_ = reinterpret_cast(ptr); + } + }; + } + // try enable arena buffer + auto segment = GetSegment(channel_id); + if (segment) { + arena_buffer_callbacks_[channel_id](); + } + return true; + } + + template ::value, + M>::type* = nullptr> + void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr& ret_msg) { + auto arena_conf = + cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); + google::protobuf::ArenaOptions options; + options.start_block_size = arena_conf.max_msg_size(); + options.max_block_size = arena_conf.max_msg_size(); + + auto segment = GetSegment(channel_id); + if (!segment) { + return; + } + + ArenaSegmentBlockInfo wb; + // TODO(All): size should be send to + // AcquireBlockToWrite for dynamic adjust block size + // auto size = input_msg->ByteSizeLong(); + uint64_t size = 0; + if (!segment->AcquireBlockToWrite(size, &wb)) { + return; + } + options.initial_block = + reinterpret_cast(segment->arena_block_address_[wb.block_index_]); + options.initial_block_size = segment->message_capacity_; + if (segment->arenas_[wb.block_index_] != nullptr) { + segment->arenas_[wb.block_index_] = nullptr; + } + segment->arenas_[wb.block_index_] = + std::make_shared(options); + + // deconstructor do nothing to avoid proto + // instance deconstructed before arena allocator + ret_msg = std::shared_ptr( + google::protobuf::Arena::CreateMessage( + segment->arenas_[wb.block_index_].get()), + [segment, wb](M* ptr) { + int32_t lock_num = segment->blocks_[wb.block_index_].lock_num_.load(); + if (lock_num < ArenaSegmentBlock::kRWLockFree) { + segment->ReleaseWrittenBlock(wb); + } + }); + return; + } + + template ::value, + M>::type* = nullptr> + void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr& ret_msg) { + return; + } + + private: + bool init_; + std::unordered_map> segments_; + std::unordered_map non_arena_buffers_; + std::unordered_map> arena_buffer_callbacks_; + std::mutex segments_mutex_; + + std::shared_ptr address_allocator_; + + static ArenaAllocCallback arena_alloc_cb_; + static void* ArenaAlloc(uint64_t size); + static void ArenaDealloc(void* addr, uint64_t size); + + std::mutex arena_alloc_cb_mutex_; + + std::unordered_map managed_wrappers_; + + DECLARE_SINGLETON(ProtobufArenaManager) +}; + +// template +// std::shared_ptr ProtobufArenaManager::CreateMessage( +// message::ArenaMessageWrapper* wrapper, const MessageT& message) {} + +// template +// std::shared_ptr ProtobufArenaManager::LoadMessage( +// message::ArenaMessageWrapper* wrapper) {} + +} // namespace transport +} // namespace cyber +} // namespace apollo + +#endif diff --git a/cyber/transport/shm/readable_info.cc b/cyber/transport/shm/readable_info.cc index 605da79..5f7c332 100644 --- a/cyber/transport/shm/readable_info.cc +++ b/cyber/transport/shm/readable_info.cc @@ -24,13 +24,21 @@ namespace apollo { namespace cyber { namespace transport { -const size_t ReadableInfo::kSize = sizeof(uint64_t) * 2 + sizeof(uint32_t); - -ReadableInfo::ReadableInfo() : host_id_(0), block_index_(0), channel_id_(0) {} - -ReadableInfo::ReadableInfo(uint64_t host_id, uint32_t block_index, - uint64_t channel_id) - : host_id_(host_id), block_index_(block_index), channel_id_(channel_id) {} +const size_t ReadableInfo::kSize = sizeof(uint64_t) * 2 + \ + sizeof(int32_t) + sizeof(int32_t); + +ReadableInfo::ReadableInfo() + : host_id_(0), + block_index_(0), + arena_block_index_(-1), + channel_id_(0) {} + +ReadableInfo::ReadableInfo(uint64_t host_id, int32_t block_index, + uint64_t channel_id, int32_t arena_block_index) + : host_id_(host_id), + block_index_(block_index), + arena_block_index_(arena_block_index), + channel_id_(channel_id) {} ReadableInfo::~ReadableInfo() {} @@ -39,6 +47,7 @@ ReadableInfo& ReadableInfo::operator=(const ReadableInfo& other) { this->host_id_ = other.host_id_; this->block_index_ = other.block_index_; this->channel_id_ = other.channel_id_; + this->arena_block_index_ = other.arena_block_index_; } return *this; } @@ -48,10 +57,12 @@ bool ReadableInfo::SerializeTo(std::string* dst) const { dst->assign(reinterpret_cast(const_cast(&host_id_)), sizeof(host_id_)); - dst->append(reinterpret_cast(const_cast(&block_index_)), + dst->append(reinterpret_cast(const_cast(&block_index_)), sizeof(block_index_)); dst->append(reinterpret_cast(const_cast(&channel_id_)), sizeof(channel_id_)); + dst->append(reinterpret_cast(const_cast( + &arena_block_index_)), sizeof(arena_block_index_)); return true; } @@ -72,7 +83,9 @@ bool ReadableInfo::DeserializeFrom(const char* src, std::size_t len) { memcpy(reinterpret_cast(&block_index_), ptr, sizeof(block_index_)); ptr += sizeof(block_index_); memcpy(reinterpret_cast(&channel_id_), ptr, sizeof(channel_id_)); - + ptr += sizeof(channel_id_); + memcpy(reinterpret_cast(&arena_block_index_), + ptr, sizeof(arena_block_index_)); return true; } diff --git a/cyber/transport/shm/readable_info.h b/cyber/transport/shm/readable_info.h index ffeb5c8..06d4e71 100644 --- a/cyber/transport/shm/readable_info.h +++ b/cyber/transport/shm/readable_info.h @@ -32,7 +32,8 @@ using ReadableInfoPtr = std::shared_ptr; class ReadableInfo { public: ReadableInfo(); - ReadableInfo(uint64_t host_id, uint32_t block_index, uint64_t channel_id); + ReadableInfo(uint64_t host_id, int32_t block_index, + uint64_t channel_id, int32_t arena_block_index = -1); virtual ~ReadableInfo(); ReadableInfo& operator=(const ReadableInfo& other); @@ -44,8 +45,12 @@ class ReadableInfo { uint64_t host_id() const { return host_id_; } void set_host_id(uint64_t host_id) { host_id_ = host_id; } - uint32_t block_index() const { return block_index_; } - void set_block_index(uint32_t block_index) { block_index_ = block_index; } + int32_t block_index() const { return block_index_; } + void set_block_index(int32_t block_index) { block_index_ = block_index; } + + int32_t arena_block_index() const { return arena_block_index_; } + void set_arena_block_index( + int32_t arena_block_index) { arena_block_index_ = arena_block_index; } uint64_t channel_id() const { return channel_id_; } void set_channel_id(uint64_t channel_id) { channel_id_ = channel_id; } @@ -54,7 +59,8 @@ class ReadableInfo { private: uint64_t host_id_; - uint32_t block_index_; + int32_t block_index_; + int32_t arena_block_index_; uint64_t channel_id_; }; diff --git a/cyber/transport/shm/segment.cc b/cyber/transport/shm/segment.cc index 1890e1b..a250f6c 100644 --- a/cyber/transport/shm/segment.cc +++ b/cyber/transport/shm/segment.cc @@ -30,9 +30,12 @@ Segment::Segment(uint64_t channel_id) channel_id_(channel_id), state_(nullptr), blocks_(nullptr), + arena_blocks_(nullptr), managed_shm_(nullptr), block_buf_lock_(), - block_buf_addrs_() {} + arena_block_buf_lock_(), + block_buf_addrs_(), + arena_block_buf_addrs_() {} bool Segment::AcquireBlockToWrite(std::size_t msg_size, WritableBlock* writable_block) { @@ -66,6 +69,25 @@ bool Segment::AcquireBlockToWrite(std::size_t msg_size, return true; } +bool Segment::AcquireArenaBlockToWrite(std::size_t msg_size, + WritableBlock* writable_block) { + RETURN_VAL_IF_NULL(writable_block, false); + if (!init_ && !OpenOrCreate()) { + AERROR << "create shm failed, can't write now."; + return false; + } + + if (state_->need_remap()) { + Remap(); + } + + uint32_t index = GetNextArenaWritableBlockIndex(); + writable_block->index = index; + writable_block->block = &arena_blocks_[index]; + writable_block->buf = arena_block_buf_addrs_[index]; + return true; +} + void Segment::ReleaseWrittenBlock(const WritableBlock& writable_block) { auto index = writable_block.index; if (index >= conf_.block_num()) { @@ -74,6 +96,14 @@ void Segment::ReleaseWrittenBlock(const WritableBlock& writable_block) { blocks_[index].ReleaseWriteLock(); } +void Segment::ReleaseArenaWrittenBlock(const WritableBlock& writable_block) { + auto index = writable_block.index; + if (index >= ShmConf::ARENA_BLOCK_NUM) { + return; + } + arena_blocks_[index].ReleaseWriteLock(); +} + bool Segment::AcquireBlockToRead(ReadableBlock* readable_block) { RETURN_VAL_IF_NULL(readable_block, false); if (!init_ && !OpenOnly()) { @@ -105,6 +135,45 @@ bool Segment::AcquireBlockToRead(ReadableBlock* readable_block) { return true; } +bool Segment::AcquireArenaBlockToRead(ReadableBlock* readable_block) { + RETURN_VAL_IF_NULL(readable_block, false); + if (!init_ && !OpenOnly()) { + AERROR << "failed to open shared memory, can't read now."; + return false; + } + + auto index = readable_block->index; + if (index >= ShmConf::ARENA_BLOCK_NUM) { + AERROR << "invalid arena block_index[" << index << "]."; + return false; + } + + bool result = true; + if (state_->need_remap()) { + result = Remap(); + } + + if (!result) { + AERROR << "segment update failed."; + return false; + } + + if (!arena_blocks_[index].TryLockForRead()) { + return false; + } + readable_block->block = arena_blocks_ + index; + readable_block->buf = arena_block_buf_addrs_[index]; + return true; +} + +void Segment::ReleaseArenaReadBlock(const ReadableBlock& readable_block) { + auto index = readable_block.index; + if (index >= ShmConf::ARENA_BLOCK_NUM) { + return; + } + arena_blocks_[index].ReleaseReadLock(); +} + void Segment::ReleaseReadBlock(const ReadableBlock& readable_block) { auto index = readable_block.index; if (index >= conf_.block_num()) { @@ -113,6 +182,79 @@ void Segment::ReleaseReadBlock(const ReadableBlock& readable_block) { blocks_[index].ReleaseReadLock(); } +bool Segment::InitOnly(uint64_t message_size) { + if (init_) { + return true; + } + conf_.Update(message_size); + if (!OpenOrCreate()) { + return false; + } + return true; +} + +void* Segment::GetManagedShm() { return managed_shm_; } + +bool Segment::LockBlockForWriteByIndex(uint64_t block_index) { + if (block_index >= conf_.block_num()) { + return false; + } + return blocks_[block_index].TryLockForWrite(); +} + +bool Segment::ReleaseBlockForWriteByIndex(uint64_t block_index) { + if (block_index >= conf_.block_num()) { + return false; + } + blocks_[block_index].ReleaseWriteLock(); + return true; +} + +bool Segment::LockBlockForReadByIndex(uint64_t block_index) { + if (block_index >= conf_.block_num()) { + return false; + } + return blocks_[block_index].TryLockForRead(); +} + +bool Segment::ReleaseBlockForReadByIndex(uint64_t block_index) { + if (block_index >= conf_.block_num()) { + return false; + } + blocks_[block_index].ReleaseReadLock(); + return true; +} + +bool Segment::LockArenaBlockForWriteByIndex(uint64_t block_index) { + if (block_index >= ShmConf::ARENA_BLOCK_NUM) { + return false; + } + return arena_blocks_[block_index].TryLockForWrite(); +} + +bool Segment::ReleaseArenaBlockForWriteByIndex(uint64_t block_index) { + if (block_index >= ShmConf::ARENA_BLOCK_NUM) { + return false; + } + arena_blocks_[block_index].ReleaseWriteLock(); + return true; +} + +bool Segment::LockArenaBlockForReadByIndex(uint64_t block_index) { + if (block_index >= ShmConf::ARENA_BLOCK_NUM) { + return false; + } + return arena_blocks_[block_index].TryLockForRead(); +} + +bool Segment::ReleaseArenaBlockForReadByIndex(uint64_t block_index) { + if (block_index >= ShmConf::ARENA_BLOCK_NUM) { + return false; + } + arena_blocks_[block_index].ReleaseReadLock(); + return true; +} + bool Segment::Destroy() { if (!init_) { return true; @@ -161,6 +303,17 @@ uint32_t Segment::GetNextWritableBlockIndex() { return 0; } +uint32_t Segment::GetNextArenaWritableBlockIndex() { + const auto block_num = ShmConf::ARENA_BLOCK_NUM; + while (1) { + uint32_t try_idx = state_->FetchAddArenaSeq(1) % block_num; + if (arena_blocks_[try_idx].TryLockForWrite()) { + return try_idx; + } + } + return 0; +} + } // namespace transport } // namespace cyber } // namespace apollo diff --git a/cyber/transport/shm/segment.h b/cyber/transport/shm/segment.h index 1adaea6..1e4416b 100644 --- a/cyber/transport/shm/segment.h +++ b/cyber/transport/shm/segment.h @@ -48,9 +48,28 @@ class Segment { bool AcquireBlockToWrite(std::size_t msg_size, WritableBlock* writable_block); void ReleaseWrittenBlock(const WritableBlock& writable_block); + bool AcquireArenaBlockToWrite( + std::size_t msg_size, WritableBlock* writable_block); + void ReleaseArenaWrittenBlock(const WritableBlock& writable_block); + bool AcquireBlockToRead(ReadableBlock* readable_block); void ReleaseReadBlock(const ReadableBlock& readable_block); + bool AcquireArenaBlockToRead(ReadableBlock* readable_block); + void ReleaseArenaReadBlock(const ReadableBlock& readable_block); + + bool InitOnly(uint64_t message_size); + void* GetManagedShm(); + bool LockBlockForWriteByIndex(uint64_t block_index); + bool ReleaseBlockForWriteByIndex(uint64_t block_index); + bool LockBlockForReadByIndex(uint64_t block_index); + bool ReleaseBlockForReadByIndex(uint64_t block_index); + + bool LockArenaBlockForWriteByIndex(uint64_t block_index); + bool ReleaseArenaBlockForWriteByIndex(uint64_t block_index); + bool LockArenaBlockForReadByIndex(uint64_t block_index); + bool ReleaseArenaBlockForReadByIndex(uint64_t block_index); + protected: virtual bool Destroy(); virtual void Reset() = 0; @@ -64,14 +83,18 @@ class Segment { State* state_; Block* blocks_; + Block* arena_blocks_; void* managed_shm_; std::mutex block_buf_lock_; + std::mutex arena_block_buf_lock_; std::unordered_map block_buf_addrs_; + std::unordered_map arena_block_buf_addrs_; private: bool Remap(); bool Recreate(const uint64_t& msg_size); uint32_t GetNextWritableBlockIndex(); + uint32_t GetNextArenaWritableBlockIndex(); }; } // namespace transport diff --git a/cyber/transport/shm/shm_conf.cc b/cyber/transport/shm/shm_conf.cc index e7ffb22..44c780e 100644 --- a/cyber/transport/shm/shm_conf.cc +++ b/cyber/transport/shm/shm_conf.cc @@ -31,8 +31,9 @@ void ShmConf::Update(const uint64_t& real_msg_size) { ceiling_msg_size_ = GetCeilingMessageSize(real_msg_size); block_buf_size_ = GetBlockBufSize(ceiling_msg_size_); block_num_ = GetBlockNum(ceiling_msg_size_); - managed_shm_size_ = - EXTRA_SIZE + STATE_SIZE + (BLOCK_SIZE + block_buf_size_) * block_num_; + managed_shm_size_ = EXTRA_SIZE + STATE_SIZE + \ + (BLOCK_SIZE + block_buf_size_) * block_num_ + \ + (BLOCK_SIZE + ARENA_MESSAGE_SIZE) * ARENA_BLOCK_NUM; } const uint64_t ShmConf::EXTRA_SIZE = 1024 * 4; @@ -40,6 +41,9 @@ const uint64_t ShmConf::STATE_SIZE = 1024; const uint64_t ShmConf::BLOCK_SIZE = 1024; const uint64_t ShmConf::MESSAGE_INFO_SIZE = 1024; +const uint32_t ShmConf::ARENA_BLOCK_NUM = 512; +const uint64_t ShmConf::ARENA_MESSAGE_SIZE = 1024; + const uint32_t ShmConf::BLOCK_NUM_16K = 512; const uint64_t ShmConf::MESSAGE_SIZE_16K = 1024 * 16; diff --git a/cyber/transport/shm/shm_conf.h b/cyber/transport/shm/shm_conf.h index 84f9d16..d230ae1 100644 --- a/cyber/transport/shm/shm_conf.h +++ b/cyber/transport/shm/shm_conf.h @@ -37,6 +37,10 @@ class ShmConf { const uint32_t& block_num() { return block_num_; } const uint64_t& managed_shm_size() { return managed_shm_size_; } + // For arena msg + static const uint32_t ARENA_BLOCK_NUM; + static const uint64_t ARENA_MESSAGE_SIZE; + private: uint64_t GetCeilingMessageSize(const uint64_t& real_msg_size); uint64_t GetBlockBufSize(const uint64_t& ceiling_msg_size); diff --git a/cyber/transport/shm/state.h b/cyber/transport/shm/state.h index 62da2a9..98cd5d2 100644 --- a/cyber/transport/shm/state.h +++ b/cyber/transport/shm/state.h @@ -46,6 +46,11 @@ class State { uint32_t FetchAddSeq(uint32_t diff) { return seq_.fetch_add(diff); } uint32_t seq() { return seq_.load(); } + uint32_t FetchAddArenaSeq(uint32_t diff) { + return arena_seq_.fetch_add(diff); + } + uint32_t arena_seq() { return arena_seq_.load(); } + void set_need_remap(bool need) { need_remap_.store(need); } bool need_remap() { return need_remap_; } @@ -55,6 +60,7 @@ class State { private: std::atomic need_remap_ = {false}; std::atomic seq_ = {0}; + std::atomic arena_seq_ = {0}; std::atomic reference_count_ = {0}; std::atomic ceiling_msg_size_; }; diff --git a/cyber/transport/shm/xsi_segment.cc b/cyber/transport/shm/xsi_segment.cc index dce45e7..a613222 100644 --- a/cyber/transport/shm/xsi_segment.cc +++ b/cyber/transport/shm/xsi_segment.cc @@ -100,27 +100,60 @@ bool XsiSegment::OpenOrCreate() { return false; } + // create field arena_blocks_ + arena_blocks_ = new (static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block)) Block[ + ShmConf::ARENA_BLOCK_NUM]; + if (arena_blocks_ == nullptr) { + AERROR << "create arena blocks failed."; + state_->~State(); + state_ = nullptr; + shmdt(managed_shm_); + managed_shm_ = nullptr; + shmctl(shmid, IPC_RMID, 0); + return false; + } + // create block buf uint32_t i = 0; for (; i < conf_.block_num(); ++i) { - uint8_t* addr = - new (static_cast(managed_shm_) + sizeof(State) + - conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()) - uint8_t[conf_.block_buf_size()]; - + uint8_t* addr = \ + new (static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + \ + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ + i * conf_.block_buf_size()) uint8_t[conf_.block_buf_size()]; std::lock_guard _g(block_buf_lock_); block_buf_addrs_[i] = addr; } - if (i != conf_.block_num()) { - AERROR << "create block buf failed."; + // create arena block buf + uint32_t ai = 0; + for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { + uint8_t* addr = \ + new(static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + \ + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ + conf_.block_num() * conf_.block_buf_size() + \ + ai * ShmConf::ARENA_MESSAGE_SIZE) uint8_t[ + ShmConf::ARENA_MESSAGE_SIZE]; + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_[ai] = addr; + } + + if (ai != ShmConf::ARENA_BLOCK_NUM || i != conf_.block_num()) { + AERROR << "create arena block or block buf failed."; state_->~State(); state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard _g(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } shmdt(managed_shm_); managed_shm_ = nullptr; shmctl(shmid, IPC_RMID, 0); @@ -174,12 +207,26 @@ bool XsiSegment::OpenOnly() { return false; } + // get field arena_blocks_ + arena_blocks_ = reinterpret_cast( + static_cast(managed_shm_) + sizeof(State) + \ + sizeof(Block) * conf_.block_num()); + if (arena_blocks_ == nullptr) { + AERROR << "get blocks failed."; + state_ = nullptr; + shmdt(managed_shm_); + managed_shm_ = nullptr; + return false; + } + // get block buf uint32_t i = 0; for (; i < conf_.block_num(); ++i) { uint8_t* addr = reinterpret_cast( - static_cast(managed_shm_) + sizeof(State) + - conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()); + static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + \ + ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ + i * conf_.block_buf_size()); if (addr == nullptr) { break; @@ -188,15 +235,36 @@ bool XsiSegment::OpenOnly() { block_buf_addrs_[i] = addr; } - if (i != conf_.block_num()) { + // get arena block buf + uint32_t ai = 0; + for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { + uint8_t* addr = reinterpret_cast( + static_cast(managed_shm_) + sizeof(State) + \ + conf_.block_num() * sizeof(Block) + ShmConf::ARENA_BLOCK_NUM * \ + sizeof(Block) + conf_.block_num() * conf_.block_buf_size() + \ + ai * ShmConf::ARENA_MESSAGE_SIZE); + + if (addr == nullptr) { + break; + } + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_[ai] = addr; + } + + if (i != conf_.block_num() || ai != ShmConf::ARENA_BLOCK_NUM) { AERROR << "open only failed."; state_->~State(); state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard _g(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } shmdt(managed_shm_); managed_shm_ = nullptr; shmctl(shmid, IPC_RMID, 0); @@ -222,10 +290,15 @@ bool XsiSegment::Remove() { void XsiSegment::Reset() { state_ = nullptr; blocks_ = nullptr; + arena_blocks_ = nullptr; { std::lock_guard _g(block_buf_lock_); block_buf_addrs_.clear(); } + { + std::lock_guard _g(arena_block_buf_lock_); + arena_block_buf_addrs_.clear(); + } if (managed_shm_ != nullptr) { shmdt(managed_shm_); managed_shm_ = nullptr; diff --git a/cyber/transport/transmitter/hybrid_transmitter.h b/cyber/transport/transmitter/hybrid_transmitter.h index 1afba70..fe176d4 100644 --- a/cyber/transport/transmitter/hybrid_transmitter.h +++ b/cyber/transport/transmitter/hybrid_transmitter.h @@ -25,12 +25,13 @@ #include #include +#include "cyber/proto/role_attributes.pb.h" +#include "cyber/proto/transport_conf.pb.h" #include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/common/types.h" -#include "cyber/proto/role_attributes.pb.h" -#include "cyber/proto/transport_conf.pb.h" #include "cyber/task/task.h" +#include "cyber/transport/dispatcher/rtps_dispatcher.h" #include "cyber/transport/message/history.h" #include "cyber/transport/rtps/participant.h" #include "cyber/transport/transmitter/intra_transmitter.h" @@ -71,6 +72,8 @@ class HybridTransmitter : public Transmitter { bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + bool AcquireMessage(std::shared_ptr& msg); + private: void InitMode(); void ObtainConfig(); @@ -141,7 +144,7 @@ void HybridTransmitter::Enable(const RoleAttributes& opposite_attr) { uint64_t id = opposite_attr.id(); std::lock_guard lock(mutex_); receivers_[mapping_table_[relation]].insert(id); - transmitters_[mapping_table_[relation]]->Enable(); + transmitters_[mapping_table_[relation]]->Enable(opposite_attr); TransmitHistoryMsg(opposite_attr); } @@ -155,9 +158,7 @@ void HybridTransmitter::Disable(const RoleAttributes& opposite_attr) { uint64_t id = opposite_attr.id(); std::lock_guard lock(mutex_); receivers_[mapping_table_[relation]].erase(id); - if (receivers_[mapping_table_[relation]].empty()) { - transmitters_[mapping_table_[relation]]->Disable(); - } + transmitters_[mapping_table_[relation]]->Disable(opposite_attr); } template @@ -165,12 +166,25 @@ bool HybridTransmitter::Transmit(const MessagePtr& msg, const MessageInfo& msg_info) { std::lock_guard lock(mutex_); history_->Add(msg, msg_info); + bool return_val = false; for (auto& item : transmitters_) { item.second->Transmit(msg, msg_info); } return true; } +template +bool HybridTransmitter::AcquireMessage(std::shared_ptr& msg) { + bool result = false; + for (auto& item : transmitters_) { + result = item.second->AcquireMessage(msg); + if (result) { + return true; + } + } + return false; +} + template void HybridTransmitter::InitMode() { mode_ = std::make_shared(); diff --git a/cyber/transport/transmitter/intra_transmitter.h b/cyber/transport/transmitter/intra_transmitter.h index 1235652..de9ab7c 100644 --- a/cyber/transport/transmitter/intra_transmitter.h +++ b/cyber/transport/transmitter/intra_transmitter.h @@ -39,13 +39,23 @@ class IntraTransmitter : public Transmitter { void Enable() override; void Disable() override; + void Enable(const RoleAttributes& opposite_attr) override; + void Disable(const RoleAttributes& opposite_attr) override; + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + bool AcquireMessage(std::shared_ptr& msg); + private: uint64_t channel_id_; IntraDispatcherPtr dispatcher_; }; +template +bool IntraTransmitter::AcquireMessage(std::shared_ptr& msg) { + return false; +} + template IntraTransmitter::IntraTransmitter(const RoleAttributes& attr) : Transmitter(attr), @@ -57,6 +67,18 @@ IntraTransmitter::~IntraTransmitter() { Disable(); } +template +void IntraTransmitter::Enable(const RoleAttributes& opposite_attr) { + (void)opposite_attr; + this->Enable(); +} + +template +void IntraTransmitter::Disable(const RoleAttributes& opposite_attr) { + (void)opposite_attr; + this->Disable(); +} + template void IntraTransmitter::Enable() { if (!this->enabled_) { diff --git a/cyber/transport/transmitter/rtps_transmitter.h b/cyber/transport/transmitter/rtps_transmitter.h index 54864c2..7ec65ff 100644 --- a/cyber/transport/transmitter/rtps_transmitter.h +++ b/cyber/transport/transmitter/rtps_transmitter.h @@ -17,18 +17,19 @@ #ifndef CYBER_TRANSPORT_TRANSMITTER_RTPS_TRANSMITTER_H_ #define CYBER_TRANSPORT_TRANSMITTER_RTPS_TRANSMITTER_H_ +#include #include #include #include "cyber/common/log.h" #include "cyber/message/message_traits.h" +#include "cyber/statistics/statistics.h" +#include "cyber/time/time.h" +#include "cyber/transport/dispatcher/subscriber_listener.h" #include "cyber/transport/rtps/attributes_filler.h" #include "cyber/transport/rtps/participant.h" +#include "cyber/transport/rtps/publisher.h" #include "cyber/transport/transmitter/transmitter.h" -#include "fastrtps/Domain.h" -#include "fastrtps/attributes/PublisherAttributes.h" -#include "fastrtps/participant/Participant.h" -#include "fastrtps/publisher/Publisher.h" namespace apollo { namespace cyber { @@ -38,6 +39,7 @@ template class RtpsTransmitter : public Transmitter { public: using MessagePtr = std::shared_ptr; + using ParticipantPtr = std::shared_ptr; RtpsTransmitter(const RoleAttributes& attr, const ParticipantPtr& participant); @@ -46,15 +48,25 @@ class RtpsTransmitter : public Transmitter { void Enable() override; void Disable() override; + void Enable(const RoleAttributes& opposite_attr) override; + void Disable(const RoleAttributes& opposite_attr) override; + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + bool AcquireMessage(std::shared_ptr& msg); + private: bool Transmit(const M& msg, const MessageInfo& msg_info); ParticipantPtr participant_; - eprosima::fastrtps::Publisher* publisher_; + PublisherPtr publisher_; }; +template +bool RtpsTransmitter::AcquireMessage(std::shared_ptr& msg) { + return false; +} + template RtpsTransmitter::RtpsTransmitter(const RoleAttributes& attr, const ParticipantPtr& participant) @@ -65,6 +77,18 @@ RtpsTransmitter::~RtpsTransmitter() { Disable(); } +template +void RtpsTransmitter::Enable(const RoleAttributes& opposite_attr) { + (void)opposite_attr; + this->Enable(); +} + +template +void RtpsTransmitter::Disable(const RoleAttributes& opposite_attr) { + (void)opposite_attr; + this->Disable(); +} + template void RtpsTransmitter::Enable() { if (this->enabled_) { @@ -73,11 +97,9 @@ void RtpsTransmitter::Enable() { RETURN_IF_NULL(participant_); - eprosima::fastrtps::PublisherAttributes pub_attr; - RETURN_IF(!AttributesFiller::FillInPubAttr( - this->attr_.channel_name(), this->attr_.qos_profile(), &pub_attr)); - publisher_ = eprosima::fastrtps::Domain::createPublisher( - participant_->fastrtps_participant(), pub_attr); + publisher_ = participant_->CreatePublisher(this->attr_.channel_name(), + this->attr_.qos_profile()); + RETURN_IF_NULL(publisher_); this->enabled_ = true; } @@ -99,30 +121,21 @@ bool RtpsTransmitter::Transmit(const MessagePtr& msg, template bool RtpsTransmitter::Transmit(const M& msg, const MessageInfo& msg_info) { if (!this->enabled_) { - ADEBUG << "not enable."; + ADEBUG << "RtpsTransmitter not enable."; return false; } UnderlayMessage m; RETURN_VAL_IF(!message::SerializeToString(msg, &m.data()), false); - - eprosima::fastrtps::rtps::WriteParams wparams; - - char* ptr = - reinterpret_cast(&wparams.related_sample_identity().writer_guid()); - - memcpy(ptr, msg_info.sender_id().data(), ID_SIZE); - memcpy(ptr + ID_SIZE, msg_info.spare_id().data(), ID_SIZE); - - wparams.related_sample_identity().sequence_number().high = - (int32_t)((msg_info.seq_num() & 0xFFFFFFFF00000000) >> 32); - wparams.related_sample_identity().sequence_number().low = - (int32_t)(msg_info.seq_num() & 0xFFFFFFFF); + m.timestamp(msg_info.send_time()); + m.seq(msg_info.seq_num()); if (participant_->is_shutdown()) { return false; } - return publisher_->write(reinterpret_cast(&m), wparams); + + RETURN_VAL_IF_NULL(publisher_, NULL); + return publisher_->Write(m, msg_info); } } // namespace transport diff --git a/cyber/transport/transmitter/shm_transmitter.h b/cyber/transport/transmitter/shm_transmitter.h index b4a6667..5d8a0d5 100644 --- a/cyber/transport/transmitter/shm_transmitter.h +++ b/cyber/transport/transmitter/shm_transmitter.h @@ -21,12 +21,16 @@ #include #include #include +#include #include "cyber/common/global_data.h" #include "cyber/common/log.h" #include "cyber/common/util.h" +#include "cyber/message/arena_message_wrapper.h" #include "cyber/message/message_traits.h" +#include "cyber/statistics/statistics.h" #include "cyber/transport/shm/notifier_factory.h" +#include "cyber/transport/shm/protobuf_arena_manager.h" #include "cyber/transport/shm/readable_info.h" #include "cyber/transport/shm/segment_factory.h" #include "cyber/transport/transmitter/transmitter.h" @@ -35,6 +39,9 @@ namespace apollo { namespace cyber { namespace transport { +template +struct type_check : std::is_same::type, U>::type {}; + template class ShmTransmitter : public Transmitter { public: @@ -46,8 +53,13 @@ class ShmTransmitter : public Transmitter { void Enable() override; void Disable() override; + void Enable(const RoleAttributes& opposite_attr); + void Disable(const RoleAttributes& opposite_attr); + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + bool AcquireMessage(std::shared_ptr& msg); + private: bool Transmit(const M& msg, const MessageInfo& msg_info); @@ -55,15 +67,44 @@ class ShmTransmitter : public Transmitter { uint64_t channel_id_; uint64_t host_id_; NotifierPtr notifier_; + std::atomic serialized_receiver_count_; + std::atomic arena_receiver_count_; + bool arena_transmit_; }; +template +bool ShmTransmitter::AcquireMessage(std::shared_ptr& msg) { + if (this->enabled_) { + auto msg_o = msg.get(); + auto arena_manager = ProtobufArenaManager::Instance(); + if (!arena_manager->Enable() || + !arena_manager->EnableSegment(this->attr_.channel_id())) { + ADEBUG << "arena manager enable failed."; + return false; + } + arena_manager->AcquireArenaMessage(channel_id_, msg); + if (msg.get() != msg_o) { + return true; + } else { + return false; + } + } + return false; +} + template ShmTransmitter::ShmTransmitter(const RoleAttributes& attr) : Transmitter(attr), segment_(nullptr), channel_id_(attr.channel_id()), - notifier_(nullptr) { + notifier_(nullptr), + serialized_receiver_count_(0), + arena_receiver_count_(0) { host_id_ = common::Hash(attr.host_ip()); + arena_transmit_ = common::GlobalData::Instance()->IsChannelEnableArenaShm( + this->attr_.channel_id()) && + !type_check::value && + !type_check::value; } template @@ -71,12 +112,71 @@ ShmTransmitter::~ShmTransmitter() { Disable(); } +template +void ShmTransmitter::Enable(const RoleAttributes& opposite_attr) { + if (arena_transmit_) { + if (opposite_attr.message_type() == + message::MessageType() || + opposite_attr.message_type() == + message::MessageType()) { + serialized_receiver_count_.fetch_add(1); + } else { + arena_receiver_count_.fetch_add(1); + } + } else { + serialized_receiver_count_.fetch_add(1); + } + if (!this->enabled_) { + this->Enable(); + } +} + +template +void ShmTransmitter::Disable(const RoleAttributes& opposite_attr) { + if (this->enabled_) { + if (arena_transmit_) { + if (opposite_attr.message_type() == + message::MessageType() || + opposite_attr.message_type() == + message::MessageType()) { + serialized_receiver_count_.fetch_sub(1); + } else { + arena_receiver_count_.fetch_sub(1); + } + if (serialized_receiver_count_.load() <= 0 && + arena_receiver_count_.load() <= 0) { + this->Disable(); + } + } else { + serialized_receiver_count_.fetch_sub(1); + if (serialized_receiver_count_.load() <= 0) { + this->Disable(); + } + } + } +} + template void ShmTransmitter::Enable() { if (this->enabled_) { return; } + if (serialized_receiver_count_.load() == 0 && + arena_receiver_count_.load() == 0) { + AERROR << "please enable shm transmitter by passing role attr."; + return; + } + + if (arena_transmit_) { + auto arena_manager = ProtobufArenaManager::Instance(); + if (!arena_manager->Enable() || + !arena_manager->EnableSegment(this->attr_.channel_id())) { + AERROR << "arena manager enable failed."; + return; + } + } + segment_ = SegmentFactory::CreateSegment(channel_id_); notifier_ = NotifierFactory::CreateNotifier(); this->enabled_ = true; @@ -104,35 +204,119 @@ bool ShmTransmitter::Transmit(const M& msg, const MessageInfo& msg_info) { return false; } + ReadableInfo readable_info; + WritableBlock arena_wb; WritableBlock wb; - std::size_t msg_size = message::ByteSize(msg); - if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { - AERROR << "acquire block failed."; - return false; - } - ADEBUG << "block index: " << wb.index; - if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { - AERROR << "serialize to array failed."; - segment_->ReleaseWrittenBlock(wb); - return false; - } - wb.block->set_msg_size(msg_size); + readable_info.set_host_id(host_id_); + readable_info.set_channel_id(channel_id_); + readable_info.set_arena_block_index(-1); + readable_info.set_block_index(-1); + + if (arena_transmit_) { + // std::size_t msg_size = sizeof(message::ArenaMessageWrapper); + std::size_t msg_size = 1024; + if (!segment_->AcquireArenaBlockToWrite(msg_size, &arena_wb)) { + AERROR << "acquire block failed."; + return false; + } + + ADEBUG << "arena block index: " << arena_wb.index; + auto arena_manager = ProtobufArenaManager::Instance(); + auto msg_wrapper = arena_manager->CreateMessageWrapper(); + arena_manager->SetMessageChannelId(msg_wrapper.get(), channel_id_); + M* msg_p; + // arena_manager->CreateMessage(msg_wrapper.get(), msg); + if (!message::SerializeToArenaMessageWrapper(msg, msg_wrapper.get(), + &msg_p)) { + AERROR << "serialize to arena message wrapper failed."; + segment_->ReleaseArenaWrittenBlock(arena_wb); + return false; + } + auto segment = arena_manager->GetSegment(channel_id_); + // auto msg_n = + // std::shared_ptr( + // msg_p, [arena_manager, segment, msg_wrapper](M* p) { + // auto related_blocks = + // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); + // for (auto block_index : related_blocks) { + // // segment->ReleaseBlockForWriteByIndex(block_index); + // segment->RemoveBlockWriteLock(block_index); + // } + // }); + // for (auto block_index : + // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get())) { + // segment->LockBlockForWriteByIndex(block_index); + // } + memcpy(arena_wb.buf, msg_wrapper->GetData(), msg_size); + arena_wb.block->set_msg_size(msg_size); + + char* msg_info_addr = reinterpret_cast(arena_wb.buf) + msg_size; + if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { + AERROR << "serialize message info failed."; + segment_->ReleaseArenaWrittenBlock(arena_wb); + return false; + } + arena_wb.block->set_msg_info_size(MessageInfo::kSize); + readable_info.set_arena_block_index(arena_wb.index); + if (serialized_receiver_count_.load() > 0) { + std::size_t msg_size = message::ByteSize(msg); + if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { + AERROR << "acquire block failed."; + return false; + } + + ADEBUG << "block index: " << wb.index; + if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { + AERROR << "serialize to array failed."; + segment_->ReleaseWrittenBlock(wb); + return false; + } + wb.block->set_msg_size(msg_size); - char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; - if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { - AERROR << "serialize message info failed."; + char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; + if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { + AERROR << "serialize message info failed."; + segment_->ReleaseWrittenBlock(wb); + return false; + } + wb.block->set_msg_info_size(MessageInfo::kSize); + segment_->ReleaseWrittenBlock(wb); + segment_->ReleaseArenaWrittenBlock(arena_wb); + readable_info.set_block_index(wb.index); + } else { + segment_->ReleaseArenaWrittenBlock(arena_wb); + } + } else { + std::size_t msg_size = message::ByteSize(msg); + if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { + AERROR << "acquire block failed."; + return false; + } + + ADEBUG << "block index: " << wb.index; + if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { + AERROR << "serialize to array failed."; + segment_->ReleaseWrittenBlock(wb); + return false; + } + wb.block->set_msg_size(msg_size); + + char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; + if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { + AERROR << "serialize message info failed."; + segment_->ReleaseWrittenBlock(wb); + return false; + } + wb.block->set_msg_info_size(MessageInfo::kSize); segment_->ReleaseWrittenBlock(wb); - return false; + readable_info.set_block_index(wb.index); } - wb.block->set_msg_info_size(MessageInfo::kSize); - segment_->ReleaseWrittenBlock(wb); - - ReadableInfo readable_info(host_id_, wb.index, channel_id_); ADEBUG << "Writing sharedmem message: " << common::GlobalData::GetChannelById(channel_id_) - << " to block: " << wb.index; + << " to normal block: " << readable_info.block_index() + << " to arena block: " << readable_info.arena_block_index(); return notifier_->Notify(readable_info); } diff --git a/cyber/transport/transmitter/transmitter.h b/cyber/transport/transmitter/transmitter.h index b8fc7f7..de0fa96 100644 --- a/cyber/transport/transmitter/transmitter.h +++ b/cyber/transport/transmitter/transmitter.h @@ -22,6 +22,7 @@ #include #include "cyber/event/perf_event_cache.h" +#include "cyber/statistics/statistics.h" #include "cyber/transport/common/endpoint.h" #include "cyber/transport/message/message_info.h" @@ -43,26 +44,32 @@ class Transmitter : public Endpoint { virtual void Enable() = 0; virtual void Disable() = 0; + virtual bool AcquireMessage(std::shared_ptr& msg) = 0; + virtual void Enable(const RoleAttributes& opposite_attr); virtual void Disable(const RoleAttributes& opposite_attr); virtual bool Transmit(const MessagePtr& msg); virtual bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) = 0; - uint64_t NextSeqNum() { return ++seq_num_; } + uint64_t NextSeqNum() { + (*seq_num_) << 1; + return seq_num_->get_value(); + } - uint64_t seq_num() const { return seq_num_; } + uint64_t seq_num() const { return seq_num_->get_value(); } protected: - uint64_t seq_num_; MessageInfo msg_info_; + std::shared_ptr<::bvar::Adder> seq_num_; }; template -Transmitter::Transmitter(const RoleAttributes& attr) - : Endpoint(attr), seq_num_(0) { +Transmitter::Transmitter(const RoleAttributes& attr) : Endpoint(attr) { msg_info_.set_sender_id(this->id_); - msg_info_.set_seq_num(this->seq_num_); + msg_info_.set_seq_num(0); + seq_num_ = + statistics::Statistics::Instance()->CreateAdder(Endpoint::attr_); } template @@ -71,6 +78,7 @@ Transmitter::~Transmitter() {} template bool Transmitter::Transmit(const MessagePtr& msg) { msg_info_.set_seq_num(NextSeqNum()); + msg_info_.set_send_time(Time::Now().ToNanosecond()); PerfEventCache::Instance()->AddTransportEvent( TransPerf::TRANSMIT_BEGIN, attr_.channel_id(), msg_info_.seq_num()); return Transmit(msg, msg_info_); diff --git a/cyber/transport/transport.cc b/cyber/transport/transport.cc index 0234871..a9d6d0c 100644 --- a/cyber/transport/transport.cc +++ b/cyber/transport/transport.cc @@ -17,6 +17,7 @@ #include "cyber/transport/transport.h" #include "cyber/common/global_data.h" +#include "cyber/transport/dispatcher/rtps_dispatcher.h" namespace apollo { namespace cyber { @@ -28,7 +29,7 @@ Transport::Transport() { intra_dispatcher_ = IntraDispatcher::Instance(); shm_dispatcher_ = ShmDispatcher::Instance(); rtps_dispatcher_ = RtpsDispatcher::Instance(); - rtps_dispatcher_->set_participant(participant_); + rtps_dispatcher_->SetParticipant(participant_); } Transport::~Transport() { Shutdown(); } @@ -53,7 +54,11 @@ void Transport::CreateParticipant() { std::string participant_name = common::GlobalData::Instance()->HostName() + "+" + std::to_string(common::GlobalData::Instance()->ProcessId()); - participant_ = std::make_shared(participant_name, 11512); + participant_ = std::make_shared< + Participant>(participant_name, 11512); + if (!participant_->Init()) { + AERROR << "Transport inner participant init failed!"; + } } } // namespace transport From 98f13ce098a67f887fa83be9b4a8b1c1d8e50b70 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 14 Dec 2024 12:33:03 +0800 Subject: [PATCH 05/14] feat(common_msgs): update common_msgs for v10 --- .../common_msgs/basic_msgs/pnc_point.proto | 1 + .../common_msgs/chassis_msgs/chassis.proto | 1 + modules/common_msgs/control_msgs/BUILD | 8 + .../control_msgs/control_cmd.proto | 5 +- .../control_interactive_msg.proto | 17 ++ .../dreamview_msgs/hmi_config.proto | 1 + .../common_msgs/dreamview_msgs/hmi_mode.proto | 10 +- .../dreamview_msgs/simulation_world.proto | 2 + .../common_msgs/external_command_msgs/BUILD | 18 +++ .../action_command.proto | 4 + .../precise_parking_command.proto | 26 ++++ .../zone_cover_command.proto | 16 ++ .../localization_status.proto | 71 ++++++++- modules/common_msgs/map_msgs/BUILD | 22 +++ modules/common_msgs/map_msgs/map.proto | 4 + modules/common_msgs/map_msgs/map_area.proto | 22 +++ .../map_msgs/map_barrier_gate.proto | 22 +++ modules/common_msgs/map_msgs/map_lane.proto | 1 + .../common_msgs/map_msgs/map_overlap.proto | 6 + .../monitor_msgs/monitor_log.proto | 1 + modules/common_msgs/perception_msgs/BUILD | 8 + .../perception_barrier_gate.proto | 33 ++++ .../perception_msgs/perception_obstacle.proto | 69 +++++++++ .../traffic_light_detection.proto | 1 + .../common_msgs/planning_msgs/pad_msg.proto | 4 + .../common_msgs/planning_msgs/planning.proto | 25 +++ .../prediction_msgs/prediction_obstacle.proto | 3 + modules/common_msgs/sensor_msgs/BUILD | 8 + .../common_msgs/sensor_msgs/nano_radar.proto | 146 ++++++++++++++++++ .../common_msgs/simulation_msgs/agent.proto | 17 ++ 30 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 modules/common_msgs/control_msgs/control_interactive_msg.proto create mode 100644 modules/common_msgs/external_command_msgs/precise_parking_command.proto create mode 100644 modules/common_msgs/external_command_msgs/zone_cover_command.proto create mode 100644 modules/common_msgs/map_msgs/map_area.proto create mode 100644 modules/common_msgs/map_msgs/map_barrier_gate.proto create mode 100644 modules/common_msgs/perception_msgs/perception_barrier_gate.proto create mode 100755 modules/common_msgs/sensor_msgs/nano_radar.proto diff --git a/modules/common_msgs/basic_msgs/pnc_point.proto b/modules/common_msgs/basic_msgs/pnc_point.proto index cf948f5..f8cff2c 100644 --- a/modules/common_msgs/basic_msgs/pnc_point.proto +++ b/modules/common_msgs/basic_msgs/pnc_point.proto @@ -74,6 +74,7 @@ message TrajectoryPoint { // Gaussian probability information optional GaussianInfo gaussian_info = 7; + } message Trajectory { diff --git a/modules/common_msgs/chassis_msgs/chassis.proto b/modules/common_msgs/chassis_msgs/chassis.proto index 77e9fb7..d4ab806 100644 --- a/modules/common_msgs/chassis_msgs/chassis.proto +++ b/modules/common_msgs/chassis_msgs/chassis.proto @@ -35,6 +35,7 @@ message Chassis { CHASSIS_ERROR_ON_BRAKE = 7; CHASSIS_ERROR_ON_THROTTLE = 8; CHASSIS_ERROR_ON_GEAR = 9; + CHASSIS_CAN_LOST = 10; MANUAL_INTERVENTION = 3; // human manual intervention diff --git a/modules/common_msgs/control_msgs/BUILD b/modules/common_msgs/control_msgs/BUILD index 2f12fee..e17a1b2 100644 --- a/modules/common_msgs/control_msgs/BUILD +++ b/modules/common_msgs/control_msgs/BUILD @@ -19,6 +19,14 @@ proto_library( ], ) +proto_library( + name = "control_interactive_msg_proto", + srcs = ["control_interactive_msg.proto"], + deps = [ + "//modules/common_msgs/basic_msgs:header_proto", + ], +) + proto_library( name = "control_pad_msg_proto", srcs = ["pad_msg.proto"], diff --git a/modules/common_msgs/control_msgs/control_cmd.proto b/modules/common_msgs/control_msgs/control_cmd.proto index 7559675..87c3ce8 100644 --- a/modules/common_msgs/control_msgs/control_cmd.proto +++ b/modules/common_msgs/control_msgs/control_cmd.proto @@ -38,7 +38,7 @@ message ControlCommand { // target steering angle, in percentage of full scale [-100, 100] optional double steering_target = 7; - // parking brake engage. true: engaged + // parking brake engage. true: engaged epd brake optional bool parking_brake = 8; // target speed, in m/s @@ -171,6 +171,9 @@ message SimpleLateralDebug { // Mrac control status and feedback states for steer control optional MracDebug steer_mrac_debug = 32; optional bool steer_mrac_enable_status = 33; + + // lat acc in ENU, in m/s^2 + optional double lateral_centripetal_acceleration = 34; } message SimpleMPCDebug { diff --git a/modules/common_msgs/control_msgs/control_interactive_msg.proto b/modules/common_msgs/control_msgs/control_interactive_msg.proto new file mode 100644 index 0000000..159a458 --- /dev/null +++ b/modules/common_msgs/control_msgs/control_interactive_msg.proto @@ -0,0 +1,17 @@ +syntax = "proto2"; +package apollo.control; + +import "modules/common_msgs/basic_msgs/header.proto"; + +message ControlInteractiveMsg { + optional apollo.common.Header header = 1; // common header + optional bool replan_request = 2; // request replan. true: need replan, false: don't need replan + optional ReplanRequestReasonCode replan_req_reason_code = 3; // request replan reason code + optional string replan_request_reason = 4; // request replan reason +} + +enum ReplanRequestReasonCode { + REPLAN_REQ_ALL_REPLAN = 1; + REPLAN_REQ_STATION_REPLAN = 2; + REPLAN_REQ_SPEED_REPLAN = 3; +} diff --git a/modules/common_msgs/dreamview_msgs/hmi_config.proto b/modules/common_msgs/dreamview_msgs/hmi_config.proto index 9e373d4..44c4b9b 100644 --- a/modules/common_msgs/dreamview_msgs/hmi_config.proto +++ b/modules/common_msgs/dreamview_msgs/hmi_config.proto @@ -34,6 +34,7 @@ enum HMIAction { LOAD_RTK_RECORDS = 25; // Load all rtk records CHANGE_RTK_RECORD = 26; // change rtk records LOAD_RECORD = 27; // Load record + LOAD_MAPS = 28; // Load maps } message HMIConfig { diff --git a/modules/common_msgs/dreamview_msgs/hmi_mode.proto b/modules/common_msgs/dreamview_msgs/hmi_mode.proto index aef7cde..09354ba 100644 --- a/modules/common_msgs/dreamview_msgs/hmi_mode.proto +++ b/modules/common_msgs/dreamview_msgs/hmi_mode.proto @@ -118,6 +118,14 @@ message CyberModule { optional string process_group = 3; } +message Layout { + optional string type = 1; + optional Layout first = 2; + optional Layout second = 3; + optional string direction = 4; + optional double splitPercentage = 5 [default = 50.0]; +} + message HMIMode { map cyber_modules = 1; map modules = 2; @@ -125,6 +133,6 @@ message HMIMode { map other_components = 4; repeated HMIModeOperation operations = 5; optional HMIModeOperation default_operation = 6; - optional string layout = 7; + optional Layout layout = 7; map global_components = 8; } diff --git a/modules/common_msgs/dreamview_msgs/simulation_world.proto b/modules/common_msgs/dreamview_msgs/simulation_world.proto index 089ae9b..a1c8218 100644 --- a/modules/common_msgs/dreamview_msgs/simulation_world.proto +++ b/modules/common_msgs/dreamview_msgs/simulation_world.proto @@ -197,6 +197,8 @@ message MapElementIds { repeated string parking_space = 10; repeated string speed_bump = 11; repeated string pnc_junction = 12; + repeated string ad_area = 13; + repeated string barrier_gate = 14; } message ControlData { diff --git a/modules/common_msgs/external_command_msgs/BUILD b/modules/common_msgs/external_command_msgs/BUILD index 830d0e8..fab1d33 100644 --- a/modules/common_msgs/external_command_msgs/BUILD +++ b/modules/common_msgs/external_command_msgs/BUILD @@ -4,6 +4,15 @@ load("//tools:apollo_package.bzl", "apollo_package") package(default_visibility = ["//visibility:public"]) +proto_library( + name = "precise_parking_command_proto", + srcs = ["precise_parking_command.proto"], + deps = [ + ":external_geometry_proto", + "//modules/common_msgs/basic_msgs:header_proto", + ], +) + proto_library( name = "valet_parking_command_proto", srcs = ["valet_parking_command.proto"], @@ -60,6 +69,15 @@ proto_library( ], ) +proto_library( + name = "zone_cover_command_proto", + srcs = ["zone_cover_command.proto"], + deps = [ + ":external_geometry_proto", + "//modules/common_msgs/basic_msgs:header_proto", + ], +) + proto_library( name = "speed_command_proto", srcs = ["speed_command.proto"], diff --git a/modules/common_msgs/external_command_msgs/action_command.proto b/modules/common_msgs/external_command_msgs/action_command.proto index 6e52ed8..89bc1f7 100644 --- a/modules/common_msgs/external_command_msgs/action_command.proto +++ b/modules/common_msgs/external_command_msgs/action_command.proto @@ -25,6 +25,10 @@ enum ActionCommandType { SWITCH_TO_AUTO = 51; // Varify vin code of vehicle. VIN_REQ = 52; + // Enter mission model + ENTER_MISSION = 53; + // Exit mission model + EXIT_MISSION = 54; } message ActionCommand { diff --git a/modules/common_msgs/external_command_msgs/precise_parking_command.proto b/modules/common_msgs/external_command_msgs/precise_parking_command.proto new file mode 100644 index 0000000..212dd29 --- /dev/null +++ b/modules/common_msgs/external_command_msgs/precise_parking_command.proto @@ -0,0 +1,26 @@ +syntax = "proto2"; + +package apollo.external_command; + +import "modules/common_msgs/basic_msgs/header.proto"; +import "modules/common_msgs/external_command_msgs/geometry.proto"; + +enum PreciseMissionType { + CHARGE = 0; + DUMP = 1; +} + +message PreciseParkingCommand { + optional apollo.common.Header header = 1; + // Unique identification for command. + optional int64 command_id = 2 [default = -1]; + // If the start pose is set as the first point of "way_point". + optional bool is_start_pose_set = 3 [default = false]; + // Pose of the parking spot. + required Pose parking_spot_pose = 4; + // true: parking inwards, false: parking outwards + required bool parking_inwards = 5; + required PreciseMissionType mission_type = 6; + // not given, the default target speed of system will be used. + optional double target_speed = 7; +} \ No newline at end of file diff --git a/modules/common_msgs/external_command_msgs/zone_cover_command.proto b/modules/common_msgs/external_command_msgs/zone_cover_command.proto new file mode 100644 index 0000000..f206305 --- /dev/null +++ b/modules/common_msgs/external_command_msgs/zone_cover_command.proto @@ -0,0 +1,16 @@ +syntax = "proto2"; + +package apollo.external_command; + +import "modules/common_msgs/basic_msgs/header.proto"; +import "modules/common_msgs/external_command_msgs/geometry.proto"; + +message ZoneCoverCommand { + optional apollo.common.Header header = 1; + // Unique identification for command. + optional int64 command_id = 2 [default = -1]; + required string overlap_id = 3; + optional double target_speed = 4; + repeated RoiPolygon non_drivable_roi = 5; + optional RoiPolygon drivable_roi = 6; +} diff --git a/modules/common_msgs/localization_msgs/localization_status.proto b/modules/common_msgs/localization_msgs/localization_status.proto index d852c31..11d3db7 100644 --- a/modules/common_msgs/localization_msgs/localization_status.proto +++ b/modules/common_msgs/localization_msgs/localization_status.proto @@ -155,6 +155,7 @@ enum MsfRunningStatus { MSF_NOSOL_X_XX = 22; MSF_NOSOL_X_XXX = 23; MSF_RUNNING_INIT = 24; + MSF_REINIT_ABNORMALLY = 25; } // The status of sensor msg @@ -164,12 +165,76 @@ message MsfSensorMsgStatus { optional ImuMsgDataStatus imu_data_status = 3; } +// The init pose source +enum MsfInitPoseSource { + UNKNOWN_SOURCE = 0; + GNSS_HEADING = 1; + LOCAL_SEARCH_FROM_INTEGPVA = 2; + LOCAL_SEARCH_FROM_FILE = 3; + LOCAL_UPDATE_FROM_FILE = 4; + USER_INTERACTION = 5; + INSPVA_RECORD = 6; + GNSS_VELOCITY = 7; + GLOBAL_LIDAR = 8; +} + +// The status of gnss map offset +enum MsfGnssMapOffsetStatus { + MSF_LOCAL_GNSS_MAP_OFFSET_NORMAL = 0; + MSF_LOCAL_GNSS_MAP_OFFSET_ABNORMAL = 1; +} + +// The gnss map offset +message MsfGnssMapOffset { + optional MsfGnssMapOffsetStatus status = 1; + optional double offsetx = 2; + optional double offsety = 3; +} + +// The init pose status +enum MsfInitPoseStatus { + INIT_WAITING = 0; + INIT_DOING = 1; + INIT_SUCCESSFUL = 2; + INIT_FAILED = 3; + INIT_TERMINATED = 4; +} + +// The init details +message MsfInitDetails { + optional MsfInitPoseSource init_pose_source = 1; + optional MsfInitPoseStatus local_search_from_integpva_status = 2; + optional MsfInitPoseStatus local_search_from_file_status = 3; + optional MsfInitPoseStatus local_update_from_file_status = 4; + optional MsfInitPoseStatus user_interaction_status = 5; + optional int32 gnss_position_type = 6; + optional MsfInitPoseStatus local_from_global_lidar_status = 7; +} + +// The initializaiton status of localization module +enum MSFInitStatus { + MSF_INIT = 0; + MSF_ALIGNING = 1; + MSF_ALIGNED_INIT = 2; + MSF_ALIGNED_CONVERGED = 3; + MSF_ALIGNED_CONVERGING = 4; + MSF_ALIGNED_GOOD = 5; + MSF_ALIGNED_VALID = 6; +} + // The status of msf localization module message MsfStatus { optional LocalLidarConsistency local_lidar_consistency = 1; optional GnssConsistency gnss_consistency = 2; optional LocalLidarStatus local_lidar_status = 3; - optional LocalLidarQuality local_lidar_quality = 4; - optional GnssPositionType gnsspos_position_type = 5; - optional MsfRunningStatus msf_running_status = 6; + optional GnssPositionType gnsspos_position_type = 4; + optional uint32 heading_position_type = 5; + optional MSFInitStatus msf_init_status = 6; + optional MsfRunningStatus msf_running_status = 7; + optional MsfInitDetails msf_init_details = 8; + optional LocalLidarQuality local_lidar_quality = 9; + optional MsfGnssMapOffset gnss_map_offset = 10; + optional bool lidar_alt_from_map = 11; + optional double local_lidar_score = 12; + optional bool local_reliability_status = 13 [default = false]; } diff --git a/modules/common_msgs/map_msgs/BUILD b/modules/common_msgs/map_msgs/BUILD index 3dc0bb6..f61b8fe 100644 --- a/modules/common_msgs/map_msgs/BUILD +++ b/modules/common_msgs/map_msgs/BUILD @@ -96,6 +96,8 @@ proto_library( ":map_speed_bump_proto", ":map_stop_sign_proto", ":map_yield_sign_proto", + ":map_area_proto", + ":map_barrier_gate_proto", ], ) @@ -162,4 +164,24 @@ proto_library( ], ) +proto_library( + name = "map_area_proto", + srcs = ["map_area.proto"], + deps = [ + ":map_geometry_proto", + ":map_id_proto", + "//modules/common_msgs/basic_msgs:geometry_proto", + ], +) + +proto_library( + name = "map_barrier_gate_proto", + srcs = ["map_barrier_gate.proto"], + deps = [ + ":map_geometry_proto", + ":map_id_proto", + "//modules/common_msgs/basic_msgs:geometry_proto", + ], +) + apollo_package() diff --git a/modules/common_msgs/map_msgs/map.proto b/modules/common_msgs/map_msgs/map.proto index 77e6c0d..f303962 100644 --- a/modules/common_msgs/map_msgs/map.proto +++ b/modules/common_msgs/map_msgs/map.proto @@ -15,6 +15,8 @@ import "modules/common_msgs/map_msgs/map_signal.proto"; import "modules/common_msgs/map_msgs/map_speed_bump.proto"; import "modules/common_msgs/map_msgs/map_stop_sign.proto"; import "modules/common_msgs/map_msgs/map_yield_sign.proto"; +import "modules/common_msgs/map_msgs/map_area.proto"; +import "modules/common_msgs/map_msgs/map_barrier_gate.proto"; // This message defines how we project the ellipsoidal Earth surface to a plane. message Projection { @@ -55,4 +57,6 @@ message Map { repeated ParkingSpace parking_space = 12; repeated PNCJunction pnc_junction = 13; repeated RSU rsu = 14; + repeated Area ad_area = 15; + repeated BarrierGate barrier_gate = 16; } diff --git a/modules/common_msgs/map_msgs/map_area.proto b/modules/common_msgs/map_msgs/map_area.proto new file mode 100644 index 0000000..0087595 --- /dev/null +++ b/modules/common_msgs/map_msgs/map_area.proto @@ -0,0 +1,22 @@ +syntax = "proto2"; + +package apollo.hdmap; + +import "modules/common_msgs/map_msgs/map_geometry.proto"; +import "modules/common_msgs/map_msgs/map_id.proto"; + +message Area { + enum Type { + Driveable = 1; + UnDriveable = 2; + Custom1 = 3; + Custom2 = 4; + Custom3 = 5; + }; + + required Id id = 1; + optional Type type = 2; + required Polygon polygon = 3; + repeated Id overlap_id = 4; + optional string name = 5; +} diff --git a/modules/common_msgs/map_msgs/map_barrier_gate.proto b/modules/common_msgs/map_msgs/map_barrier_gate.proto new file mode 100644 index 0000000..f7a5a0e --- /dev/null +++ b/modules/common_msgs/map_msgs/map_barrier_gate.proto @@ -0,0 +1,22 @@ +syntax = "proto2"; + +package apollo.hdmap; + +import "modules/common_msgs/map_msgs/map_geometry.proto"; +import "modules/common_msgs/map_msgs/map_id.proto"; + +message BarrierGate { + enum BarrierGateType { + ROD = 1; + FENCE = 2; + ADVERTISING = 3; + TELESCOPIC = 4; + OTHER = 5; + }; + + required Id id = 1; + optional BarrierGateType type = 2; + optional Polygon polygon = 3; + repeated Curve stop_line = 4; + repeated Id overlap_id = 5; +} \ No newline at end of file diff --git a/modules/common_msgs/map_msgs/map_lane.proto b/modules/common_msgs/map_msgs/map_lane.proto index a78cd73..01483b1 100644 --- a/modules/common_msgs/map_msgs/map_lane.proto +++ b/modules/common_msgs/map_msgs/map_lane.proto @@ -74,6 +74,7 @@ message Lane { SIDEWALK = 4; PARKING = 5; SHOULDER = 6; + SHARED = 7; }; optional LaneType type = 12; diff --git a/modules/common_msgs/map_msgs/map_overlap.proto b/modules/common_msgs/map_msgs/map_overlap.proto index 25509ff..003bb3b 100644 --- a/modules/common_msgs/map_msgs/map_overlap.proto +++ b/modules/common_msgs/map_msgs/map_overlap.proto @@ -35,6 +35,10 @@ message PNCJunctionOverlapInfo {} message RSUOverlapInfo {} +message AreaOverlapInfo {} + +message BarrierGateOverlapInfo {} + message RegionOverlapInfo { optional Id id = 1; repeated Polygon polygon = 2; @@ -56,6 +60,8 @@ message ObjectOverlapInfo { ParkingSpaceOverlapInfo parking_space_overlap_info = 11; PNCJunctionOverlapInfo pnc_junction_overlap_info = 12; RSUOverlapInfo rsu_overlap_info = 13; + AreaOverlapInfo area_overlap_info = 14; + BarrierGateOverlapInfo barrier_gate_overlap_info = 15; } } diff --git a/modules/common_msgs/monitor_msgs/monitor_log.proto b/modules/common_msgs/monitor_msgs/monitor_log.proto index 6bdf459..8d8a360 100644 --- a/modules/common_msgs/monitor_msgs/monitor_log.proto +++ b/modules/common_msgs/monitor_msgs/monitor_log.proto @@ -27,6 +27,7 @@ message MonitorMessageItem { DELPHI_ESR = 19; STORYTELLING = 20; TASK_MANAGER = 21; + NANO_RADAR = 22; } optional MessageSource source = 1 [default = UNKNOWN]; diff --git a/modules/common_msgs/perception_msgs/BUILD b/modules/common_msgs/perception_msgs/BUILD index a5f9d7c..e29f330 100644 --- a/modules/common_msgs/perception_msgs/BUILD +++ b/modules/common_msgs/perception_msgs/BUILD @@ -53,4 +53,12 @@ proto_library( ], ) +proto_library( + name = "perception_barrier_gate_proto", + srcs = ["perception_barrier_gate.proto"], + deps = [ + "//modules/common_msgs/basic_msgs:header_proto", + ], +) + apollo_package() diff --git a/modules/common_msgs/perception_msgs/perception_barrier_gate.proto b/modules/common_msgs/perception_msgs/perception_barrier_gate.proto new file mode 100644 index 0000000..7fe0be6 --- /dev/null +++ b/modules/common_msgs/perception_msgs/perception_barrier_gate.proto @@ -0,0 +1,33 @@ +syntax = "proto2"; + +package apollo.perception; + +import "modules/common_msgs/basic_msgs/header.proto"; + +message BarrierGate { + enum Status { + UNKNOWN = 0; + CLOSED = 1; + CLOSING = 2; + OPENED = 3; + OPENING = 4; + }; + optional Status status = 1; + + // Barrier gate string-ID in the map data. + optional string id = 2; + + // Barrier gate type in the map data. + optional string type = 3; + + // Wheter the barrier recognition is activated. + optional bool is_useable = 4 [default = false]; + + // Open percentage. + optional double open_percent = 5; +} + +message PerceptionBarrierGate { + optional apollo.common.Header header = 1; + repeated BarrierGate barrier_gates = 2; +} diff --git a/modules/common_msgs/perception_msgs/perception_obstacle.proto b/modules/common_msgs/perception_msgs/perception_obstacle.proto index 3798794..be3067c 100644 --- a/modules/common_msgs/perception_msgs/perception_obstacle.proto +++ b/modules/common_msgs/perception_msgs/perception_obstacle.proto @@ -157,6 +157,20 @@ message PerceptionObstacle { optional Source source = 27 [default = HOST_VEHICLE]; optional V2XInformation v2x_info = 28; + + enum SemanticType { + SM_UNKNOWN = 0; + SM_IGNORE = 1; + SM_GROUND = 2; + SM_OBJECT = 3; + SM_CURB = 4; + SM_VEGETATION = 5; + SM_FENCE = 6; + SM_NOISE = 7; + SM_WALL = 8; + SM_MAX_OBJECT_SEMANTIC_LABEL = 9; + }; + optional SemanticType semantic_type = 29; } message LaneMarker { @@ -186,10 +200,65 @@ message CIPVInfo { repeated int32 potential_cipv_id = 2; } +message PerceptionWaste { + optional int32 id = 1; + + optional apollo.common.Point3D position = 2; + optional double theta = 3; + optional apollo.common.Point3D velocity = 4; + optional double length = 5; + optional double width = 6; + optional double height = 7; + repeated apollo.common.Point3D polygon_point = 8; + optional double tracking_time = 9; + + enum Type { + UNKNOWN = 0; + CAN = 1; + CIGARETTE = 2; + CIGARETTE_CASE = 3; + PEEL = 4; + PACKAGE = 5; + PLASTIC_BAG = 6; + BOTTLES = 7; + SHELL = 8; + LEAF = 9; + PAPER_CUP = 10; + CUBE = 11; + WIRE = 12; + }; + optional Type type = 10; + + optional double timestamp = 11; + optional double confidence = 12; + optional BBox2D bbox2d = 13; + optional DebugMessage msg = 14; +} + message PerceptionObstacles { repeated PerceptionObstacle perception_obstacle = 1; // An array of obstacles optional apollo.common.Header header = 2; // Header optional apollo.common.ErrorCode error_code = 3 [default = OK]; optional LaneMarkers lane_marker = 4; optional CIPVInfo cipv_info = 5; // Closest In Path Vehicle (CIPV) + repeated PerceptionWaste perception_waste = 6; // An array of wastes +} + +message PerceptionEdgeInfo { + optional apollo.common.Header header = 1; + optional bool is_useable = 2 [default = false]; + repeated apollo.common.Point3D edge_point = 3; + repeated apollo.common.Point3D edge_relative_point = 4; + optional double delta_s = 5 [default = 0.2]; + optional double edge_length = 6; + optional bool is_smoother_succ = 7 [default = false]; + optional bool is_cross_localization = 8 [default = false]; } + +message PerceptionAccurateDockInfo { + optional apollo.common.Header header = 1; + optional bool is_useable = 2 [default = false]; + optional apollo.common.Point3D relative_position = 3; + repeated apollo.common.Point3D relative_path_position = 4; + optional double relative_heading = 5; +} \ No newline at end of file diff --git a/modules/common_msgs/perception_msgs/traffic_light_detection.proto b/modules/common_msgs/perception_msgs/traffic_light_detection.proto index 58b4925..baa0df4 100644 --- a/modules/common_msgs/perception_msgs/traffic_light_detection.proto +++ b/modules/common_msgs/perception_msgs/traffic_light_detection.proto @@ -68,4 +68,5 @@ message TrafficLightDetection { CAMERA_FRONT_WIDE = 3; }; optional CameraID camera_id = 5; + optional string camera_name = 6; } diff --git a/modules/common_msgs/planning_msgs/pad_msg.proto b/modules/common_msgs/planning_msgs/pad_msg.proto index c5f2374..ac7bd46 100644 --- a/modules/common_msgs/planning_msgs/pad_msg.proto +++ b/modules/common_msgs/planning_msgs/pad_msg.proto @@ -16,6 +16,10 @@ message PadMessage { STOP = 4; RESUME_CRUISE = 5; CLEAR_PLANNING = 6; + // Enter mission model + ENTER_MISSION = 7; + // Exit mission model + EXIT_MISSION = 8; }; // driving action diff --git a/modules/common_msgs/planning_msgs/planning.proto b/modules/common_msgs/planning_msgs/planning.proto index 95308a6..c4864a6 100644 --- a/modules/common_msgs/planning_msgs/planning.proto +++ b/modules/common_msgs/planning_msgs/planning.proto @@ -11,6 +11,22 @@ import "modules/common_msgs/map_msgs/map_id.proto"; import "modules/common_msgs/planning_msgs/decision.proto"; import "modules/common_msgs/planning_msgs/planning_internal.proto"; +message Point { + optional double x = 1; + optional double y = 2; +} + +message LocationPose { + //vehice location pose + optional Point vehice_location = 1; + + // left width point of vehice location + optional Point left_lane_boundary_point = 2; + + // right width SL point of vehice location + optional Point right_lane_boundary_point = 3; +} + message EStop { // is_estop == true when emergency stop is required optional bool is_estop = 1; @@ -107,6 +123,8 @@ message ADCTrajectory { SPEED_FALLBACK = 3; PATH_REUSED = 4; OPEN_SPACE = 5; + EDGE_FOLLOW = 6; + RELATIVE_CONTROL = 7; } optional TrajectoryType trajectory_type = 21 [default = UNKNOWN]; @@ -118,6 +136,13 @@ message ADCTrajectory { // complete dead end flag optional bool car_in_dead_end = 24; + // vehicle location pose + optional LocationPose location_pose = 25; + + // in RELATIVE_CONTROL trajectory type, if trajectory is collisioned with obstable + optional bool is_collision = 26 [default = false]; + // output related to RSS optional RSSInfo rss_info = 100; + } diff --git a/modules/common_msgs/prediction_msgs/prediction_obstacle.proto b/modules/common_msgs/prediction_msgs/prediction_obstacle.proto index a41cce9..0cd3db0 100644 --- a/modules/common_msgs/prediction_msgs/prediction_obstacle.proto +++ b/modules/common_msgs/prediction_msgs/prediction_obstacle.proto @@ -77,4 +77,7 @@ message PredictionObstacles { // Scenario optional Scenario scenario = 7; + + // waste + repeated apollo.perception.PerceptionWaste perception_waste = 8; } diff --git a/modules/common_msgs/sensor_msgs/BUILD b/modules/common_msgs/sensor_msgs/BUILD index 3183f75..fd9be42 100644 --- a/modules/common_msgs/sensor_msgs/BUILD +++ b/modules/common_msgs/sensor_msgs/BUILD @@ -60,6 +60,14 @@ proto_library( ], ) +proto_library( + name = "nano_radar_proto", + srcs = ["nano_radar.proto"], + deps = [ + "//modules/common_msgs/basic_msgs:header_proto", + ], +) + proto_library( name = "smartereye_proto", srcs = ["smartereye.proto"], diff --git a/modules/common_msgs/sensor_msgs/nano_radar.proto b/modules/common_msgs/sensor_msgs/nano_radar.proto new file mode 100755 index 0000000..03f0e8a --- /dev/null +++ b/modules/common_msgs/sensor_msgs/nano_radar.proto @@ -0,0 +1,146 @@ +syntax = "proto2"; + +package apollo.drivers; + +import "modules/common_msgs/basic_msgs/header.proto"; + +message NanoObjectListStatus_60A { + optional int32 nof_objects = 1 [default = 0]; + optional int32 meas_counter = 2 [default = -1]; + optional int32 interface_version = 3; +} + + + +message NanoRadarState_201 { + enum OutputType { + OUTPUT_TYPE_NONE = 0; + OUTPUT_TYPE_OBJECTS = 1; + OUTPUT_TYPE_CLUSTERS = 2; + OUTPUT_TYPE_ERROR = 3; + } + + enum RcsThreshold { + RCS_THRESHOLD_STANDARD = 0; + RCS_THRESHOLD_HIGH_SENSITIVITY = 1; + RCS_THRESHOLD_ERROR = 2; + } + + optional uint32 max_distance = 1; + optional uint32 radar_power = 2; + optional OutputType output_type = 3; + optional RcsThreshold rcs_threshold = 4; + optional bool send_quality = 5; + optional bool send_ext_info = 6; +} + +message NanoSoftwareVersion_700 { + optional uint32 soft_major_release = 1; + optional uint32 soft_minor_release = 2; + optional uint32 soft_patch_level = 3; +} + +message NanoCollisionDetectionRegionState_402 { + // x axis ^ + // | longitude_dist + // P2(Long2,Lat2) | + // ---------------------------------- + // | | | + // | | | + // | | | + // ---------------------------------- + // | P1(Long1,Lat1) + // | + // | lateral_dist + // ---------------------> + // y axis + // ooooooooooooo //radar front surface max:50m x 50m + optional uint32 region_id = 1; + optional uint32 region_max_output_number = 2; + optional double point1_longitude = 3; + optional double point1_lateral = 4; + optional double point2_longitude = 5; + optional double point2_lateral = 6; + optional bool coordinates_valid = 7; + optional bool activation_valid = 8; +} + +message NanoRadarObs { + // x axis ^ + // | longitude_dist + // | + // | + // | + // | lateral_dist + // | y axis + // -----------------> + // ooooooooooooo //radar front surface 77GHz + + optional apollo.common.Header header = 1; + optional bool clusterortrack = 2; // 0 = track, 1 = cluster + optional int32 obstacle_id = 3; // obstacle Id + // longitude distance to the radar; (+) = target far away the radar unit = m + optional double longitude_dist = 4; + // lateral distance to the radar; (+) = right; unit = m + optional double lateral_dist = 5; + // longitude velocity to the radar; (+) = forward; unit = m/s + optional double longitude_vel = 6; + // lateral velocity to the radar; (+) = right; unit = m/s + optional double lateral_vel = 7; + // obstacle Radar Cross-Section; unit = dBsm + optional double rcs = 8; + // 0 = moving, 1 = stationary, 2 = oncoming, 3 = stationary candidate + // 4 = unknown, 5 = crossing stationary, 6 = crossing moving, 7 = stopped + optional int32 dynprop = 9; + // longitude distance standard deviation to the radar; (+) = forward; unit = m + optional double longitude_dist_rms = 10; + // lateral distance standard deviation to the radar; (+) = left; unit = m + optional double lateral_dist_rms = 11; + // longitude velocity standard deviation to the radar; (+) = forward; unit = + // m/s + optional double longitude_vel_rms = 12; + // lateral velocity standard deviation to the radar; (+) = left; unit = m/s + optional double lateral_vel_rms = 13; + // obstacle probability of existence + optional double probexist = 14; + + // The following is only valid for the track object message + // 0 = deleted, 1 = new, 2 = measured, 3 = predicted, 4 = deleted for, 5 = new + // from merge + optional int32 meas_state = 15; + // longitude acceleration to the radar; (+) = forward; unit = m/s2 + optional double longitude_accel = 16; + // lateral acceleration to the radar; (+) = left; unit = m/s2 + optional double lateral_accel = 17; + // orientation angle to the radar; (+) = counterclockwise; unit = degree + optional double oritation_angle = 18; + // longitude acceleration standard deviation to the radar; (+) = forward; unit + // = m/s2 + optional double longitude_accel_rms = 19; + // lateral acceleration standard deviation to the radar; (+) = left; unit = + // m/s2 + optional double lateral_accel_rms = 20; + // orientation angle standard deviation to the radar; (+) = counterclockwise; + // unit = degree + optional double oritation_angle_rms = 21; + optional double length = 22; // obstacle length; unit = m + optional double width = 23; // obstacle width; unit = m + // 0: point; 1: car; 2: truck; 3: pedestrian; 4: motorcycle; 5: bicycle; 6: + // wide; 7: unknown + optional int32 obstacle_class = 24; + // Object Range + optional double obstacle_range = 25; + // Object Velocity + optional double obstacle_vel = 26; + // Object Angle + optional double obstacle_angle = 27; +} + +message NanoRadar { + optional apollo.common.Header header = 1; + repeated NanoRadarObs contiobs = 2; // conti radar obstacle array + optional NanoRadarState_201 radar_state = 3; + optional NanoCollisionDetectionRegionState_402 radar_region_state = 4; + optional NanoObjectListStatus_60A object_list_status = 6; + optional NanoSoftwareVersion_700 software_version = 7; +} diff --git a/modules/common_msgs/simulation_msgs/agent.proto b/modules/common_msgs/simulation_msgs/agent.proto index e17421f..e461f91 100644 --- a/modules/common_msgs/simulation_msgs/agent.proto +++ b/modules/common_msgs/simulation_msgs/agent.proto @@ -57,4 +57,21 @@ message AgentConfig { optional bool avoid_rear_end_collision = 17 [default = true]; optional double rear_end_collision_distance = 18 [default = 3.0, deprecated = true]; + + // When an obstacle approaches the adc at a certain distance, + // it needs to decelerate. + message NearCar { + optional double distance = 1 [default = 20]; + optional double acceleration = 2 [default = -2]; + optional bool is_same_lane = 3 [default = false]; + optional bool only_include_behind = 4 [default = true]; + } + optional NearCar near_car = 19; + + // Need to decelerate when an obstacle meets the crosswalk + message NearCrosswalk { + optional double distance = 1 [default = 15]; + optional double acceleration = 2 [default = -1]; + } + optional NearCrosswalk near_crosswalk = 22; } From c34ff749882130fee430e22c39de3c8d3fe38680 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 14 Dec 2024 12:27:52 +0800 Subject: [PATCH 06/14] chore(version): update version --- CMakeLists.txt | 2 +- README.md | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbfe81d..3b1c5a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5.1) -project(cyber VERSION 9.0.0) # Apollo Version +project(cyber VERSION 10.0.0) # Apollo Version set(CMAKE_CXX_STANDARD 14) set(TARGET_NAME ${PROJECT_NAME}) diff --git a/README.md b/README.md index 4536135..252607e 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -# Apollo(v9.0.0) CyberRT +# Apollo(v10.0.0) CyberRT ![CyberRT](./docs/CyberRT.gif) | Target | CI Status | | ------------- | :-----:| -| Ubuntu18.04 x86_64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-v9.0.0-build.yaml) | -| Ubuntu20.04 x86_64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-v9.0.0-build.yaml) | -| Ubuntu22.04 x86_64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-v9.0.0-build.yaml) | -| Ubuntu24.04 x86_64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu24-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu24-v9.0.0-build.yaml) | -| Ubuntu latest x86_64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-v9.0.0-build.yaml) | -| Ubuntu18.04 arrch64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-arrch64-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-arrch64-v9.0.0-build.yaml) | -| Ubuntu20.04 arrch64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-arrch64-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-arrch64-v9.0.0-build.yaml) | -| Ubuntu22.04 arrch64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-arrch64-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-arrch64-v9.0.0-build.yaml) | -| Ubuntu latest arrch64 | [![build v9.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-arrch64-v9.0.0-build.yaml/badge.svg?branch=v9.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-arrch64-v9.0.0-build.yaml) | +| Ubuntu18.04 x86_64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-v10.0.0-build.yaml) | +| Ubuntu20.04 x86_64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-v10.0.0-build.yaml) | +| Ubuntu22.04 x86_64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-v10.0.0-build.yaml) | +| Ubuntu24.04 x86_64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu24-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu24-v10.0.0-build.yaml) | +| Ubuntu latest x86_64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-v10.0.0-build.yaml) | +| Ubuntu18.04 arrch64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-arrch64-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu18-arrch64-v10.0.0-build.yaml) | +| Ubuntu20.04 arrch64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-arrch64-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu20-arrch64-v10.0.0-build.yaml) | +| Ubuntu22.04 arrch64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-arrch64-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu22-arrch64-v10.0.0-build.yaml) | +| Ubuntu latest arrch64 | [![build v10.0.0](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-arrch64-v10.0.0-build.yaml/badge.svg?branch=v10.0.0)](https://github.com/minhanghuang/CyberRT/actions/workflows/ubuntu-latest-arrch64-v10.0.0-build.yaml) | ## #1 Env @@ -29,7 +29,7 @@ python3 -m pip install protobuf==3.14.0 1. clone ```shell -git clone --single-branch --branch v9.0.0 https://github.com/minhanghuang/CyberRT.git +git clone --single-branch --branch v10.0.0 https://github.com/minhanghuang/CyberRT.git cd CyberRT ``` From 30ee0304ef48dab6b66002ec6c5a69fe17f37bb1 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 14 Dec 2024 12:46:23 +0800 Subject: [PATCH 07/14] chore: add v10 diff file --- diffs/v10/common_msgs.patch | 934 ++ diffs/v10/cyber.patch | 19124 ++++++++++++++++++++++++++++++++++ 2 files changed, 20058 insertions(+) create mode 100644 diffs/v10/common_msgs.patch create mode 100644 diffs/v10/cyber.patch diff --git a/diffs/v10/common_msgs.patch b/diffs/v10/common_msgs.patch new file mode 100644 index 0000000..8648e67 --- /dev/null +++ b/diffs/v10/common_msgs.patch @@ -0,0 +1,934 @@ +diff --git a/modules/common_msgs/basic_msgs/pnc_point.proto b/modules/common_msgs/basic_msgs/pnc_point.proto +index cf948f5..f8cff2c 100644 +--- a/modules/common_msgs/basic_msgs/pnc_point.proto ++++ b/modules/common_msgs/basic_msgs/pnc_point.proto +@@ -74,6 +74,7 @@ message TrajectoryPoint { + + // Gaussian probability information + optional GaussianInfo gaussian_info = 7; ++ + } + + message Trajectory { +diff --git a/modules/common_msgs/chassis_msgs/chassis.proto b/modules/common_msgs/chassis_msgs/chassis.proto +index 77e9fb7..d4ab806 100644 +--- a/modules/common_msgs/chassis_msgs/chassis.proto ++++ b/modules/common_msgs/chassis_msgs/chassis.proto +@@ -35,6 +35,7 @@ message Chassis { + CHASSIS_ERROR_ON_BRAKE = 7; + CHASSIS_ERROR_ON_THROTTLE = 8; + CHASSIS_ERROR_ON_GEAR = 9; ++ CHASSIS_CAN_LOST = 10; + + MANUAL_INTERVENTION = 3; // human manual intervention + +diff --git a/modules/common_msgs/control_msgs/BUILD b/modules/common_msgs/control_msgs/BUILD +index 2f12fee..e17a1b2 100644 +--- a/modules/common_msgs/control_msgs/BUILD ++++ b/modules/common_msgs/control_msgs/BUILD +@@ -19,6 +19,14 @@ proto_library( + ], + ) + ++proto_library( ++ name = "control_interactive_msg_proto", ++ srcs = ["control_interactive_msg.proto"], ++ deps = [ ++ "//modules/common_msgs/basic_msgs:header_proto", ++ ], ++) ++ + proto_library( + name = "control_pad_msg_proto", + srcs = ["pad_msg.proto"], +diff --git a/modules/common_msgs/control_msgs/control_cmd.proto b/modules/common_msgs/control_msgs/control_cmd.proto +index 7559675..87c3ce8 100644 +--- a/modules/common_msgs/control_msgs/control_cmd.proto ++++ b/modules/common_msgs/control_msgs/control_cmd.proto +@@ -38,7 +38,7 @@ message ControlCommand { + // target steering angle, in percentage of full scale [-100, 100] + optional double steering_target = 7; + +- // parking brake engage. true: engaged ++ // parking brake engage. true: engaged epd brake + optional bool parking_brake = 8; + + // target speed, in m/s +@@ -171,6 +171,9 @@ message SimpleLateralDebug { + // Mrac control status and feedback states for steer control + optional MracDebug steer_mrac_debug = 32; + optional bool steer_mrac_enable_status = 33; ++ ++ // lat acc in ENU, in m/s^2 ++ optional double lateral_centripetal_acceleration = 34; + } + + message SimpleMPCDebug { +diff --git a/modules/common_msgs/control_msgs/control_interactive_msg.proto b/modules/common_msgs/control_msgs/control_interactive_msg.proto +new file mode 100644 +index 0000000..159a458 +--- /dev/null ++++ b/modules/common_msgs/control_msgs/control_interactive_msg.proto +@@ -0,0 +1,17 @@ ++syntax = "proto2"; ++package apollo.control; ++ ++import "modules/common_msgs/basic_msgs/header.proto"; ++ ++message ControlInteractiveMsg { ++ optional apollo.common.Header header = 1; // common header ++ optional bool replan_request = 2; // request replan. true: need replan, false: don't need replan ++ optional ReplanRequestReasonCode replan_req_reason_code = 3; // request replan reason code ++ optional string replan_request_reason = 4; // request replan reason ++} ++ ++enum ReplanRequestReasonCode { ++ REPLAN_REQ_ALL_REPLAN = 1; ++ REPLAN_REQ_STATION_REPLAN = 2; ++ REPLAN_REQ_SPEED_REPLAN = 3; ++} +diff --git a/modules/common_msgs/dreamview_msgs/hmi_config.proto b/modules/common_msgs/dreamview_msgs/hmi_config.proto +index 9e373d4..44c4b9b 100644 +--- a/modules/common_msgs/dreamview_msgs/hmi_config.proto ++++ b/modules/common_msgs/dreamview_msgs/hmi_config.proto +@@ -34,6 +34,7 @@ enum HMIAction { + LOAD_RTK_RECORDS = 25; // Load all rtk records + CHANGE_RTK_RECORD = 26; // change rtk records + LOAD_RECORD = 27; // Load record ++ LOAD_MAPS = 28; // Load maps + } + + message HMIConfig { +diff --git a/modules/common_msgs/dreamview_msgs/hmi_mode.proto b/modules/common_msgs/dreamview_msgs/hmi_mode.proto +index aef7cde..09354ba 100644 +--- a/modules/common_msgs/dreamview_msgs/hmi_mode.proto ++++ b/modules/common_msgs/dreamview_msgs/hmi_mode.proto +@@ -118,6 +118,14 @@ message CyberModule { + optional string process_group = 3; + } + ++message Layout { ++ optional string type = 1; ++ optional Layout first = 2; ++ optional Layout second = 3; ++ optional string direction = 4; ++ optional double splitPercentage = 5 [default = 50.0]; ++} ++ + message HMIMode { + map cyber_modules = 1; + map modules = 2; +@@ -125,6 +133,6 @@ message HMIMode { + map other_components = 4; + repeated HMIModeOperation operations = 5; + optional HMIModeOperation default_operation = 6; +- optional string layout = 7; ++ optional Layout layout = 7; + map global_components = 8; + } +diff --git a/modules/common_msgs/dreamview_msgs/simulation_world.proto b/modules/common_msgs/dreamview_msgs/simulation_world.proto +index 089ae9b..a1c8218 100644 +--- a/modules/common_msgs/dreamview_msgs/simulation_world.proto ++++ b/modules/common_msgs/dreamview_msgs/simulation_world.proto +@@ -197,6 +197,8 @@ message MapElementIds { + repeated string parking_space = 10; + repeated string speed_bump = 11; + repeated string pnc_junction = 12; ++ repeated string ad_area = 13; ++ repeated string barrier_gate = 14; + } + + message ControlData { +diff --git a/modules/common_msgs/external_command_msgs/BUILD b/modules/common_msgs/external_command_msgs/BUILD +index 830d0e8..fab1d33 100644 +--- a/modules/common_msgs/external_command_msgs/BUILD ++++ b/modules/common_msgs/external_command_msgs/BUILD +@@ -4,6 +4,15 @@ load("//tools:apollo_package.bzl", "apollo_package") + + package(default_visibility = ["//visibility:public"]) + ++proto_library( ++ name = "precise_parking_command_proto", ++ srcs = ["precise_parking_command.proto"], ++ deps = [ ++ ":external_geometry_proto", ++ "//modules/common_msgs/basic_msgs:header_proto", ++ ], ++) ++ + proto_library( + name = "valet_parking_command_proto", + srcs = ["valet_parking_command.proto"], +@@ -60,6 +69,15 @@ proto_library( + ], + ) + ++proto_library( ++ name = "zone_cover_command_proto", ++ srcs = ["zone_cover_command.proto"], ++ deps = [ ++ ":external_geometry_proto", ++ "//modules/common_msgs/basic_msgs:header_proto", ++ ], ++) ++ + proto_library( + name = "speed_command_proto", + srcs = ["speed_command.proto"], +diff --git a/modules/common_msgs/external_command_msgs/action_command.proto b/modules/common_msgs/external_command_msgs/action_command.proto +index 6e52ed8..89bc1f7 100644 +--- a/modules/common_msgs/external_command_msgs/action_command.proto ++++ b/modules/common_msgs/external_command_msgs/action_command.proto +@@ -25,6 +25,10 @@ enum ActionCommandType { + SWITCH_TO_AUTO = 51; + // Varify vin code of vehicle. + VIN_REQ = 52; ++ // Enter mission model ++ ENTER_MISSION = 53; ++ // Exit mission model ++ EXIT_MISSION = 54; + } + + message ActionCommand { +diff --git a/modules/common_msgs/external_command_msgs/precise_parking_command.proto b/modules/common_msgs/external_command_msgs/precise_parking_command.proto +new file mode 100644 +index 0000000..212dd29 +--- /dev/null ++++ b/modules/common_msgs/external_command_msgs/precise_parking_command.proto +@@ -0,0 +1,26 @@ ++syntax = "proto2"; ++ ++package apollo.external_command; ++ ++import "modules/common_msgs/basic_msgs/header.proto"; ++import "modules/common_msgs/external_command_msgs/geometry.proto"; ++ ++enum PreciseMissionType { ++ CHARGE = 0; ++ DUMP = 1; ++} ++ ++message PreciseParkingCommand { ++ optional apollo.common.Header header = 1; ++ // Unique identification for command. ++ optional int64 command_id = 2 [default = -1]; ++ // If the start pose is set as the first point of "way_point". ++ optional bool is_start_pose_set = 3 [default = false]; ++ // Pose of the parking spot. ++ required Pose parking_spot_pose = 4; ++ // true: parking inwards, false: parking outwards ++ required bool parking_inwards = 5; ++ required PreciseMissionType mission_type = 6; ++ // not given, the default target speed of system will be used. ++ optional double target_speed = 7; ++} +\ No newline at end of file +diff --git a/modules/common_msgs/external_command_msgs/zone_cover_command.proto b/modules/common_msgs/external_command_msgs/zone_cover_command.proto +new file mode 100644 +index 0000000..f206305 +--- /dev/null ++++ b/modules/common_msgs/external_command_msgs/zone_cover_command.proto +@@ -0,0 +1,16 @@ ++syntax = "proto2"; ++ ++package apollo.external_command; ++ ++import "modules/common_msgs/basic_msgs/header.proto"; ++import "modules/common_msgs/external_command_msgs/geometry.proto"; ++ ++message ZoneCoverCommand { ++ optional apollo.common.Header header = 1; ++ // Unique identification for command. ++ optional int64 command_id = 2 [default = -1]; ++ required string overlap_id = 3; ++ optional double target_speed = 4; ++ repeated RoiPolygon non_drivable_roi = 5; ++ optional RoiPolygon drivable_roi = 6; ++} +diff --git a/modules/common_msgs/localization_msgs/localization_status.proto b/modules/common_msgs/localization_msgs/localization_status.proto +index d852c31..11d3db7 100644 +--- a/modules/common_msgs/localization_msgs/localization_status.proto ++++ b/modules/common_msgs/localization_msgs/localization_status.proto +@@ -155,6 +155,7 @@ enum MsfRunningStatus { + MSF_NOSOL_X_XX = 22; + MSF_NOSOL_X_XXX = 23; + MSF_RUNNING_INIT = 24; ++ MSF_REINIT_ABNORMALLY = 25; + } + + // The status of sensor msg +@@ -164,12 +165,76 @@ message MsfSensorMsgStatus { + optional ImuMsgDataStatus imu_data_status = 3; + } + ++// The init pose source ++enum MsfInitPoseSource { ++ UNKNOWN_SOURCE = 0; ++ GNSS_HEADING = 1; ++ LOCAL_SEARCH_FROM_INTEGPVA = 2; ++ LOCAL_SEARCH_FROM_FILE = 3; ++ LOCAL_UPDATE_FROM_FILE = 4; ++ USER_INTERACTION = 5; ++ INSPVA_RECORD = 6; ++ GNSS_VELOCITY = 7; ++ GLOBAL_LIDAR = 8; ++} ++ ++// The status of gnss map offset ++enum MsfGnssMapOffsetStatus { ++ MSF_LOCAL_GNSS_MAP_OFFSET_NORMAL = 0; ++ MSF_LOCAL_GNSS_MAP_OFFSET_ABNORMAL = 1; ++} ++ ++// The gnss map offset ++message MsfGnssMapOffset { ++ optional MsfGnssMapOffsetStatus status = 1; ++ optional double offsetx = 2; ++ optional double offsety = 3; ++} ++ ++// The init pose status ++enum MsfInitPoseStatus { ++ INIT_WAITING = 0; ++ INIT_DOING = 1; ++ INIT_SUCCESSFUL = 2; ++ INIT_FAILED = 3; ++ INIT_TERMINATED = 4; ++} ++ ++// The init details ++message MsfInitDetails { ++ optional MsfInitPoseSource init_pose_source = 1; ++ optional MsfInitPoseStatus local_search_from_integpva_status = 2; ++ optional MsfInitPoseStatus local_search_from_file_status = 3; ++ optional MsfInitPoseStatus local_update_from_file_status = 4; ++ optional MsfInitPoseStatus user_interaction_status = 5; ++ optional int32 gnss_position_type = 6; ++ optional MsfInitPoseStatus local_from_global_lidar_status = 7; ++} ++ ++// The initializaiton status of localization module ++enum MSFInitStatus { ++ MSF_INIT = 0; ++ MSF_ALIGNING = 1; ++ MSF_ALIGNED_INIT = 2; ++ MSF_ALIGNED_CONVERGED = 3; ++ MSF_ALIGNED_CONVERGING = 4; ++ MSF_ALIGNED_GOOD = 5; ++ MSF_ALIGNED_VALID = 6; ++} ++ + // The status of msf localization module + message MsfStatus { + optional LocalLidarConsistency local_lidar_consistency = 1; + optional GnssConsistency gnss_consistency = 2; + optional LocalLidarStatus local_lidar_status = 3; +- optional LocalLidarQuality local_lidar_quality = 4; +- optional GnssPositionType gnsspos_position_type = 5; +- optional MsfRunningStatus msf_running_status = 6; ++ optional GnssPositionType gnsspos_position_type = 4; ++ optional uint32 heading_position_type = 5; ++ optional MSFInitStatus msf_init_status = 6; ++ optional MsfRunningStatus msf_running_status = 7; ++ optional MsfInitDetails msf_init_details = 8; ++ optional LocalLidarQuality local_lidar_quality = 9; ++ optional MsfGnssMapOffset gnss_map_offset = 10; ++ optional bool lidar_alt_from_map = 11; ++ optional double local_lidar_score = 12; ++ optional bool local_reliability_status = 13 [default = false]; + } +diff --git a/modules/common_msgs/map_msgs/BUILD b/modules/common_msgs/map_msgs/BUILD +index 3dc0bb6..f61b8fe 100644 +--- a/modules/common_msgs/map_msgs/BUILD ++++ b/modules/common_msgs/map_msgs/BUILD +@@ -96,6 +96,8 @@ proto_library( + ":map_speed_bump_proto", + ":map_stop_sign_proto", + ":map_yield_sign_proto", ++ ":map_area_proto", ++ ":map_barrier_gate_proto", + ], + ) + +@@ -162,4 +164,24 @@ proto_library( + ], + ) + ++proto_library( ++ name = "map_area_proto", ++ srcs = ["map_area.proto"], ++ deps = [ ++ ":map_geometry_proto", ++ ":map_id_proto", ++ "//modules/common_msgs/basic_msgs:geometry_proto", ++ ], ++) ++ ++proto_library( ++ name = "map_barrier_gate_proto", ++ srcs = ["map_barrier_gate.proto"], ++ deps = [ ++ ":map_geometry_proto", ++ ":map_id_proto", ++ "//modules/common_msgs/basic_msgs:geometry_proto", ++ ], ++) ++ + apollo_package() +diff --git a/modules/common_msgs/map_msgs/map.proto b/modules/common_msgs/map_msgs/map.proto +index 77e6c0d..f303962 100644 +--- a/modules/common_msgs/map_msgs/map.proto ++++ b/modules/common_msgs/map_msgs/map.proto +@@ -15,6 +15,8 @@ import "modules/common_msgs/map_msgs/map_signal.proto"; + import "modules/common_msgs/map_msgs/map_speed_bump.proto"; + import "modules/common_msgs/map_msgs/map_stop_sign.proto"; + import "modules/common_msgs/map_msgs/map_yield_sign.proto"; ++import "modules/common_msgs/map_msgs/map_area.proto"; ++import "modules/common_msgs/map_msgs/map_barrier_gate.proto"; + + // This message defines how we project the ellipsoidal Earth surface to a plane. + message Projection { +@@ -55,4 +57,6 @@ message Map { + repeated ParkingSpace parking_space = 12; + repeated PNCJunction pnc_junction = 13; + repeated RSU rsu = 14; ++ repeated Area ad_area = 15; ++ repeated BarrierGate barrier_gate = 16; + } +diff --git a/modules/common_msgs/map_msgs/map_area.proto b/modules/common_msgs/map_msgs/map_area.proto +new file mode 100644 +index 0000000..0087595 +--- /dev/null ++++ b/modules/common_msgs/map_msgs/map_area.proto +@@ -0,0 +1,22 @@ ++syntax = "proto2"; ++ ++package apollo.hdmap; ++ ++import "modules/common_msgs/map_msgs/map_geometry.proto"; ++import "modules/common_msgs/map_msgs/map_id.proto"; ++ ++message Area { ++ enum Type { ++ Driveable = 1; ++ UnDriveable = 2; ++ Custom1 = 3; ++ Custom2 = 4; ++ Custom3 = 5; ++ }; ++ ++ required Id id = 1; ++ optional Type type = 2; ++ required Polygon polygon = 3; ++ repeated Id overlap_id = 4; ++ optional string name = 5; ++} +diff --git a/modules/common_msgs/map_msgs/map_barrier_gate.proto b/modules/common_msgs/map_msgs/map_barrier_gate.proto +new file mode 100644 +index 0000000..f7a5a0e +--- /dev/null ++++ b/modules/common_msgs/map_msgs/map_barrier_gate.proto +@@ -0,0 +1,22 @@ ++syntax = "proto2"; ++ ++package apollo.hdmap; ++ ++import "modules/common_msgs/map_msgs/map_geometry.proto"; ++import "modules/common_msgs/map_msgs/map_id.proto"; ++ ++message BarrierGate { ++ enum BarrierGateType { ++ ROD = 1; ++ FENCE = 2; ++ ADVERTISING = 3; ++ TELESCOPIC = 4; ++ OTHER = 5; ++ }; ++ ++ required Id id = 1; ++ optional BarrierGateType type = 2; ++ optional Polygon polygon = 3; ++ repeated Curve stop_line = 4; ++ repeated Id overlap_id = 5; ++} +\ No newline at end of file +diff --git a/modules/common_msgs/map_msgs/map_lane.proto b/modules/common_msgs/map_msgs/map_lane.proto +index a78cd73..01483b1 100644 +--- a/modules/common_msgs/map_msgs/map_lane.proto ++++ b/modules/common_msgs/map_msgs/map_lane.proto +@@ -74,6 +74,7 @@ message Lane { + SIDEWALK = 4; + PARKING = 5; + SHOULDER = 6; ++ SHARED = 7; + }; + optional LaneType type = 12; + +diff --git a/modules/common_msgs/map_msgs/map_overlap.proto b/modules/common_msgs/map_msgs/map_overlap.proto +index 25509ff..003bb3b 100644 +--- a/modules/common_msgs/map_msgs/map_overlap.proto ++++ b/modules/common_msgs/map_msgs/map_overlap.proto +@@ -35,6 +35,10 @@ message PNCJunctionOverlapInfo {} + + message RSUOverlapInfo {} + ++message AreaOverlapInfo {} ++ ++message BarrierGateOverlapInfo {} ++ + message RegionOverlapInfo { + optional Id id = 1; + repeated Polygon polygon = 2; +@@ -56,6 +60,8 @@ message ObjectOverlapInfo { + ParkingSpaceOverlapInfo parking_space_overlap_info = 11; + PNCJunctionOverlapInfo pnc_junction_overlap_info = 12; + RSUOverlapInfo rsu_overlap_info = 13; ++ AreaOverlapInfo area_overlap_info = 14; ++ BarrierGateOverlapInfo barrier_gate_overlap_info = 15; + } + } + +diff --git a/modules/common_msgs/monitor_msgs/monitor_log.proto b/modules/common_msgs/monitor_msgs/monitor_log.proto +index 6bdf459..8d8a360 100644 +--- a/modules/common_msgs/monitor_msgs/monitor_log.proto ++++ b/modules/common_msgs/monitor_msgs/monitor_log.proto +@@ -27,6 +27,7 @@ message MonitorMessageItem { + DELPHI_ESR = 19; + STORYTELLING = 20; + TASK_MANAGER = 21; ++ NANO_RADAR = 22; + } + + optional MessageSource source = 1 [default = UNKNOWN]; +diff --git a/modules/common_msgs/perception_msgs/BUILD b/modules/common_msgs/perception_msgs/BUILD +index a5f9d7c..e29f330 100644 +--- a/modules/common_msgs/perception_msgs/BUILD ++++ b/modules/common_msgs/perception_msgs/BUILD +@@ -53,4 +53,12 @@ proto_library( + ], + ) + ++proto_library( ++ name = "perception_barrier_gate_proto", ++ srcs = ["perception_barrier_gate.proto"], ++ deps = [ ++ "//modules/common_msgs/basic_msgs:header_proto", ++ ], ++) ++ + apollo_package() +diff --git a/modules/common_msgs/perception_msgs/perception_barrier_gate.proto b/modules/common_msgs/perception_msgs/perception_barrier_gate.proto +new file mode 100644 +index 0000000..7fe0be6 +--- /dev/null ++++ b/modules/common_msgs/perception_msgs/perception_barrier_gate.proto +@@ -0,0 +1,33 @@ ++syntax = "proto2"; ++ ++package apollo.perception; ++ ++import "modules/common_msgs/basic_msgs/header.proto"; ++ ++message BarrierGate { ++ enum Status { ++ UNKNOWN = 0; ++ CLOSED = 1; ++ CLOSING = 2; ++ OPENED = 3; ++ OPENING = 4; ++ }; ++ optional Status status = 1; ++ ++ // Barrier gate string-ID in the map data. ++ optional string id = 2; ++ ++ // Barrier gate type in the map data. ++ optional string type = 3; ++ ++ // Wheter the barrier recognition is activated. ++ optional bool is_useable = 4 [default = false]; ++ ++ // Open percentage. ++ optional double open_percent = 5; ++} ++ ++message PerceptionBarrierGate { ++ optional apollo.common.Header header = 1; ++ repeated BarrierGate barrier_gates = 2; ++} +diff --git a/modules/common_msgs/perception_msgs/perception_obstacle.proto b/modules/common_msgs/perception_msgs/perception_obstacle.proto +index 3798794..be3067c 100644 +--- a/modules/common_msgs/perception_msgs/perception_obstacle.proto ++++ b/modules/common_msgs/perception_msgs/perception_obstacle.proto +@@ -157,6 +157,20 @@ message PerceptionObstacle { + + optional Source source = 27 [default = HOST_VEHICLE]; + optional V2XInformation v2x_info = 28; ++ ++ enum SemanticType { ++ SM_UNKNOWN = 0; ++ SM_IGNORE = 1; ++ SM_GROUND = 2; ++ SM_OBJECT = 3; ++ SM_CURB = 4; ++ SM_VEGETATION = 5; ++ SM_FENCE = 6; ++ SM_NOISE = 7; ++ SM_WALL = 8; ++ SM_MAX_OBJECT_SEMANTIC_LABEL = 9; ++ }; ++ optional SemanticType semantic_type = 29; + } + + message LaneMarker { +@@ -186,10 +200,65 @@ message CIPVInfo { + repeated int32 potential_cipv_id = 2; + } + ++message PerceptionWaste { ++ optional int32 id = 1; ++ ++ optional apollo.common.Point3D position = 2; ++ optional double theta = 3; ++ optional apollo.common.Point3D velocity = 4; ++ optional double length = 5; ++ optional double width = 6; ++ optional double height = 7; ++ repeated apollo.common.Point3D polygon_point = 8; ++ optional double tracking_time = 9; ++ ++ enum Type { ++ UNKNOWN = 0; ++ CAN = 1; ++ CIGARETTE = 2; ++ CIGARETTE_CASE = 3; ++ PEEL = 4; ++ PACKAGE = 5; ++ PLASTIC_BAG = 6; ++ BOTTLES = 7; ++ SHELL = 8; ++ LEAF = 9; ++ PAPER_CUP = 10; ++ CUBE = 11; ++ WIRE = 12; ++ }; ++ optional Type type = 10; ++ ++ optional double timestamp = 11; ++ optional double confidence = 12; ++ optional BBox2D bbox2d = 13; ++ optional DebugMessage msg = 14; ++} ++ + message PerceptionObstacles { + repeated PerceptionObstacle perception_obstacle = 1; // An array of obstacles + optional apollo.common.Header header = 2; // Header + optional apollo.common.ErrorCode error_code = 3 [default = OK]; + optional LaneMarkers lane_marker = 4; + optional CIPVInfo cipv_info = 5; // Closest In Path Vehicle (CIPV) ++ repeated PerceptionWaste perception_waste = 6; // An array of wastes ++} ++ ++message PerceptionEdgeInfo { ++ optional apollo.common.Header header = 1; ++ optional bool is_useable = 2 [default = false]; ++ repeated apollo.common.Point3D edge_point = 3; ++ repeated apollo.common.Point3D edge_relative_point = 4; ++ optional double delta_s = 5 [default = 0.2]; ++ optional double edge_length = 6; ++ optional bool is_smoother_succ = 7 [default = false]; ++ optional bool is_cross_localization = 8 [default = false]; + } ++ ++message PerceptionAccurateDockInfo { ++ optional apollo.common.Header header = 1; ++ optional bool is_useable = 2 [default = false]; ++ optional apollo.common.Point3D relative_position = 3; ++ repeated apollo.common.Point3D relative_path_position = 4; ++ optional double relative_heading = 5; ++} +\ No newline at end of file +diff --git a/modules/common_msgs/perception_msgs/traffic_light_detection.proto b/modules/common_msgs/perception_msgs/traffic_light_detection.proto +index 58b4925..baa0df4 100644 +--- a/modules/common_msgs/perception_msgs/traffic_light_detection.proto ++++ b/modules/common_msgs/perception_msgs/traffic_light_detection.proto +@@ -68,4 +68,5 @@ message TrafficLightDetection { + CAMERA_FRONT_WIDE = 3; + }; + optional CameraID camera_id = 5; ++ optional string camera_name = 6; + } +diff --git a/modules/common_msgs/planning_msgs/pad_msg.proto b/modules/common_msgs/planning_msgs/pad_msg.proto +index c5f2374..ac7bd46 100644 +--- a/modules/common_msgs/planning_msgs/pad_msg.proto ++++ b/modules/common_msgs/planning_msgs/pad_msg.proto +@@ -16,6 +16,10 @@ message PadMessage { + STOP = 4; + RESUME_CRUISE = 5; + CLEAR_PLANNING = 6; ++ // Enter mission model ++ ENTER_MISSION = 7; ++ // Exit mission model ++ EXIT_MISSION = 8; + }; + + // driving action +diff --git a/modules/common_msgs/planning_msgs/planning.proto b/modules/common_msgs/planning_msgs/planning.proto +index 95308a6..c4864a6 100644 +--- a/modules/common_msgs/planning_msgs/planning.proto ++++ b/modules/common_msgs/planning_msgs/planning.proto +@@ -11,6 +11,22 @@ import "modules/common_msgs/map_msgs/map_id.proto"; + import "modules/common_msgs/planning_msgs/decision.proto"; + import "modules/common_msgs/planning_msgs/planning_internal.proto"; + ++message Point { ++ optional double x = 1; ++ optional double y = 2; ++} ++ ++message LocationPose { ++ //vehice location pose ++ optional Point vehice_location = 1; ++ ++ // left width point of vehice location ++ optional Point left_lane_boundary_point = 2; ++ ++ // right width SL point of vehice location ++ optional Point right_lane_boundary_point = 3; ++} ++ + message EStop { + // is_estop == true when emergency stop is required + optional bool is_estop = 1; +@@ -107,6 +123,8 @@ message ADCTrajectory { + SPEED_FALLBACK = 3; + PATH_REUSED = 4; + OPEN_SPACE = 5; ++ EDGE_FOLLOW = 6; ++ RELATIVE_CONTROL = 7; + } + optional TrajectoryType trajectory_type = 21 [default = UNKNOWN]; + +@@ -118,6 +136,13 @@ message ADCTrajectory { + // complete dead end flag + optional bool car_in_dead_end = 24; + ++ // vehicle location pose ++ optional LocationPose location_pose = 25; ++ ++ // in RELATIVE_CONTROL trajectory type, if trajectory is collisioned with obstable ++ optional bool is_collision = 26 [default = false]; ++ + // output related to RSS + optional RSSInfo rss_info = 100; ++ + } +diff --git a/modules/common_msgs/prediction_msgs/prediction_obstacle.proto b/modules/common_msgs/prediction_msgs/prediction_obstacle.proto +index a41cce9..0cd3db0 100644 +--- a/modules/common_msgs/prediction_msgs/prediction_obstacle.proto ++++ b/modules/common_msgs/prediction_msgs/prediction_obstacle.proto +@@ -77,4 +77,7 @@ message PredictionObstacles { + + // Scenario + optional Scenario scenario = 7; ++ ++ // waste ++ repeated apollo.perception.PerceptionWaste perception_waste = 8; + } +diff --git a/modules/common_msgs/sensor_msgs/BUILD b/modules/common_msgs/sensor_msgs/BUILD +index 3183f75..fd9be42 100644 +--- a/modules/common_msgs/sensor_msgs/BUILD ++++ b/modules/common_msgs/sensor_msgs/BUILD +@@ -60,6 +60,14 @@ proto_library( + ], + ) + ++proto_library( ++ name = "nano_radar_proto", ++ srcs = ["nano_radar.proto"], ++ deps = [ ++ "//modules/common_msgs/basic_msgs:header_proto", ++ ], ++) ++ + proto_library( + name = "smartereye_proto", + srcs = ["smartereye.proto"], +diff --git a/modules/common_msgs/sensor_msgs/nano_radar.proto b/modules/common_msgs/sensor_msgs/nano_radar.proto +new file mode 100755 +index 0000000..03f0e8a +--- /dev/null ++++ b/modules/common_msgs/sensor_msgs/nano_radar.proto +@@ -0,0 +1,146 @@ ++syntax = "proto2"; ++ ++package apollo.drivers; ++ ++import "modules/common_msgs/basic_msgs/header.proto"; ++ ++message NanoObjectListStatus_60A { ++ optional int32 nof_objects = 1 [default = 0]; ++ optional int32 meas_counter = 2 [default = -1]; ++ optional int32 interface_version = 3; ++} ++ ++ ++ ++message NanoRadarState_201 { ++ enum OutputType { ++ OUTPUT_TYPE_NONE = 0; ++ OUTPUT_TYPE_OBJECTS = 1; ++ OUTPUT_TYPE_CLUSTERS = 2; ++ OUTPUT_TYPE_ERROR = 3; ++ } ++ ++ enum RcsThreshold { ++ RCS_THRESHOLD_STANDARD = 0; ++ RCS_THRESHOLD_HIGH_SENSITIVITY = 1; ++ RCS_THRESHOLD_ERROR = 2; ++ } ++ ++ optional uint32 max_distance = 1; ++ optional uint32 radar_power = 2; ++ optional OutputType output_type = 3; ++ optional RcsThreshold rcs_threshold = 4; ++ optional bool send_quality = 5; ++ optional bool send_ext_info = 6; ++} ++ ++message NanoSoftwareVersion_700 { ++ optional uint32 soft_major_release = 1; ++ optional uint32 soft_minor_release = 2; ++ optional uint32 soft_patch_level = 3; ++} ++ ++message NanoCollisionDetectionRegionState_402 { ++ // x axis ^ ++ // | longitude_dist ++ // P2(Long2,Lat2) | ++ // ---------------------------------- ++ // | | | ++ // | | | ++ // | | | ++ // ---------------------------------- ++ // | P1(Long1,Lat1) ++ // | ++ // | lateral_dist ++ // ---------------------> ++ // y axis ++ // ooooooooooooo //radar front surface max:50m x 50m ++ optional uint32 region_id = 1; ++ optional uint32 region_max_output_number = 2; ++ optional double point1_longitude = 3; ++ optional double point1_lateral = 4; ++ optional double point2_longitude = 5; ++ optional double point2_lateral = 6; ++ optional bool coordinates_valid = 7; ++ optional bool activation_valid = 8; ++} ++ ++message NanoRadarObs { ++ // x axis ^ ++ // | longitude_dist ++ // | ++ // | ++ // | ++ // | lateral_dist ++ // | y axis ++ // -----------------> ++ // ooooooooooooo //radar front surface 77GHz ++ ++ optional apollo.common.Header header = 1; ++ optional bool clusterortrack = 2; // 0 = track, 1 = cluster ++ optional int32 obstacle_id = 3; // obstacle Id ++ // longitude distance to the radar; (+) = target far away the radar unit = m ++ optional double longitude_dist = 4; ++ // lateral distance to the radar; (+) = right; unit = m ++ optional double lateral_dist = 5; ++ // longitude velocity to the radar; (+) = forward; unit = m/s ++ optional double longitude_vel = 6; ++ // lateral velocity to the radar; (+) = right; unit = m/s ++ optional double lateral_vel = 7; ++ // obstacle Radar Cross-Section; unit = dBsm ++ optional double rcs = 8; ++ // 0 = moving, 1 = stationary, 2 = oncoming, 3 = stationary candidate ++ // 4 = unknown, 5 = crossing stationary, 6 = crossing moving, 7 = stopped ++ optional int32 dynprop = 9; ++ // longitude distance standard deviation to the radar; (+) = forward; unit = m ++ optional double longitude_dist_rms = 10; ++ // lateral distance standard deviation to the radar; (+) = left; unit = m ++ optional double lateral_dist_rms = 11; ++ // longitude velocity standard deviation to the radar; (+) = forward; unit = ++ // m/s ++ optional double longitude_vel_rms = 12; ++ // lateral velocity standard deviation to the radar; (+) = left; unit = m/s ++ optional double lateral_vel_rms = 13; ++ // obstacle probability of existence ++ optional double probexist = 14; ++ ++ // The following is only valid for the track object message ++ // 0 = deleted, 1 = new, 2 = measured, 3 = predicted, 4 = deleted for, 5 = new ++ // from merge ++ optional int32 meas_state = 15; ++ // longitude acceleration to the radar; (+) = forward; unit = m/s2 ++ optional double longitude_accel = 16; ++ // lateral acceleration to the radar; (+) = left; unit = m/s2 ++ optional double lateral_accel = 17; ++ // orientation angle to the radar; (+) = counterclockwise; unit = degree ++ optional double oritation_angle = 18; ++ // longitude acceleration standard deviation to the radar; (+) = forward; unit ++ // = m/s2 ++ optional double longitude_accel_rms = 19; ++ // lateral acceleration standard deviation to the radar; (+) = left; unit = ++ // m/s2 ++ optional double lateral_accel_rms = 20; ++ // orientation angle standard deviation to the radar; (+) = counterclockwise; ++ // unit = degree ++ optional double oritation_angle_rms = 21; ++ optional double length = 22; // obstacle length; unit = m ++ optional double width = 23; // obstacle width; unit = m ++ // 0: point; 1: car; 2: truck; 3: pedestrian; 4: motorcycle; 5: bicycle; 6: ++ // wide; 7: unknown ++ optional int32 obstacle_class = 24; ++ // Object Range ++ optional double obstacle_range = 25; ++ // Object Velocity ++ optional double obstacle_vel = 26; ++ // Object Angle ++ optional double obstacle_angle = 27; ++} ++ ++message NanoRadar { ++ optional apollo.common.Header header = 1; ++ repeated NanoRadarObs contiobs = 2; // conti radar obstacle array ++ optional NanoRadarState_201 radar_state = 3; ++ optional NanoCollisionDetectionRegionState_402 radar_region_state = 4; ++ optional NanoObjectListStatus_60A object_list_status = 6; ++ optional NanoSoftwareVersion_700 software_version = 7; ++} +diff --git a/modules/common_msgs/simulation_msgs/agent.proto b/modules/common_msgs/simulation_msgs/agent.proto +index e17421f..e461f91 100644 +--- a/modules/common_msgs/simulation_msgs/agent.proto ++++ b/modules/common_msgs/simulation_msgs/agent.proto +@@ -57,4 +57,21 @@ message AgentConfig { + optional bool avoid_rear_end_collision = 17 [default = true]; + optional double rear_end_collision_distance = 18 + [default = 3.0, deprecated = true]; ++ ++ // When an obstacle approaches the adc at a certain distance, ++ // it needs to decelerate. ++ message NearCar { ++ optional double distance = 1 [default = 20]; ++ optional double acceleration = 2 [default = -2]; ++ optional bool is_same_lane = 3 [default = false]; ++ optional bool only_include_behind = 4 [default = true]; ++ } ++ optional NearCar near_car = 19; ++ ++ // Need to decelerate when an obstacle meets the crosswalk ++ message NearCrosswalk { ++ optional double distance = 1 [default = 15]; ++ optional double acceleration = 2 [default = -1]; ++ } ++ optional NearCrosswalk near_crosswalk = 22; + } diff --git a/diffs/v10/cyber.patch b/diffs/v10/cyber.patch new file mode 100644 index 0000000..b9ec4d8 --- /dev/null +++ b/diffs/v10/cyber.patch @@ -0,0 +1,19124 @@ +diff --git a/cyber/BUILD b/cyber/BUILD +index 7f52f29..85ee119 100755 +--- a/cyber/BUILD ++++ b/cyber/BUILD +@@ -62,7 +62,7 @@ apollo_cc_library( + "//cyber/transport:cyber_transport", + "@com_github_google_glog//:glog", + "@com_google_protobuf//:protobuf", +- "@fastrtps", ++ "@fastdds", + ], + ) + +diff --git a/cyber/base/BUILD b/cyber/base/BUILD +index 5d59d8d..d7d163f 100644 +--- a/cyber/base/BUILD ++++ b/cyber/base/BUILD +@@ -1,11 +1,12 @@ + load("//tools:cpplint.bzl", "cpplint") +-load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_library", "apollo_cc_test") ++load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") + + package(default_visibility = ["//visibility:public"]) + + apollo_cc_library( + name = "cyber_base", + hdrs = [ ++ "arena_queue.h", + "atomic_hash_map.h", + "atomic_rw_lock.h", + "bounded_queue.h", +@@ -13,6 +14,7 @@ apollo_cc_library( + "for_each.h", + "macros.h", + "object_pool.h", ++ "pthread_rw_lock.h", + "reentrant_rw_lock.h", + "rw_lock_guard.h", + "signal.h", +@@ -97,4 +99,5 @@ apollo_cc_test( + ) + + apollo_package() ++ + cpplint() +diff --git a/cyber/base/arena_queue.h b/cyber/base/arena_queue.h +new file mode 100644 +index 0000000..5abdb50 +--- /dev/null ++++ b/cyber/base/arena_queue.h +@@ -0,0 +1,262 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_BASE_ARENA_QUEUE_H_ ++#define CYBER_BASE_ARENA_QUEUE_H_ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "cyber/base/macros.h" ++#include "cyber/base/wait_strategy.h" ++ ++namespace apollo { ++namespace cyber { ++namespace base { ++ ++template ++class ArenaQueue { ++ public: ++ using value_type = T; ++ using size_type = uint64_t; ++ ++ public: ++ ArenaQueue() {} ++ ArenaQueue& operator=(const ArenaQueue& other) = delete; ++ ArenaQueue(const ArenaQueue& other) = delete; ++ ~ArenaQueue(); ++ bool Init(uint64_t size); ++ bool Init(uint64_t size, google::protobuf::Arena* arena); ++ ++ T* AddBack(); ++ T* PopFront(); ++ T* GetBack(); ++ T* GetFront(); ++ ++ uint64_t Size(); ++ bool Empty(); ++ uint64_t Head() { return head_.load(); } ++ uint64_t Tail() { return tail_.load(); } ++ uint64_t Commit() { return commit_.load(); } ++ bool NextIndex(uint64_t& index) { ++ if (Empty()) { ++ return false; ++ } ++ if (arena_) { ++ if (GetIndex(index) < Tail() - 1) { ++ index = GetIndex(index + 1); ++ return true; ++ } ++ return false; ++ } else { ++ if (index < Size() - 1) { ++ index = index + 1; ++ return true; ++ } ++ return false; ++ } ++ } ++ bool GetHeadIndex(uint64_t& index) { ++ if (Empty()) { ++ return false; ++ } ++ if (arena_) { ++ index = GetIndex(head_ + 1); ++ return true; ++ } else { ++ index = 0; ++ return true; ++ } ++ } ++ bool GetTailIndex(uint64_t& index) { ++ if (Empty()) { ++ return false; ++ } ++ if (arena_) { ++ index = GetIndex(tail_ - 1); ++ return true; ++ } else { ++ index = Size() - 1; ++ return true; ++ } ++ } ++ bool GetEleByIndex(uint64_t i, T*& ptr) { ++ if (Empty()) { ++ return false; ++ } ++ if (arena_) { ++ ptr = pool_[GetIndex(i)]; ++ return true; ++ } else { ++ if (i > Size() - 1) { ++ return false; ++ } ++ ptr = &normal_queue[i]; ++ return true; ++ } ++ } ++ bool IsArenaEnable() { return arena_; } ++ ++ private: ++ uint64_t GetIndex(uint64_t num); ++ ++ alignas(CACHELINE_SIZE) std::atomic head_ = {0}; ++ alignas(CACHELINE_SIZE) std::atomic tail_ = {1}; ++ alignas(CACHELINE_SIZE) std::atomic commit_ = {1}; ++ ++ uint64_t pool_size_ = 0; ++ std::vector pool_; ++ bool arena_; ++ std::deque normal_queue; ++}; ++ ++template ++ArenaQueue::~ArenaQueue() {} ++ ++template ++inline bool ArenaQueue::Init(uint64_t size) { ++ arena_ = false; ++ return true; ++} ++ ++template ++inline bool ArenaQueue::Init(uint64_t size, google::protobuf::Arena* arena) { ++ pool_size_ = size + 2; ++ if (pool_.size() == pool_size_) { ++ return true; ++ } ++ pool_.clear(); ++ for (uint64_t i = 0; i < pool_size_; ++i) { ++ pool_.push_back(google::protobuf::Arena::CreateMessage(arena)); ++ } ++ arena_ = true; ++ return true; ++} ++ ++template ++T* ArenaQueue::GetBack() { ++ if (Empty()) { ++ return nullptr; ++ } ++ if (arena_) { ++ return pool_[GetIndex(tail_ - 1)]; ++ } else { ++ return &normal_queue.back(); ++ } ++} ++ ++template ++T* ArenaQueue::GetFront() { ++ if (Empty()) { ++ return nullptr; ++ } ++ if (arena_) { ++ return pool_[GetIndex(head_ + 1)]; ++ } else { ++ return &normal_queue.front(); ++ } ++} ++ ++template ++T* ArenaQueue::AddBack() { ++ if (arena_) { ++ uint64_t new_tail = 0; ++ uint64_t old_commit = 0; ++ uint64_t old_tail = tail_.load(std::memory_order_acquire); ++ do { ++ new_tail = old_tail + 1; ++ if (GetIndex(new_tail) == ++ GetIndex(head_.load(std::memory_order_acquire))) { ++ return nullptr; ++ } ++ } while (!tail_.compare_exchange_weak(old_tail, new_tail, ++ std::memory_order_acq_rel, ++ std::memory_order_relaxed)); ++ do { ++ old_commit = old_tail; ++ } while (cyber_unlikely(!commit_.compare_exchange_weak( ++ old_commit, new_tail, std::memory_order_acq_rel, ++ std::memory_order_relaxed))); ++ return pool_[GetIndex(old_tail)]; ++ } else { ++ T instance; ++ normal_queue.push_back(instance); ++ return &normal_queue.back(); ++ } ++} ++ ++template ++T* ArenaQueue::PopFront() { ++ if (Empty()) { ++ return nullptr; ++ } ++ if (arena_) { ++ uint64_t new_head = 0; ++ uint64_t old_head = head_.load(std::memory_order_acquire); ++ do { ++ new_head = old_head + 1; ++ if (new_head == commit_.load(std::memory_order_acquire)) { ++ return nullptr; ++ } ++ } while (!head_.compare_exchange_weak(old_head, new_head, ++ std::memory_order_acq_rel, ++ std::memory_order_relaxed)); ++ return pool_[GetIndex(new_head)]; ++ } else { ++ normal_queue.pop_front(); ++ return nullptr; ++ } ++} ++ ++template ++inline uint64_t ArenaQueue::Size() { ++ if (arena_) { ++ return tail_ - head_ - 1; ++ } else { ++ return normal_queue.size(); ++ } ++} ++ ++template ++inline bool ArenaQueue::Empty() { ++ if (arena_) { ++ return Size() == 0; ++ } else { ++ return normal_queue.empty(); ++ } ++} ++ ++template ++inline uint64_t ArenaQueue::GetIndex(uint64_t num) { ++ return num - (num / pool_size_) * pool_size_; // faster than % ++} ++ ++} // namespace base ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_BASE_ARENA_QUEUE_H_ +diff --git a/cyber/base/macros.h b/cyber/base/macros.h +index 7a58b94..96442a3 100644 +--- a/cyber/base/macros.h ++++ b/cyber/base/macros.h +@@ -20,6 +20,8 @@ + #include + #include + ++#define eprosima eprosima_wrap ++ + #if __GNUC__ >= 3 + #define cyber_likely(x) (__builtin_expect((x), 1)) + #define cyber_unlikely(x) (__builtin_expect((x), 0)) +diff --git a/cyber/base/pthread_rw_lock.h b/cyber/base/pthread_rw_lock.h +new file mode 100644 +index 0000000..bb2c6b0 +--- /dev/null ++++ b/cyber/base/pthread_rw_lock.h +@@ -0,0 +1,73 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_BASE_PTHREAD_RW_LOCK_H_ ++#define CYBER_BASE_PTHREAD_RW_LOCK_H_ ++ ++#include ++ ++#include "cyber/base/rw_lock_guard.h" ++ ++namespace apollo { ++namespace cyber { ++namespace base { ++ ++class PthreadRWLock { ++ friend class ReadLockGuard; ++ friend class WriteLockGuard; ++ ++ public: ++ explicit PthreadRWLock(bool writer) { ++ pthread_rwlockattr_init(&rwlock_attr_); ++ if (writer) { ++ pthread_rwlockattr_setkind_np( ++ &rwlock_attr_, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); ++ } ++ pthread_rwlockattr_setpshared(&rwlock_attr_, PTHREAD_PROCESS_SHARED); ++ pthread_rwlock_init(&rwlock_, &rwlock_attr_); ++ } ++ PthreadRWLock() : PthreadRWLock(true) {} ++ ++ ~PthreadRWLock() { ++ pthread_rwlock_destroy(&rwlock_); ++ pthread_rwlockattr_destroy(&rwlock_attr_); ++ } ++ ++ void ReadLock(); ++ void ReadUnlock(); ++ ++ void WriteLock(); ++ void WriteUnlock(); ++ ++ private: ++ PthreadRWLock(const PthreadRWLock& other) = delete; ++ PthreadRWLock& operator=(const PthreadRWLock& other) = delete; ++ pthread_rwlock_t rwlock_; ++ pthread_rwlockattr_t rwlock_attr_; ++}; ++ ++inline void PthreadRWLock::ReadLock() { pthread_rwlock_rdlock(&rwlock_); } ++ ++inline void PthreadRWLock::ReadUnlock() { pthread_rwlock_unlock(&rwlock_); } ++ ++inline void PthreadRWLock::WriteLock() { pthread_rwlock_wrlock(&rwlock_); } ++ ++inline void PthreadRWLock::WriteUnlock() { pthread_rwlock_unlock(&rwlock_); } ++ ++} // namespace base ++} // namespace cyber ++} // namespace apollo ++ ++#endif +diff --git a/cyber/benchmark/BUILD b/cyber/benchmark/BUILD +new file mode 100644 +index 0000000..5090dc6 +--- /dev/null ++++ b/cyber/benchmark/BUILD +@@ -0,0 +1,51 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools/proto:proto.bzl", "proto_library", "apollo_py_binary") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_binary") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++apollo_py_binary( ++ name = "cyber_benchmark", ++ srcs = ["cyber_benchmark.py"], ++) ++ ++apollo_cc_binary( ++ name = "cyber_benchmark_reader", ++ srcs = [ ++ "cyber_benchmark_reader.cc", ++ ], ++ linkopts = [ ++ "-pthread", ++ "-lprofiler", ++ "-ltcmalloc", ++ ], ++ deps = [ ++ "//cyber", ++ ":benchmark_msg_proto", ++ ], ++) ++ ++apollo_cc_binary( ++ name = "cyber_benchmark_writer", ++ srcs = [ ++ "cyber_benchmark_writer.cc", ++ ], ++ linkopts = [ ++ "-pthread", ++ "-lprofiler", ++ "-ltcmalloc", ++ ], ++ deps = [ ++ "//cyber", ++ "//cyber/time:cyber_time", ++ ":benchmark_msg_proto", ++ ], ++) ++ ++proto_library( ++ name = "benchmark_msg_proto", ++ srcs = ["benchmark_msg.proto"], ++) ++ ++apollo_package() ++cpplint() +\ No newline at end of file +diff --git a/cyber/benchmark/benchmark_msg.proto b/cyber/benchmark/benchmark_msg.proto +new file mode 100644 +index 0000000..6757684 +--- /dev/null ++++ b/cyber/benchmark/benchmark_msg.proto +@@ -0,0 +1,8 @@ ++syntax = "proto2"; ++ ++package apollo.cyber.benchmark; ++ ++message BenchmarkMsg { ++ repeated uint32 data = 1; ++ optional bytes data_bytes = 2; ++} +\ No newline at end of file +diff --git a/cyber/benchmark/cyber_benchmark.py b/cyber/benchmark/cyber_benchmark.py +new file mode 100644 +index 0000000..7f676d3 +--- /dev/null ++++ b/cyber/benchmark/cyber_benchmark.py +@@ -0,0 +1,337 @@ ++""" ++cyber benchmark ++""" ++#!/usr/bin/env python3 ++# **************************************************************************** ++# Copyright 2024 The Apollo Authors. All Rights Reserved. ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++# **************************************************************************** ++ ++import os ++import re ++import sys ++import json ++import time ++import numpy as np ++import argparse ++import atexit ++import signal ++import logging ++import itertools ++import subprocess ++import threading ++from watchdog.observers import Observer ++from watchdog.events import FileSystemEventHandler ++ ++ ++""" ++colorful logging ++""" ++BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = list(range(8)) ++RESET_SEQ = "\033[0m" ++COLOR_SEQ = "\033[1;%dm" ++BOLD_SEQ = "\033[1m" ++ ++COLORS = { ++ 'INFO': GREEN, ++ 'WARNING': YELLOW, ++ 'DEBUG': BLUE, ++ 'ERROR': RED, ++ 'CRITICAL': YELLOW ++} ++ ++logger = logging.Logger(__name__) ++reader_nums = -1 ++ ++class Benchmark(FileSystemEventHandler): ++ """ ++ benchmark class definition ++ """ ++ def __init__(self, params): ++ self.params = params ++ self.directory_to_watch = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "dumps") ++ self.preformance_to_write = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "data") ++ self.performances = {} ++ self.performance_key = None ++ self.debounce_period = 1 ++ self.last_sample_time = 0 ++ self.base_key = { ++ "cyber_benchmark_cpu_usage_latency": "cpu_usage", ++ "cyber_benchmark_mem_resident_usage_latency": "mem_usage", ++ } ++ self.latency_key = {} ++ self.data_fd = open( ++ "transport_performance_{}".format(int(time.time())), "w+") ++ ++ def on_any_event(self, event): ++ """ ++ monitor the files associated with performance ++ """ ++ if event.is_directory: ++ return None ++ ++ elif event.event_type == 'created' or event.event_type == 'modified': ++ if "cyber_benchmark_reader" not in event.src_path.split('/')[-1] or \ ++ not event.src_path.split('/')[-1].endswith("latency.data"): ++ return None ++ if self.performance_key is None: ++ return None ++ ++ current = time.time() ++ if current - self.last_sample_time < 1: ++ return None ++ ++ self.last_sample_time = current ++ ++ latancy_data_path = event.src_path ++ try: ++ with open(latancy_data_path, "r") as f: ++ for l in f.readlines(): ++ k, v = l.strip().split(" : ")[0], l.strip().split(" : ")[1] ++ if k in self.latency_key: ++ if self.latency_key[k] not in self.performances[self.performance_key]: ++ self.performances[self.performance_key][self.latency_key[k]] = [] ++ self.performances[ ++ self.performance_key][self.latency_key[k]].append(int(v)) ++ except: ++ return None ++ ++ def parse_result(self): ++ """ ++ get the final results of performance ++ """ ++ global reader_nums ++ for i in range(reader_nums): ++ data_path = os.path.join( ++ self.directory_to_watch, f"cyber_benchmark_reader_{i}.data") ++ recv_total = -1 ++ send_total = -1 ++ with open(data_path, "r") as f: ++ for l in f.readlines(): ++ k, v = l.strip().strip().split(" : ")[0], l.strip().split(" : ")[1] ++ if k == f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_recv_msgs_nums": ++ if i == 0: ++ recv_total = int(v) ++ else: ++ recv_total += int(v) ++ elif k == f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_total_msgs_nums": ++ if i == 0: ++ send_total = int(v) ++ else: ++ send_total += int(v) ++ if recv_total == -1 or send_total == -1: ++ logger.error("parse cyber_benchmark_reader.data result failed") ++ sys.exit(3) ++ ++ writer_data_path = os.path.join( ++ self.directory_to_watch, "cyber_benchmark_writer.data") ++ test_time = -1 ++ test_message_size = -1 ++ with open(writer_data_path, "r") as f: ++ for l in f.readlines(): ++ k, v = l.strip().strip().split(" : ")[0], l.strip().split(" : ")[1] ++ if k == "cyber_benchmark_cyber_benchmark_writer_test_time": ++ test_time = float(v) ++ elif k == "cyber_benchmark_cyber_benchmark_writer_message_size": ++ test_message_size = int(v) ++ if test_time == -1 or test_message_size == -1: ++ logger.error("parse cyber_benchmark_writer.data result failed") ++ sys.exit(3) ++ ++ test_message_size = test_message_size / 1024 / 1024 # in MB ++ ++ msg_lose_rate = round((send_total - recv_total) / send_total * 100, 2) ++ bandwidth = round(recv_total * test_message_size / test_time * 8, 2) # mbps ++ ++ ret_str = f"{self.performance_key}:\n" ++ for k in self.performances[self.performance_key]: ++ self.performances[self.performance_key][k].remove( ++ max(self.performances[self.performance_key][k])) ++ self.performances[self.performance_key][k].remove( ++ min(self.performances[self.performance_key][k])) ++ self.performances[self.performance_key][k] = list( ++ filter(lambda x: x != 0, self.performances[self.performance_key][k])) ++ if "cpu" in k: ++ self.performances[self.performance_key][k] = list( ++ filter(lambda x: x < 120, self.performances[self.performance_key][k])) ++ pavg = round(np.mean(self.performances[self.performance_key][k]), 2) ++ p99 = round(np.percentile(self.performances[self.performance_key][k], 99), 2) ++ p95 = round(np.percentile(self.performances[self.performance_key][k], 95), 2) ++ p50 = round(np.percentile(self.performances[self.performance_key][k], 50), 2) ++ pmin = round(np.min(self.performances[self.performance_key][k]), 2) ++ pmax = round(np.max(self.performances[self.performance_key][k]), 2) ++ ret_str += f"{k}: \n" ++ ret_str += f" avg: {pavg}, pmin: {pmin}, pmax: {pmax}, p50: {p50}, p95: {p95}, p99: {p99}\n" ++ ++ ret_str += f"bandwidth: {bandwidth} mbps\n" ++ ret_str += f"msg_lose_rate: {msg_lose_rate}%" ++ print(ret_str) ++ self.performances[self.performance_key]["test_message_size"] = test_message_size ++ self.performances[self.performance_key]["test_time"] = test_time ++ ++ def save_data(self): ++ """ ++ record all performance data ++ """ ++ self.data_fd.write( ++ json.dumps(self.performances[self.performance_key])) ++ self.data_fd.flush() ++ ++ def run(self): ++ """ ++ run the performance test ++ """ ++ global reader_nums ++ transport_data_type = [] ++ if self.params.transport_type == 0 or \ ++ self.params.transport_type == 1: ++ transport_data_type = [self.params.transport_type] ++ else: ++ transport_data_type = [0, 1] ++ ++ cartesian_product = list(itertools.product(self.params.data_size, ++ self.params.reader_nums, self.params.frequency, transport_data_type)) ++ ++ for item in cartesian_product: ++ ds = item[0] ++ rn = item[1] ++ f = item[2] ++ dt = item[3] ++ ++ reader_nums = rn ++ ++ for k in self.base_key: ++ self.latency_key[k] = self.base_key[k] ++ for i in range(rn): ++ self.latency_key[ ++ f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_cyber_latency" ++ ] = "cyber_latency" ++ self.latency_key[ ++ f"cyber_benchmark_cyber_benchmark_reader_{i}_apollo_cyber_benchmark_tran_latency" ++ ] = "cyber_tran_latency" ++ ++ if self.params.best_effords: ++ qos = 1 ++ else: ++ qos = 0 ++ self.performance_key = \ ++ f"data-size:{ds}/reader-nums:{rn}/frequency:{f}/data_type:{dt}/qos:{qos}" ++ self.performances[self.performance_key] = {} ++ print(f"\nrunning test with {self.performance_key}") ++ self.readers = [] ++ for i in range(rn): ++ try: ++ reader_args_list = [ ++ "cyber_benchmark_reader", ++ "-n", f"{i}"] ++ reader = subprocess.Popen(reader_args_list, stdout=subprocess.DEVNULL, ++ stderr=subprocess.DEVNULL) ++ except Exception as err: ++ logger.error('Subprocess Popen exception: ' + str(err)) ++ sys.exit(2) ++ else: ++ if reader.pid == 0 or reader.returncode is not None: ++ logger.error('Start process cyber_benchmark_reader failed.') ++ sys.exit(2) ++ self.readers.append(reader) ++ time.sleep(3) ++ try: ++ writer_args_list = [ ++ "cyber_benchmark_writer", "-s", f"{ds}", ++ "-t", f"{f}", "-T", f"{self.params.time}", ++ "-d", f"{dt}", "-q", f"{qos}"] ++ ret = subprocess.run(writer_args_list, stdout=subprocess.DEVNULL, ++ stderr=subprocess.DEVNULL) ++ except Exception as err: ++ logger.error('Subprocess run writer exception: ' + str(err)) ++ sys.exit(2) ++ else: ++ if ret.returncode != 0: ++ logger.error('Run process cyber_benchmark_writer failed.') ++ sys.exit(2) ++ time.sleep(3) ++ for reader in self.readers: ++ reader.kill() ++ self.parse_result() ++ self.save_data() ++ ++ ++def param_parse(params): ++ """ ++ parse user parameters ++ """ ++ pattern = re.compile(r'^\d+(\.\d+)?[kKmMbB]$') ++ for i in range(len(params.data_size)): ++ param = params.data_size[i] ++ if not pattern.match(param): ++ logger.error(f"data size {param} is invalid") ++ params.data_size[i] = \ ++ param[: len(params.data_size[i]) - 1] + param[-1].upper() ++ for i in range(len(params.reader_nums)): ++ try: ++ param = int(params.reader_nums[i]) ++ except: ++ logger.error( ++ f"reader nums {params.reader_nums[i]} is invalid") ++ params.reader_nums[i] = param ++ for i in range(len(params.frequency)): ++ try: ++ param = int(params.frequency[i]) ++ except: ++ logger.error( ++ f"frequency {params.frequency[i]} is invalid") ++ params.frequency[i] = param ++ return params ++ ++ ++def main(): ++ """ ++ entry ++ """ ++ parser = argparse.ArgumentParser(description='cyber benchmark') ++ parser.add_argument( ++ '-s', '--data_size', nargs='*', metavar='*', ++ default=['16B', '1K', '64K', '256K', '1M', '5M', '10M'], ++ type=str.lstrip, help="transport data size, default is 16B - 10M" ++ ) ++ parser.add_argument( ++ '-T', '--transport_type', type=int, default=0, ++ help='transport data type, 0 means bytes, 1 means repeted field, while others mean both' ++ ) ++ parser.add_argument( ++ '-b', '--best_effords', action='store_true', default=False, ++ help='test the performance using qos policy best effords' ++ ) ++ parser.add_argument( ++ '-r', '--reader_nums', nargs='*', metavar='*', default=[1, 2, 5, 10], ++ help='desribe how many readers receive the message' ++ ) ++ parser.add_argument( ++ '-f', '--frequency', nargs='*', metavar='*', default=[10, 20, 50, 100, -1], ++ help='desribe the frequency of message sended, e.g. 10 means 10 hz' ++ ) ++ parser.add_argument( ++ '-t', '--time', type=int, default=60, ++ help='desribe the time of performance test, default is 60s' ++ ) ++ params = param_parse(parser.parse_args(sys.argv[1:])) ++ benchmark = Benchmark(params) ++ observer = Observer() ++ ++ observer.schedule(benchmark, benchmark.directory_to_watch) ++ observer.start() ++ benchmark.run() ++ ++if __name__ == "__main__": ++ main() +\ No newline at end of file +diff --git a/cyber/benchmark/cyber_benchmark_reader.cc b/cyber/benchmark/cyber_benchmark_reader.cc +new file mode 100644 +index 0000000..a23fb2f +--- /dev/null ++++ b/cyber/benchmark/cyber_benchmark_reader.cc +@@ -0,0 +1,179 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/benchmark/benchmark_msg.pb.h" ++#include "cyber/cyber.h" ++ ++#if __has_include("gperftools/profiler.h") ++#include "gperftools/heap-profiler.h" ++#include "gperftools/malloc_extension.h" ++#include "gperftools/profiler.h" ++#endif ++ ++using apollo::cyber::benchmark::BenchmarkMsg; ++ ++std::string BINARY_NAME = "cyber_benchmark_reader"; // NOLINT ++ ++int nums_of_reader = 1; ++bool enable_cpuprofile = false; ++bool enable_heapprofile = false; ++std::string profile_filename = "cyber_benchmark_reader_cpu.prof"; // NOLINT ++std::string heapprofile_filename = "cyber_benchmark_reader_mem.prof"; // NOLINT ++ ++void DisplayUsage() { ++ AINFO << "Usage: \n " << BINARY_NAME << " [OPTION]...\n" ++ << "Description: \n" ++ << " -h, --help: help information \n" ++ << " -n, --nums_of_reader=nums_of_reader: numbers of reader, " ++ "default value is 1\n" ++ << " -c, --cpuprofile: enable gperftools cpu profile\n" ++ << " -o, --profile_filename=filename: the filename to dump the " ++ "profile to, default value is cyber_benchmark_writer_cpu.prof. " ++ "Only work with -c option\n" ++ << " -H, --heapprofile: enable gperftools heap profile\n" ++ << " -O, --heapprofile_filename=filename: the filename " ++ " to dump the profile to, default value is " ++ "cyber_benchmark_writer_mem.prof. Only work with -H option\n" ++ << "Example:\n" ++ << " " << BINARY_NAME << " -h\n" ++ << " " << BINARY_NAME << " -n 1\n" ++ << " " << BINARY_NAME << " -n 10 -c -H "; ++} ++ ++void GetOptions(const int argc, char* const argv[]) { ++ opterr = 0; // extern int opterr ++ int long_index = 0; ++ const std::string short_opts = "hn:co:HO:"; ++ static const struct option long_opts[] = { ++ {"help", no_argument, nullptr, 'h'}, ++ {"nums_of_reader", required_argument, nullptr, 'n'}, ++ {"cpuprofile", no_argument, nullptr, 'c'}, ++ {"profile_filename", required_argument, nullptr, 'o'}, ++ {"heapprofile", no_argument, nullptr, 'H'}, ++ {"heapprofile_filename", required_argument, nullptr, 'O'}, ++ {NULL, no_argument, nullptr, 0}}; ++ ++ // log command for info ++ std::string cmd(""); ++ for (int i = 0; i < argc; ++i) { ++ cmd += argv[i]; ++ cmd += " "; ++ } ++ AINFO << "command: " << cmd; ++ ++ if (1 == argc) { ++ DisplayUsage(); ++ exit(0); ++ } ++ ++ do { ++ int opt = ++ getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); ++ if (opt == -1) { ++ break; ++ } ++ switch (opt) { ++ case 'n': ++ nums_of_reader = std::stoi(std::string(optarg)); ++ if (nums_of_reader < 0) { ++ AERROR << "Invalid numbers of reader. It should be grater than 0"; ++ exit(-1); ++ } ++ break; ++ case 'c': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_cpuprofile = true; ++ break; ++ case 'o': ++ profile_filename = std::string(optarg); ++ break; ++ case 'H': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_heapprofile = true; ++ break; ++ case 'O': ++ heapprofile_filename = std::string(optarg); ++ break; ++ case 'h': ++ DisplayUsage(); ++ exit(0); ++ default: ++ break; ++ } ++ } while (true); ++ ++ if (optind < argc) { ++ AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; ++ DisplayUsage(); ++ exit(1); ++ } ++} ++ ++int main(int argc, char** argv) { ++ GetOptions(argc, argv); ++ google::SetCommandLineOption("bvar_dump_interval", "1"); ++ apollo::cyber::Init(argv[0], ++ BINARY_NAME + "_" + std::to_string(nums_of_reader)); ++ ++ apollo::cyber::ReaderConfig reader_config; ++ reader_config.channel_name = "/apollo/cyber/benchmark"; ++ reader_config.qos_profile.set_depth(10); ++ ++ std::vector>> vec; ++ ++ // for (int i = 0; i < nums_of_reader; i++) { ++ std::string node_name = BINARY_NAME + "-" + std::to_string(nums_of_reader); ++ auto node = apollo::cyber::CreateNode(node_name); ++ vec.push_back(std::move(node->CreateReader( ++ reader_config, [](const std::shared_ptr m) {}))); ++ // } ++ ++#ifndef NO_TCMALLOC ++#ifdef BASE_PROFILER_H_ ++ if (enable_cpuprofile) { ++ ProfilerStart(profile_filename.c_str()); ++ } ++ if (enable_heapprofile) { ++ HeapProfilerStart(heapprofile_filename.c_str()); ++ } ++#endif ++#endif ++ ++ apollo::cyber::WaitForShutdown(); ++ ++#ifndef NO_TCMALLOC ++#ifdef BASE_PROFILER_H_ ++ if (enable_cpuprofile) { ++ ProfilerStop(); ++ } ++ if (enable_heapprofile) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++#endif ++#endif ++ ++ return 0; ++} +diff --git a/cyber/benchmark/cyber_benchmark_writer.cc b/cyber/benchmark/cyber_benchmark_writer.cc +new file mode 100644 +index 0000000..78b19ca +--- /dev/null ++++ b/cyber/benchmark/cyber_benchmark_writer.cc +@@ -0,0 +1,362 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "cyber/benchmark/benchmark_msg.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/time/duration.h" ++#include "cyber/time/time.h" ++ ++#if __has_include("gperftools/profiler.h") ++#include "gperftools/heap-profiler.h" ++#include "gperftools/malloc_extension.h" ++#include "gperftools/profiler.h" ++#endif ++ ++std::string BINARY_NAME = "cyber_benchmark_writer"; // NOLINT ++ ++int message_size = -1; ++int transport_freq = -1; ++int qos_policy = 0; ++int data_type = 0; ++int running_time = 10; ++bool enable_cpuprofile = false; ++bool enable_heapprofile = false; ++std::string profile_filename = "cyber_benchmark_writer_cpu.prof"; // NOLINT ++std::string heapprofile_filename = "cyber_benchmark_writer_mem.prof"; // NOLINT ++ ++void DisplayUsage() { ++ AINFO << "Usage: \n " << BINARY_NAME << " [OPTION]...\n" ++ << "Description: \n" ++ << " -h, --help: help information \n" ++ << " -s, --message_size=message_size: transport message size\n" ++ << " -t, --transport_freq=transmission_frequency: transmission " ++ "frequency\n" // NOLINT ++ << " -q, --qos_policy=qos_reliable_policy: set qos reliable policy, " ++ "0 is Reliable, 1 is Best effort, default value is 0\n" ++ << " -d, --data_type=data_type: transport data type, " ++ "0 is bytes, 1 is repeated field, default value is 0\n" ++ << " -T, --time=time: running time, default value is 10 seconds\n" ++ << " -c, --cpuprofile: enable gperftools cpu profile\n" ++ << " -o, --profile_filename=filename: the filename to dump the " ++ "profile to, default value is cyber_benchmark_writer_cpu.prof. Only " ++ "work " // NOLINT ++ "with -c option\n" ++ << " -H, --heapprofile: enable gperftools heap profile\n" ++ << " -O, --heapprofile_filename=filename: the filename to dump the " ++ "profile to, default value is cyber_benchmark_writer_mem.prof. Only " ++ "work " // NOLINT ++ "with -H option\n" ++ << "Example:\n" ++ << " " << BINARY_NAME << " -h\n" ++ << " " << BINARY_NAME << " -s 64K -t 10\n" ++ << " " << BINARY_NAME << " -s 64K -t 10 -c -H "; ++} ++ ++void GetOptions(const int argc, char* const argv[]) { ++ opterr = 0; // extern int opterr ++ int long_index = 0; ++ const std::string short_opts = "hs:t:q:d:T:co:HO:"; ++ static const struct option long_opts[] = { ++ {"help", no_argument, nullptr, 'h'}, ++ {"message_size", required_argument, nullptr, 's'}, ++ {"transport_freq", required_argument, nullptr, 't'}, ++ {"qos_policy", required_argument, nullptr, 'q'}, ++ {"data_type", required_argument, nullptr, 'd'}, ++ {"time", required_argument, nullptr, 'T'}, ++ {"cpuprofile", no_argument, nullptr, 'c'}, ++ {"profile_filename", required_argument, nullptr, 'o'}, ++ {"heapprofile", no_argument, nullptr, 'H'}, ++ {"heapprofile_filename", required_argument, nullptr, 'O'}, ++ {NULL, no_argument, nullptr, 0}}; ++ ++ // log command for info ++ std::string cmd(""); ++ for (int i = 0; i < argc; ++i) { ++ cmd += argv[i]; ++ cmd += " "; ++ } ++ AINFO << "command: " << cmd; ++ ++ if (1 == argc) { ++ DisplayUsage(); ++ exit(0); ++ } ++ ++ do { ++ int opt = ++ getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); ++ if (opt == -1) { ++ break; ++ } ++ int base_size = 1; ++ std::string arg; ++ switch (opt) { ++ case 's': ++ arg = std::string(optarg); ++ switch (arg[arg.length() - 1]) { ++ case 'B': ++ base_size = 1; ++ break; ++ case 'K': ++ base_size = 1024; ++ break; ++ case 'M': ++ base_size = 1024 * 1024; ++ break; ++ default: ++ AERROR << "Invalid identifier. It should be 'K' or 'M' or 'B'"; ++ exit(-1); ++ } ++ message_size = std::stoi(arg.substr(0, arg.length() - 1)) * base_size; ++ if (message_size < 0 || message_size % 4 != 0) { ++ AERROR << "Invalid message size."; ++ exit(-1); ++ } ++ break; ++ case 't': ++ transport_freq = std::stoi(std::string(optarg)); ++ break; ++ case 'T': ++ running_time = std::stoi(std::string(optarg)); ++ if (running_time < 0) { ++ AERROR << "Invalid running time. It should greater than 0"; ++ exit(-1); ++ } ++ break; ++ case 'q': ++ qos_policy = std::stoi(std::string(optarg)); ++ if (qos_policy != 0 && qos_policy != 1) { ++ AERROR << "Invalid qos_policy. It should be 0 or 1"; ++ exit(-1); ++ } ++ break; ++ case 'd': ++ data_type = std::stoi(std::string(optarg)); ++ if (data_type != 0 && data_type != 1) { ++ AERROR << "Invalid data_type. It should be 0 or 1"; ++ exit(-1); ++ } ++ break; ++ case 'c': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_cpuprofile = true; ++ break; ++ case 'o': ++ profile_filename = std::string(optarg); ++ break; ++ case 'H': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_heapprofile = true; ++ break; ++ case 'O': ++ heapprofile_filename = std::string(optarg); ++ break; ++ case 'h': ++ DisplayUsage(); ++ exit(0); ++ default: ++ break; ++ } ++ } while (true); ++ ++ if (optind < argc) { ++ AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; ++ DisplayUsage(); ++ exit(1); ++ } ++ ++ if (message_size == -1) { ++ AINFO << "-s parameters must be specified"; ++ DisplayUsage(); ++ exit(1); ++ } ++} ++ ++int main(int argc, char** argv) { ++ GetOptions(argc, argv); ++ google::SetCommandLineOption("bvar_dump_interval", "1"); ++ ++ apollo::cyber::Init(argv[0], BINARY_NAME); ++ ++ auto node = apollo::cyber::CreateNode(BINARY_NAME); ++ auto test_time = ++ std::make_shared<::bvar::Status>(BINARY_NAME + "-test-time", 0); ++ auto test_message_size = std::make_shared<::bvar::Status>( ++ BINARY_NAME + "-message-size", 0); ++ apollo::cyber::proto::RoleAttributes attrs; ++ attrs.set_channel_name("/apollo/cyber/benchmark"); ++ auto qos = attrs.mutable_qos_profile(); ++ qos->set_depth(10); ++ ++ if (qos_policy == 1) { ++ qos->set_reliability( ++ apollo::cyber::proto::QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); ++ } else { ++ qos->set_reliability( ++ apollo::cyber::proto::QosReliabilityPolicy::RELIABILITY_RELIABLE); ++ } ++ auto writer = ++ node->CreateWriter(attrs); ++ ++ // sleep a while for initialization, aboout 2 seconds ++ apollo::cyber::Rate rate_init(0.5); ++ ++ apollo::cyber::Rate rate_ctl(static_cast(transport_freq)); ++ ++ rate_init.Sleep(); ++ ++ uint64_t send_msg_total = transport_freq * running_time; ++ ++ // std::vector trans_vec; ++ // int num_of_instance = message_size / 4; ++ // for (int i = 0; i < num_of_instance; i++) { ++ // trans_vec.push_back(rand()); ++ // } ++ ++ // char* data = (char*)malloc(message_size); ++ // for (int i = 0; i < num_of_instance; i++) { ++ // *(uint32_t*)(data + i * 4) = rand(); ++ // } ++ ++ // if (data_type == 0) { ++ // trans_unit->set_data_bytes(data, message_size); ++ // } else { ++ // for (int i = 0; i < num_of_instance; i++) { ++ // trans_unit->add_data(trans_vec[i]); ++ // } ++ // } ++ // free(data); ++ ++ int send_msg = 0; ++ ++#ifndef NO_TCMALLOC ++#ifdef BASE_PROFILER_H_ ++ if (enable_cpuprofile) { ++ ProfilerStart(profile_filename.c_str()); ++ } ++ if (enable_heapprofile) { ++ HeapProfilerStart(heapprofile_filename.c_str()); ++ } ++#endif ++#endif ++ ++ std::vector trans_vec; ++ int num_of_instance = message_size / 4; ++ for (int i = 0; i < num_of_instance; i++) { ++ trans_vec.push_back(rand()); // NOLINT ++ } ++ ++ char* data = (char*)malloc(message_size); // NOLINT ++ ++ if (transport_freq > 0) { ++ auto start_time = apollo::cyber::Time::Now(); ++ while (send_msg < send_msg_total) { ++ auto trans_unit = writer->AcquireMessage(); ++ int base = rand(); // NOLINT ++ ++ for (int i = 0; i < num_of_instance; i++) { ++ trans_vec[i] = base * i; ++ } ++ ++ for (int i = 0; i < num_of_instance; i++) { ++ *(uint32_t*)(data + i * 4) = base * i; // NOLINT ++ } ++ ++ if (data_type == 0) { ++ trans_unit->set_data_bytes(data, message_size); ++ } else { ++ for (int i = 0; i < num_of_instance; i++) { ++ trans_unit->add_data(trans_vec[i]); ++ } ++ } ++ ++ writer->Write(trans_unit); ++ ++send_msg; ++ ++ rate_ctl.Sleep(); ++ } ++ auto end_time = apollo::cyber::Time::Now(); ++ test_time->set_value((end_time - start_time).ToSecond()); ++ } else { ++ auto start_time = apollo::cyber::Time::Now(); ++ auto current = start_time; ++ auto endtime = apollo::cyber::Time::Now() + ++ apollo::cyber::Duration(static_cast(running_time)); ++ while (current < endtime) { ++ auto trans_unit = writer->AcquireMessage(); ++ int base = rand(); // NOLINT ++ ++ for (int i = 0; i < num_of_instance; i++) { ++ trans_vec[i] = base * i; ++ } ++ ++ for (int i = 0; i < num_of_instance; i++) { ++ *(uint32_t*)(data + i * 4) = base * i; // NOLINT ++ } ++ ++ if (data_type == 0) { ++ trans_unit->set_data_bytes(data, message_size); ++ } else { ++ for (int i = 0; i < num_of_instance; i++) { ++ trans_unit->add_data(trans_vec[i]); ++ } ++ } ++ ++ writer->Write(trans_unit); ++ ++send_msg; ++ current = apollo::cyber::Time::Now(); ++ } ++ test_time->set_value((current - start_time).ToSecond()); ++ } ++ ++ auto m = writer->AcquireMessage(); ++ if (data_type == 0) { ++ m->set_data_bytes(data, message_size); ++ } else { ++ for (int i = 0; i < num_of_instance; i++) { ++ m->add_data(trans_vec[i]); ++ } ++ } ++ test_message_size->set_value(m->ByteSizeLong()); ++ ++ free(data); ++ ++#ifndef NO_TCMALLOC ++#ifdef BASE_PROFILER_H_ ++ if (enable_cpuprofile) { ++ ProfilerStop(); ++ } ++ if (enable_heapprofile) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++#endif ++#endif ++ std::this_thread::sleep_for(std::chrono::milliseconds(1200)); ++ apollo::cyber::Clear(); ++ ++ return 0; ++} +diff --git a/cyber/common/BUILD b/cyber/common/BUILD +index 5d9031d..386fc8e 100644 +--- a/cyber/common/BUILD ++++ b/cyber/common/BUILD +@@ -1,16 +1,13 @@ + load("//tools:cpplint.bzl", "cpplint") +-load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package", "apollo_cc_test") ++load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") + + package(default_visibility = ["//visibility:public"]) + + apollo_cc_library( + name = "cyber_common", + srcs = [ +- "global_data.cc", + "file.cc", +- ], +- data = [ +- "//cyber:cyber_conf", ++ "global_data.cc", + ], + hdrs = [ + "environment.h", +@@ -22,13 +19,17 @@ apollo_cc_library( + "types.h", + "util.h", + ], ++ data = [ ++ "//cyber:cyber_conf", ++ ], + deps = [ + "//cyber:cyber_binary", + "//cyber/base:cyber_base", + "//cyber/proto:cyber_conf_cc_proto", ++ "//cyber/proto:transport_conf_cc_proto", ++ "@com_github_google_glog//:glog", + "@com_github_nlohmann_json//:json", + "@com_google_protobuf//:protobuf", +- "@com_github_google_glog//:glog", + ], + ) + +diff --git a/cyber/common/file.cc b/cyber/common/file.cc +index 29b1930..44a61ef 100644 +--- a/cyber/common/file.cc ++++ b/cyber/common/file.cc +@@ -66,6 +66,26 @@ bool SetProtoToASCIIFile(const google::protobuf::Message &message, + return SetProtoToASCIIFile(message, fd); + } + ++bool SetStringToASCIIFile(const std::string &content, ++ const std::string &file_name) { ++ int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); ++ if (fd < 0) { ++ AERROR << "Unable to open file " << file_name << " to write."; ++ return false; ++ } ++ // Write the string data to the file ++ ssize_t bytes_written = write(fd, content.c_str(), content.size()); ++ if (bytes_written < 0) { ++ AERROR << "Failed to write to file."; ++ close(fd); // Ensure the file descriptor is closed even on error ++ return false; ++ } ++ ++ close(fd); // Close the file descriptor ++ ++ return true; ++} ++ + bool GetProtoFromASCIIFile(const std::string &file_name, + google::protobuf::Message *message) { + using google::protobuf::TextFormat; +@@ -227,12 +247,26 @@ bool CopyFile(const std::string &from, const std::string &to) { + return true; + } + ++bool IsValidPath(const std::string &path) { ++ const std::string illegal_chars = "\0<>:\"|?*;"; ++ for (char ch : path) { ++ if (illegal_chars.find(ch) != std::string::npos) { ++ return false; ++ } ++ } ++ return true; ++} ++ + bool CopyDir(const std::string &from, const std::string &to) { + DIR *directory = opendir(from.c_str()); + if (directory == nullptr) { + AERROR << "Cannot open directory " << from; + return false; + } ++ if (!IsValidPath(from) || !IsValidPath(to)) { ++ AERROR << "invalid path format: " << from << " to " << to; ++ return false; ++ } + + bool ret = true; + if (EnsureDirectory(to)) { +diff --git a/cyber/common/file.h b/cyber/common/file.h +index eee9a97..ec3dd88 100644 +--- a/cyber/common/file.h ++++ b/cyber/common/file.h +@@ -60,6 +60,16 @@ bool SetProtoToASCIIFile(const google::protobuf::Message &message, + bool SetProtoToASCIIFile(const google::protobuf::Message &message, + const std::string &file_name); + ++/** ++ * @brief Sets the content of the file specified by the file_name to be the ++ * ascii representation of the input string. ++ * @param content The string to output to the specified file. ++ * @param file_name The name of the target file to set the content. ++ * @return If the action is successful. ++ */ ++bool SetStringToASCIIFile(const std::string &content, ++ const std::string &file_name); ++ + /** + * @brief Parses the content of the file specified by the file_name as ascii + * representation of protobufs, and merges the parsed content to the +diff --git a/cyber/common/file_test.cc b/cyber/common/file_test.cc +index addd677..853daad 100644 +--- a/cyber/common/file_test.cc ++++ b/cyber/common/file_test.cc +@@ -120,9 +120,9 @@ TEST(FileTest, Glob) { + EXPECT_THAT( + Glob("/apol?o/modules/p*"), + testing::AllOf( +- testing::Contains(std::string("/apollo/modules/perception")), +- testing::Contains(std::string("/apollo/modules/planning")), +- testing::Contains(std::string("/apollo/modules/prediction")))); ++ testing::Contains(std::string("modules/perception")), ++ testing::Contains(std::string("modules/planning")), ++ testing::Contains(std::string("modules/prediction")))); + } + + TEST(FileTest, GetAbsolutePath) { +diff --git a/cyber/common/global_data.cc b/cyber/common/global_data.cc +index 7d94f1b..4a54063 100644 +--- a/cyber/common/global_data.cc ++++ b/cyber/common/global_data.cc +@@ -103,6 +103,51 @@ bool GlobalData::IsMockTimeMode() const { + return clock_mode_ == ClockMode::MODE_MOCK; + } + ++bool GlobalData::IsChannelEnableArenaShm(std::string channel_name) const { ++ if (!config_.has_transport_conf() || ++ !config_.transport_conf().has_shm_conf() || ++ !config_.transport_conf().shm_conf().has_arena_shm_conf()) { ++ return false; ++ } ++ bool found = false; ++ for (auto arena_channel_conf : config_.transport_conf() ++ .shm_conf() ++ .arena_shm_conf() ++ .arena_channel_conf()) { ++ if (channel_name == arena_channel_conf.channel_name()) { ++ found = true; ++ break; ++ } ++ } ++ return found; ++} ++ ++bool GlobalData::IsChannelEnableArenaShm(uint64_t channel_id) const { ++ auto channel_name = ++ cyber::common::GlobalData::Instance()->GetChannelById(channel_id); ++ return IsChannelEnableArenaShm(channel_name); ++} ++ ++apollo::cyber::proto::ArenaChannelConf GlobalData::GetChannelArenaConf( ++ std::string channel_name) const& { ++ for (auto arena_channel_conf : config_.transport_conf() ++ .shm_conf() ++ .arena_shm_conf() ++ .arena_channel_conf()) { ++ if (channel_name == arena_channel_conf.channel_name()) { ++ return arena_channel_conf; ++ } ++ } ++ return apollo::cyber::proto::ArenaChannelConf(); ++} ++ ++apollo::cyber::proto::ArenaChannelConf GlobalData::GetChannelArenaConf( ++ uint64_t channel_id) const& { ++ auto channel_name = ++ cyber::common::GlobalData::Instance()->GetChannelById(channel_id); ++ return GetChannelArenaConf(channel_name); ++} ++ + void GlobalData::InitHostInfo() { + char host_name[1024]; + gethostname(host_name, sizeof(host_name)); +diff --git a/cyber/common/global_data.h b/cyber/common/global_data.h +index 2e3a194..d3ce39b 100644 +--- a/cyber/common/global_data.h ++++ b/cyber/common/global_data.h +@@ -21,6 +21,7 @@ + #include + + #include "cyber/proto/cyber_conf.pb.h" ++#include "cyber/proto/transport_conf.pb.h" + + #include "cyber/base/atomic_hash_map.h" + #include "cyber/base/atomic_rw_lock.h" +@@ -64,6 +65,13 @@ class GlobalData { + bool IsRealityMode() const; + bool IsMockTimeMode() const; + ++ bool IsChannelEnableArenaShm(std::string channel_name) const; ++ bool IsChannelEnableArenaShm(uint64_t channel_id) const; ++ apollo::cyber::proto::ArenaChannelConf GetChannelArenaConf( ++ std::string channel_name) const&; ++ apollo::cyber::proto::ArenaChannelConf GetChannelArenaConf( ++ uint64_t channel_id) const&; ++ + static uint64_t GenerateHashId(const std::string& name) { + return common::Hash(name); + } +diff --git a/cyber/component/component.h b/cyber/component/component.h +index 4b36fd7..b1700b6 100644 +--- a/cyber/component/component.h ++++ b/cyber/component/component.h +@@ -30,6 +30,8 @@ + #include "cyber/croutine/routine_factory.h" + #include "cyber/data/data_visitor.h" + #include "cyber/scheduler/scheduler.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/time/time.h" + + namespace apollo { + namespace cyber { +@@ -181,15 +183,31 @@ bool Component::Initialize( + reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); + reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + ++ auto role_attr = std::make_shared(); ++ role_attr->set_node_name(config.name()); ++ role_attr->set_channel_name(config.readers(0).channel()); ++ + std::weak_ptr> self = + std::dynamic_pointer_cast>(shared_from_this()); +- auto func = [self](const std::shared_ptr& msg) { ++ auto func = [self, role_attr](const std::shared_ptr& msg) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + ptr->Process(msg); + } else { + AERROR << "Component object has been destroyed."; + } ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + }; + + std::shared_ptr> reader = nullptr; +@@ -257,6 +275,10 @@ bool Component::Initialize( + reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); + reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + ++ auto role_attr = std::make_shared(); ++ role_attr->set_node_name(config.name()); ++ role_attr->set_channel_name(config.readers(0).channel()); ++ + std::shared_ptr> reader0 = nullptr; + if (cyber_likely(is_reality_mode)) { + reader0 = node_->template CreateReader(reader_cfg); +@@ -267,12 +289,24 @@ bool Component::Initialize( + auto blocker1 = blocker::BlockerManager::Instance()->GetBlocker( + config.readers(1).channel()); + +- auto func = [self, blocker1](const std::shared_ptr& msg0) { ++ auto func = [self, blocker1, role_attr](const std::shared_ptr& msg0) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + if (!blocker1->IsPublishedEmpty()) { + auto msg1 = blocker1->GetLatestPublishedPtr(); + ptr->Process(msg0, msg1); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + } + } else { + AERROR << "Component object has been destroyed."; +@@ -295,11 +329,23 @@ bool Component::Initialize( + auto sched = scheduler::Instance(); + std::weak_ptr> self = + std::dynamic_pointer_cast>(shared_from_this()); +- auto func = [self](const std::shared_ptr& msg0, +- const std::shared_ptr& msg1) { ++ auto func = [self, role_attr](const std::shared_ptr& msg0, ++ const std::shared_ptr& msg1) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + ptr->Process(msg0, msg1); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + } else { + AERROR << "Component object has been destroyed."; + } +@@ -359,6 +405,11 @@ bool Component::Initialize( + reader_cfg.channel_name = config.readers(0).channel(); + reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); + reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); ++ ++ auto role_attr = std::make_shared(); ++ role_attr->set_node_name(config.name()); ++ role_attr->set_channel_name(config.readers(0).channel()); ++ + std::shared_ptr> reader0 = nullptr; + if (cyber_likely(is_reality_mode)) { + reader0 = node_->template CreateReader(reader_cfg); +@@ -372,13 +423,26 @@ bool Component::Initialize( + auto blocker2 = blocker::BlockerManager::Instance()->GetBlocker( + config.readers(2).channel()); + +- auto func = [self, blocker1, blocker2](const std::shared_ptr& msg0) { ++ auto func = [self, blocker1, blocker2, ++ role_attr](const std::shared_ptr& msg0) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + if (!blocker1->IsPublishedEmpty() && !blocker2->IsPublishedEmpty()) { + auto msg1 = blocker1->GetLatestPublishedPtr(); + auto msg2 = blocker2->GetLatestPublishedPtr(); + ptr->Process(msg0, msg1, msg2); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + } + } else { + AERROR << "Component object has been destroyed."; +@@ -404,12 +468,24 @@ bool Component::Initialize( + std::weak_ptr> self = + std::dynamic_pointer_cast>( + shared_from_this()); +- auto func = [self](const std::shared_ptr& msg0, +- const std::shared_ptr& msg1, +- const std::shared_ptr& msg2) { ++ auto func = [self, role_attr](const std::shared_ptr& msg0, ++ const std::shared_ptr& msg1, ++ const std::shared_ptr& msg2) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + ptr->Process(msg0, msg1, msg2); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + } else { + AERROR << "Component object has been destroyed."; + } +@@ -476,6 +552,10 @@ bool Component::Initialize(const ComponentConfig& config) { + reader_cfg.qos_profile.CopyFrom(config.readers(0).qos_profile()); + reader_cfg.pending_queue_size = config.readers(0).pending_queue_size(); + ++ auto role_attr = std::make_shared(); ++ role_attr->set_node_name(config.name()); ++ role_attr->set_channel_name(config.readers(0).channel()); ++ + std::shared_ptr> reader0 = nullptr; + if (cyber_likely(is_reality_mode)) { + reader0 = node_->template CreateReader(reader_cfg); +@@ -491,8 +571,9 @@ bool Component::Initialize(const ComponentConfig& config) { + auto blocker3 = blocker::BlockerManager::Instance()->GetBlocker( + config.readers(3).channel()); + +- auto func = [self, blocker1, blocker2, +- blocker3](const std::shared_ptr& msg0) { ++ auto func = [self, blocker1, blocker2, blocker3, ++ role_attr](const std::shared_ptr& msg0) { ++ auto start_time = Time::Now().ToMicrosecond(); + auto ptr = self.lock(); + if (ptr) { + if (!blocker1->IsPublishedEmpty() && !blocker2->IsPublishedEmpty() && +@@ -501,6 +582,17 @@ bool Component::Initialize(const ComponentConfig& config) { + auto msg2 = blocker2->GetLatestPublishedPtr(); + auto msg3 = blocker3->GetLatestPublishedPtr(); + ptr->Process(msg0, msg1, msg2, msg3); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } + } + } else { + AERROR << "Component object has been destroyed."; +@@ -527,16 +619,29 @@ bool Component::Initialize(const ComponentConfig& config) { + auto sched = scheduler::Instance(); + std::weak_ptr> self = + std::dynamic_pointer_cast>(shared_from_this()); +- auto func = +- [self](const std::shared_ptr& msg0, const std::shared_ptr& msg1, +- const std::shared_ptr& msg2, const std::shared_ptr& msg3) { +- auto ptr = self.lock(); +- if (ptr) { +- ptr->Process(msg0, msg1, msg2, msg3); +- } else { +- AERROR << "Component object has been destroyed." << std::endl; +- } +- }; ++ auto func = [self, role_attr](const std::shared_ptr& msg0, ++ const std::shared_ptr& msg1, ++ const std::shared_ptr& msg2, ++ const std::shared_ptr& msg3) { ++ auto start_time = Time::Now().ToMicrosecond(); ++ auto ptr = self.lock(); ++ if (ptr) { ++ ptr->Process(msg0, msg1, msg2, msg3); ++ auto end_time = Time::Now().ToMicrosecond(); ++ // sampling proc latency and cyber latency in microsecond ++ uint64_t process_start_time; ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ *role_attr, end_time - start_time); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ *role_attr, &process_start_time) && ++ (start_time - process_start_time) > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ *role_attr, start_time - process_start_time); ++ } ++ } else { ++ AERROR << "Component object has been destroyed." << std::endl; ++ } ++ }; + + std::vector config_list; + for (auto& reader : readers_) { +diff --git a/cyber/component/timer_component.cc b/cyber/component/timer_component.cc +index 3248708..6cf96e0 100644 +--- a/cyber/component/timer_component.cc ++++ b/cyber/component/timer_component.cc +@@ -16,6 +16,7 @@ + + #include "cyber/component/timer_component.h" + ++#include "cyber/statistics/statistics.h" + #include "cyber/timer/timer.h" + + namespace apollo { +@@ -44,9 +45,21 @@ bool TimerComponent::Initialize(const TimerComponentConfig& config) { + } + interval_ = config.interval(); + ++ auto role_attr = std::make_shared(); ++ role_attr->set_node_name(config.name()); ++ role_attr->set_channel_name(statistics::TIMER_COMPONENT_CHAN_NAME); ++ statistics::Statistics::Instance()->RegisterChanVar(*role_attr); ++ + std::shared_ptr self = + std::dynamic_pointer_cast(shared_from_this()); +- auto func = [self]() { self->Process(); }; ++ auto func = [self, role_attr]() { ++ auto start_time = Time::Now().ToNanosecond(); ++ self->Process(); ++ auto end_time = Time::Now().ToNanosecond(); ++ // sampling proc latency in microsecond ++ statistics::Statistics::Instance()->SamplingProcLatency< ++ uint64_t>(*role_attr, (end_time-start_time)/1000); ++ }; + timer_.reset(new Timer(config.interval(), func, false)); + timer_->Start(); + return true; +diff --git a/cyber/conf/cyber.pb.conf b/cyber/conf/cyber.pb.conf +index 2ce5045..8cbf0f4 100644 +--- a/cyber/conf/cyber.pb.conf ++++ b/cyber/conf/cyber.pb.conf +@@ -24,6 +24,29 @@ + # max_history_depth: 1000 + # } + # } ++# ++transport_conf { ++ communication_mode { ++ same_proc: INTRA ++ diff_proc: SHM ++ diff_host: RTPS ++ } ++ participant_attr { ++ lease_duration: 12 ++ announcement_period: 3 ++ domain_id_gain: 250 ++ port_base: 7400 ++ } ++ shm_conf { ++ arena_shm_conf { ++ arena_channel_conf { ++ channel_name: "/apollo/msg" ++ max_msg_size: 33554432 ++ max_pool_size: 32 ++ } ++ } ++ } ++} + + run_mode_conf { + run_mode: MODE_REALITY +diff --git a/cyber/context/BUILD b/cyber/context/BUILD +index 8628958..3dffa88 100644 +--- a/cyber/context/BUILD ++++ b/cyber/context/BUILD +@@ -19,6 +19,7 @@ apollo_cc_test( + size = "small", + srcs = ["context_test.cc"], + linkstatic = True, ++ linkopts = ["-lm"], + deps = [ + ":cyber_context", + "@com_google_googletest//:gtest_main", +diff --git a/cyber/cyberfile.xml b/cyber/cyberfile.xml +index 3f0195d..5601e16 100644 +--- a/cyber/cyberfile.xml ++++ b/cyber/cyberfile.xml +@@ -16,7 +16,7 @@ + //cyber + + libncurses5-dev +- libuuid1 ++ uuid-dev + + 3rd-rules-python + 3rd-grpc +@@ -26,7 +26,10 @@ + 3rd-bazel-skylib + + 3rd-protobuf +- 3rd-fastrtps ++ ++ 3rd-fastdds-wrap ++ 3rd-proj ++ 3rd-eigen3 + 3rd-glog + 3rd-gflags + common-msgs +@@ -36,4 +39,10 @@ + libtinyxml2-dev + bazel-extend-tools + ++ libunwind-dev ++ nethogs ++ sysstat ++ gperftools ++ bvar ++ + +diff --git a/cyber/examples/common_component_example/common.launch b/cyber/examples/common_component_example/common.launch +index 2dd31bf..f32358e 100644 +--- a/cyber/examples/common_component_example/common.launch ++++ b/cyber/examples/common_component_example/common.launch +@@ -2,6 +2,8 @@ + + common + /apollo/cyber/examples/common_component_example/common.dag ++ /apollo/example_cpu.prof ++ /apollo/example_mem.prof + common + + +diff --git a/cyber/examples/service.cc b/cyber/examples/service.cc +index babe651..8aaf561 100644 +--- a/cyber/examples/service.cc ++++ b/cyber/examples/service.cc +@@ -40,7 +40,7 @@ int main(int argc, char* argv[]) { + while (apollo::cyber::OK()) { + auto res = client->SendRequest(driver_msg); + if (res != nullptr) { +- AINFO << "client: responese: " << res->ShortDebugString(); ++ AINFO << "client: response: " << res->ShortDebugString(); + } else { + AINFO << "client: service may not ready."; + } +diff --git a/cyber/init.cc b/cyber/init.cc +index 86cd48b..a53cb22 100644 +--- a/cyber/init.cc ++++ b/cyber/init.cc +@@ -22,10 +22,14 @@ + + #include + #include ++#include + #include ++#include + #include + #include + ++#include "gflags/gflags.h" ++ + #include "cyber/proto/clock.pb.h" + + #include "cyber/binary.h" +@@ -36,6 +40,7 @@ + #include "cyber/node/node.h" + #include "cyber/scheduler/scheduler.h" + #include "cyber/service_discovery/topology_manager.h" ++#include "cyber/statistics/statistics.h" + #include "cyber/sysmo/sysmo.h" + #include "cyber/task/task.h" + #include "cyber/time/clock.h" +@@ -45,9 +50,6 @@ + namespace apollo { + namespace cyber { + +-using apollo::cyber::scheduler::Scheduler; +-using apollo::cyber::service_discovery::TopologyManager; +- + namespace { + + const std::string& kClockChannel = "/clock"; +@@ -93,7 +95,15 @@ void OnShutdown(int sig) { + + void ExitHandle() { Clear(); } + +-bool Init(const char* binary_name) { ++bool Init(const char* binary_name, const std::string& dag_info) { ++ const char* apollo_runtime_path = std::getenv("APOLLO_RUNTIME_PATH"); ++ if (apollo_runtime_path != nullptr) { ++ if (std::filesystem::is_directory( ++ std::filesystem::status(apollo_runtime_path))) { ++ std::filesystem::current_path(apollo_runtime_path); ++ } ++ } ++ + std::lock_guard lg(g_mutex); + if (GetState() != STATE_UNINITIALIZED) { + return false; +@@ -127,6 +137,24 @@ bool Init(const char* binary_name) { + }; + clock_node->CreateReader(kClockChannel, cb); + } ++ ++ if (dag_info != "") { ++ std::string dump_path; ++ if (dag_info.length() > 200) { ++ std::string truncated = dag_info.substr(0, 200); ++ dump_path = common::GetEnv("APOLLO_ENV_WORKROOT", "/apollo") + "/dumps/" + ++ truncated; ++ } else { ++ dump_path = common::GetEnv("APOLLO_ENV_WORKROOT", "/apollo") + "/dumps/" + ++ dag_info; ++ } ++ google::SetCommandLineOption("bvar_dump_file", dump_path.c_str()); ++ } else { ++ statistics::Statistics::Instance()->DisableChanVar(); ++ } ++ google::SetCommandLineOption("bvar_dump_exclude", "*qps"); ++ google::SetCommandLineOption("bvar_dump", "true"); ++ + return true; + } + +diff --git a/cyber/init.h b/cyber/init.h +index d28c8dc..bac78a6 100644 +--- a/cyber/init.h ++++ b/cyber/init.h +@@ -17,14 +17,17 @@ + #ifndef CYBER_INIT_H_ + #define CYBER_INIT_H_ + ++#include ++ + #include "cyber/common/log.h" + #include "cyber/state.h" + + namespace apollo { + namespace cyber { + +-bool Init(const char* binary_name); ++bool Init(const char* binary_name, const std::string& dag_info = ""); + void Clear(); ++void OnShutdown(int sig); + + } // namespace cyber + } // namespace apollo +diff --git a/cyber/mainboard/BUILD b/cyber/mainboard/BUILD +index 7ae3f85..05feac4 100644 +--- a/cyber/mainboard/BUILD ++++ b/cyber/mainboard/BUILD +@@ -12,9 +12,14 @@ apollo_cc_binary( + "module_controller.cc", + "module_controller.h", + ], +- linkopts = ["-pthread"], ++ linkopts = [ ++ "-pthread", ++ "-lprofiler", ++ "-ltcmalloc", ++ ], + deps = [ + "//cyber", ++ "//cyber/common:cyber_common", + "//cyber/plugin_manager:cyber_plugin_manager", + "//cyber/proto:dag_conf_cc_proto", + ], +diff --git a/cyber/mainboard/mainboard.cc b/cyber/mainboard/mainboard.cc +index b518e08..1abe162 100644 +--- a/cyber/mainboard/mainboard.cc ++++ b/cyber/mainboard/mainboard.cc +@@ -14,6 +14,11 @@ + * limitations under the License. + *****************************************************************************/ + ++#include ++ ++#include ++#include ++ + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/init.h" +@@ -21,6 +26,10 @@ + #include "cyber/mainboard/module_controller.h" + #include "cyber/state.h" + ++#include "gperftools/profiler.h" ++#include "gperftools/heap-profiler.h" ++#include "gperftools/malloc_extension.h" ++ + using apollo::cyber::mainboard::ModuleArgument; + using apollo::cyber::mainboard::ModuleController; + +@@ -29,8 +38,50 @@ int main(int argc, char** argv) { + ModuleArgument module_args; + module_args.ParseArgument(argc, argv); + ++ auto dag_list = module_args.GetDAGConfList(); ++ ++ std::string dag_info; ++ for (auto&& i = dag_list.begin(); i != dag_list.end(); i++) { ++ size_t pos = 0; ++ for (size_t j = 0; j < (*i).length(); j++) { ++ pos = ((*i)[j] == '/') ? j: pos; ++ } ++ if (i != dag_list.begin()) dag_info += "_"; ++ ++ if (pos == 0) { ++ dag_info += *i; ++ } else { ++ dag_info += ++ (pos == (*i).length()-1) ? (*i).substr(pos): (*i).substr(pos+1); ++ } ++ } ++ ++ if (module_args.GetProcessGroup() != ++ apollo::cyber::mainboard::DEFAULT_process_group_) { ++ dag_info = module_args.GetProcessGroup(); ++ } ++ + // initialize cyber +- apollo::cyber::Init(argv[0]); ++ apollo::cyber::Init(argv[0], dag_info); ++ ++ static bool enable_cpu_profile = module_args.GetEnableCpuprofile(); ++ static bool enable_mem_profile = module_args.GetEnableHeapprofile(); ++ std::signal(SIGTERM, [](int sig){ ++ apollo::cyber::OnShutdown(sig); ++ if (enable_cpu_profile) { ++ ProfilerStop(); ++ } ++ ++ if (enable_mem_profile) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++ }); ++ ++ if (module_args.GetEnableHeapprofile()) { ++ auto profile_filename = module_args.GetHeapProfileFilename(); ++ HeapProfilerStart(profile_filename.c_str()); ++ } + + // start module + ModuleController controller(module_args); +@@ -40,7 +91,22 @@ int main(int argc, char** argv) { + return -1; + } + ++ if (module_args.GetEnableCpuprofile()) { ++ auto profile_filename = module_args.GetProfileFilename(); ++ ProfilerStart(profile_filename.c_str()); ++ } ++ + apollo::cyber::WaitForShutdown(); ++ ++ if (module_args.GetEnableCpuprofile()) { ++ ProfilerStop(); ++ } ++ ++ if (module_args.GetEnableHeapprofile()) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++ + controller.Clear(); + AINFO << "exit mainboard."; + +diff --git a/cyber/mainboard/module_argument.cc b/cyber/mainboard/module_argument.cc +index f169583..7e59cea 100644 +--- a/cyber/mainboard/module_argument.cc ++++ b/cyber/mainboard/module_argument.cc +@@ -16,9 +16,15 @@ + + #include "cyber/mainboard/module_argument.h" + ++#include "cyber/common/environment.h" ++ + #include + #include + ++#if __has_include("gperftools/profiler.h") ++#include "gperftools/profiler.h" ++#endif ++ + using apollo::cyber::common::GlobalData; + + namespace apollo { +@@ -38,6 +44,14 @@ void ModuleArgument::DisplayUsage() { + "plugin\n" + << " --disable_plugin_autoload : default enable autoload " + "mode of plugins, use disable_plugin_autoload to ingore autoload\n" ++ << " -c, --cpuprofile: enable gperftools cpu profile\n" ++ << " -o, --profile_filename=filename: the filename to dump the " ++ "profile to, default value is ${process_group}_cpu.prof. Only work " ++ "with -c option\n" ++ << " -H, --heapprofile: enable gperftools heap profile\n" ++ << " -O, --heapprofile_filename=filename: the filename to dump the " ++ "profile to, default value is ${process_group}_mem.prof. Only work " ++ "with -c option\n" + << "Example:\n" + << " " << binary_name_ << " -h\n" + << " " << binary_name_ << " -d dag_conf_file1 -d dag_conf_file2 " +@@ -57,6 +71,27 @@ void ModuleArgument::ParseArgument(const int argc, char* const argv[]) { + sched_name_ = DEFAULT_sched_name_; + } + ++ if (enable_cpuprofile_ && profile_filename_.empty()) { ++ auto pwd = common::GetEnv("PWD"); ++ profile_filename_ = pwd + "/" + process_group_ + std::string("_cpu.prof"); ++ } ++ ++ if (profile_filename_[0] != '/') { ++ auto pwd = common::GetEnv("PWD"); ++ profile_filename_ = pwd + "/" + profile_filename_; ++ } ++ ++ if (enable_heapprofile_ && heapprofile_filename_.empty()) { ++ auto pwd = common::GetEnv("PWD"); ++ heapprofile_filename_ = ++ pwd + "/" + process_group_ + std::string("_mem.prof"); ++ } ++ ++ if (heapprofile_filename_[0] != '/') { ++ auto pwd = common::GetEnv("PWD"); ++ heapprofile_filename_ = pwd + "/" + heapprofile_filename_; ++ } ++ + GlobalData::Instance()->SetProcessGroup(process_group_); + GlobalData::Instance()->SetSchedName(sched_name_); + AINFO << "binary_name_ is " << binary_name_ << ", process_group_ is " +@@ -69,7 +104,7 @@ void ModuleArgument::ParseArgument(const int argc, char* const argv[]) { + void ModuleArgument::GetOptions(const int argc, char* const argv[]) { + opterr = 0; // extern int opterr + int long_index = 0; +- const std::string short_opts = "hd:p:s:"; ++ const std::string short_opts = "hd:p:s:co:HO:"; + static const struct option long_opts[] = { + {"help", no_argument, nullptr, 'h'}, + {"dag_conf", required_argument, nullptr, 'd'}, +@@ -78,6 +113,10 @@ void ModuleArgument::GetOptions(const int argc, char* const argv[]) { + {"plugin", required_argument, nullptr, ARGS_OPT_CODE_PLUGIN}, + {"disable_plugin_autoload", no_argument, nullptr, + ARGS_OPT_CODE_DISABLE_PLUGIN_AUTOLOAD}, ++ {"cpuprofile", no_argument, nullptr, 'c'}, ++ {"profile_filename", required_argument, nullptr, 'o'}, ++ {"heapprofile", no_argument, nullptr, 'H'}, ++ {"heapprofile_filename", required_argument, nullptr, 'O'}, + {NULL, no_argument, nullptr, 0}}; + + // log command for info +@@ -120,7 +159,25 @@ void ModuleArgument::GetOptions(const int argc, char* const argv[]) { + plugin_description_list_.emplace_back(std::string(optarg)); + break; + case ARGS_OPT_CODE_DISABLE_PLUGIN_AUTOLOAD: +- disable_plugin_autoload_ = true; ++ disable_plugin_autoload_ = true; ++ break; ++ case 'c': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_cpuprofile_ = true; ++ break; ++ case 'o': ++ profile_filename_ = std::string(optarg); ++ break; ++ case 'H': ++#ifndef BASE_PROFILER_H_ ++ AWARN << "gperftools not installed, ignore perf parameters"; ++#endif ++ enable_heapprofile_ = true; ++ break; ++ case 'O': ++ heapprofile_filename_ = std::string(optarg); + break; + case 'h': + DisplayUsage(); +diff --git a/cyber/mainboard/module_argument.h b/cyber/mainboard/module_argument.h +index 5f2ed9f..ddc1dfa 100644 +--- a/cyber/mainboard/module_argument.h ++++ b/cyber/mainboard/module_argument.h +@@ -47,6 +47,12 @@ class ModuleArgument { + const std::string& GetSchedName() const; + const std::list& GetDAGConfList() const; + const std::list& GetPluginDescriptionList() const; ++ const bool GetEnableCpuprofile() const { return enable_cpuprofile_; } ++ const std::string GetProfileFilename() const { return profile_filename_; } ++ const bool GetEnableHeapprofile() const { return enable_heapprofile_; } ++ const std::string GetHeapProfileFilename() const { ++ return heapprofile_filename_; ++ } + const bool& GetDisablePluginsAutoLoad() const; + + private: +@@ -55,6 +61,10 @@ class ModuleArgument { + std::string binary_name_; + std::string process_group_; + std::string sched_name_; ++ bool enable_cpuprofile_ = false; ++ std::string profile_filename_; ++ bool enable_heapprofile_ = false; ++ std::string heapprofile_filename_; + bool disable_plugin_autoload_ = false; + }; + +diff --git a/cyber/message/BUILD b/cyber/message/BUILD +index e12d060..f0b690e 100644 +--- a/cyber/message/BUILD ++++ b/cyber/message/BUILD +@@ -1,5 +1,5 @@ + load("//tools:cpplint.bzl", "cpplint") +-load("//tools:apollo_package.bzl", "apollo_package", "apollo_cc_library", "apollo_cc_test", "apollo_cc_binary") ++load("//tools:apollo_package.bzl", "apollo_cc_binary", "apollo_cc_library", "apollo_cc_test", "apollo_package") + + package(default_visibility = ["//visibility:public"]) + +@@ -15,7 +15,12 @@ apollo_cc_test( + + apollo_cc_library( + name = "cyber_message", ++ srcs = [ ++ "protobuf_factory.cc", ++ ], + hdrs = [ ++ "arena_manager_base.h", ++ "arena_message_wrapper.h", + "message_header.h", + "message_traits.h", + "protobuf_factory.h", +@@ -25,9 +30,6 @@ apollo_cc_library( + "raw_message.h", + "raw_message_traits.h", + ], +- srcs = [ +- "protobuf_factory.cc", +- ], + deps = [ + "//cyber/common:cyber_common", + "//cyber/proto:proto_desc_cc_proto", +@@ -67,4 +69,5 @@ apollo_cc_test( + ) + + apollo_package() ++ + cpplint() +diff --git a/cyber/message/arena_manager_base.h b/cyber/message/arena_manager_base.h +new file mode 100644 +index 0000000..aa8209a +--- /dev/null ++++ b/cyber/message/arena_manager_base.h +@@ -0,0 +1,62 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_MESSAGE_ARENA_MANAGER_BASE_H_ ++#define CYBER_MESSAGE_ARENA_MANAGER_BASE_H_ ++ ++#include ++#include ++ ++namespace apollo { ++namespace cyber { ++namespace message { ++ ++class ArenaMessageWrapper; ++ ++class ArenaManagerBase { ++ public: ++ ArenaManagerBase() {} ++ virtual ~ArenaManagerBase() {} ++ ++ virtual uint64_t GetBaseAddress(const ArenaMessageWrapper* wrapper) { ++ return 0; ++ } ++ ++ virtual void* SetMessage(ArenaMessageWrapper* wrapper, ++ const void* message) = 0; ++ virtual void* GetMessage(ArenaMessageWrapper* wrapper) = 0; ++ ++ std::shared_ptr CreateMessageWrapper() { ++ return std::make_shared(this); ++ } ++ ++ template ++ MessageT* SetMessage(ArenaMessageWrapper* wrapper, const MessageT& message) { ++ void* msg = SetMessage(wrapper, reinterpret_cast(&message)); ++ return reinterpret_cast(msg); ++ } ++ ++ template ++ MessageT* GetMessage(ArenaMessageWrapper* wrapper) { ++ void* msg = GetMessage(wrapper); ++ return reinterpret_cast(msg); ++ } ++}; ++ ++} // namespace message ++} // namespace cyber ++} // namespace apollo ++ ++#endif +diff --git a/cyber/message/arena_message_wrapper.h b/cyber/message/arena_message_wrapper.h +new file mode 100644 +index 0000000..92e573a +--- /dev/null ++++ b/cyber/message/arena_message_wrapper.h +@@ -0,0 +1,145 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_MESSAGE_ARENA_MESSAGE_WRAPPER_H_ ++#define CYBER_MESSAGE_ARENA_MESSAGE_WRAPPER_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/message/arena_manager_base.h" ++ ++namespace apollo { ++namespace cyber { ++namespace message { ++ ++union ArenaMessageWrapperMeta { ++ struct { ++ uint64_t version_; ++ uint64_t addr_offset_; ++ } struct_; ++ uint8_t bytes_[128]; ++}; ++ ++union ArenaMessageWrapperExtended { ++ uint8_t bytes_[256]; ++}; ++ ++union ArenaMessageWrapperDataStruct { ++ struct { ++ union ArenaMessageWrapperMeta meta_; ++ union ArenaMessageWrapperExtended extended_; ++ } struct_; ++ uint8_t bytes_[1024]; ++}; ++ ++class ArenaMessageWrapper { ++ public: ++ static const uint64_t kDefaultVersion = 1L; ++ ++ ArenaMessageWrapper() : arena_manager_(nullptr) { ++ data_.struct_.meta_.struct_.version_ = kDefaultVersion; ++ data_.struct_.meta_.struct_.addr_offset_ = 0; ++ } ++ ++ explicit ArenaMessageWrapper(ArenaManagerBase* arena_manager) ++ : arena_manager_(arena_manager) { ++ data_.struct_.meta_.struct_.version_ = kDefaultVersion; ++ data_.struct_.meta_.struct_.addr_offset_ = 0; ++ } ++ ++ virtual ~ArenaMessageWrapper() {} ++ ++ void SetVersion(uint64_t version) { ++ data_.struct_.meta_.struct_.version_ = version; ++ } ++ uint64_t GetVersion() const { return data_.struct_.meta_.struct_.version_; } ++ ++ uint64_t GetMessageAddress() const { ++ return arena_manager_->GetBaseAddress(this) + ++ data_.struct_.meta_.struct_.addr_offset_; ++ } ++ ++ void* GetData() { return reinterpret_cast(data_.bytes_); } ++ ++ bool FillMeta(void* meta, uint64_t size) { ++ if (size > 128) { ++ return false; ++ } ++ memcpy(&data_.struct_.meta_, meta, size); ++ return true; ++ } ++ ++ ArenaMessageWrapperMeta* GetMeta() { ++ return reinterpret_cast( ++ data_.struct_.meta_.bytes_); ++ } ++ ++ bool FillExtended(void* extended, uint64_t size) { ++ if (size > 256) { ++ return false; ++ } ++ memcpy(&data_.struct_.extended_, extended, size); ++ return true; ++ } ++ ++ template ++ T* GetExtended() { ++ return reinterpret_cast(data_.struct_.extended_.bytes_); ++ } ++ ++ template ++ MessageT* GetMessage() { ++ // uint64_t base_address = ++ // reinterpret_cast(arena_manager_->GetBaseAddress()); ++ // uint64_t message_address = base_address + data_.struct_.addr_offset_; ++ // return std::shared_ptr( ++ // reinterpret_cast(GetMessageAddress())); ++ auto msg_ptr = arena_manager_->GetMessage(this); ++ return msg_ptr; ++ } ++ ++ template ++ MessageT* SetMessage(const MessageT& message) { ++ auto msg_ptr = arena_manager_->SetMessage(this, message); ++ return msg_ptr; ++ } ++ ++ private: ++ // union { ++ // struct { ++ // union { ++ // uint64_t version_; ++ // uint64_t addr_offset_; ++ // uint8_t bytes_[128]; ++ // } meta_; ++ // union { ++ // uint8_t bytes_[256]; ++ // } extended_; ++ // } struct_; ++ // uint8_t bytes_[1024]; ++ // } data_; ++ ArenaMessageWrapperDataStruct data_; ++ // message holder ++ std::shared_ptr message_; ++ ArenaManagerBase* arena_manager_; ++}; ++ ++} // namespace message ++} // namespace cyber ++} // namespace apollo ++ ++#endif +diff --git a/cyber/message/message_traits.h b/cyber/message/message_traits.h +index 506203b..d5edc2f 100644 +--- a/cyber/message/message_traits.h ++++ b/cyber/message/message_traits.h +@@ -18,9 +18,11 @@ + #define CYBER_MESSAGE_MESSAGE_TRAITS_H_ + + #include ++#include + + #include "cyber/base/macros.h" + #include "cyber/common/log.h" ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/message_header.h" + #include "cyber/message/protobuf_traits.h" + #include "cyber/message/py_message_traits.h" +@@ -40,6 +42,9 @@ DEFINE_TYPE_TRAIT(HasSerializeToString, SerializeToString) + DEFINE_TYPE_TRAIT(HasParseFromString, ParseFromString) + DEFINE_TYPE_TRAIT(HasSerializeToArray, SerializeToArray) + DEFINE_TYPE_TRAIT(HasParseFromArray, ParseFromArray) ++DEFINE_TYPE_TRAIT(HasSerializeToArenaMessageWrapper, ++ SerializeToArenaMessageWrapper) ++DEFINE_TYPE_TRAIT(HasParseFromArenaMessageWrapper, ParseFromArenaMessageWrapper) + + template + class HasSerializer { +@@ -141,6 +146,26 @@ int FullByteSize(const T& message) { + return content_size + static_cast(sizeof(MessageHeader)); + } + ++template ++typename std::enable_if::value, bool>::type ++ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, T* message, ++ T** message_ptr) { ++ return message->ParseFromArenaMessageWrapper(wrapper, message_ptr); ++} ++ ++template ::value && ++ !std::is_base_of::value, ++ bool>::type = 0> ++bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, T* message, ++ T** message_ptr) { ++ (void)wrapper; ++ (void)message; ++ (void)message_ptr; ++ return false; ++} ++ + template + typename std::enable_if::value, bool>::type ParseFromArray( + const void* data, int size, T* message) { +@@ -184,6 +209,27 @@ typename std::enable_if::value, bool>::type ParseFromHC( + return false; + } + ++template ++typename std::enable_if::value, bool>::type ++SerializeToArenaMessageWrapper(const T& message, ArenaMessageWrapper* wrapper, ++ T** message_ptr) { ++ return message->SerializeToArenaMessageWrapper(wrapper, message_ptr); ++} ++ ++template ::value && ++ !std::is_base_of::value, ++ bool>::type = 0> ++bool SerializeToArenaMessageWrapper(const T& message, ++ ArenaMessageWrapper* wrapper, ++ T** message_ptr) { ++ (void)message; ++ (void)wrapper; ++ (void)message_ptr; ++ return false; ++} ++ + template + typename std::enable_if::value, bool>::type + SerializeToArray(const T& message, void* data, int size) { +diff --git a/cyber/message/protobuf_traits.h b/cyber/message/protobuf_traits.h +index 0a4317a..a03f690 100644 +--- a/cyber/message/protobuf_traits.h ++++ b/cyber/message/protobuf_traits.h +@@ -21,6 +21,7 @@ + #include + #include + ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/protobuf_factory.h" + + namespace apollo { +@@ -69,6 +70,28 @@ bool RegisterMessage(const MessageT& message) { + return ProtobufFactory::Instance()->RegisterMessage(message); + } + ++template ::value, ++ bool>::type = true> ++bool SerializeToArenaMessageWrapper(const MessageT& message, ++ ArenaMessageWrapper* wrapper, ++ MessageT** message_ptr) { ++ *message_ptr = wrapper->SetMessage(message); ++ return true; ++} ++ ++template ::value, ++ bool>::type = true> ++bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, ++ MessageT* message, MessageT** message_ptr) { ++ *message_ptr = wrapper->GetMessage(); ++ // message->CopyFrom(*message_ptr); ++ return true; ++} ++ + } // namespace message + } // namespace cyber + } // namespace apollo +diff --git a/cyber/message/raw_message.h b/cyber/message/raw_message.h +index 85accc7..bc94866 100644 +--- a/cyber/message/raw_message.h ++++ b/cyber/message/raw_message.h +@@ -22,6 +22,7 @@ + #include + #include + ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/protobuf_factory.h" + + namespace apollo { +@@ -82,6 +83,10 @@ struct RawMessage { + return true; + } + ++ // bool SerializeToArenaMessageWrapper(ArenaMessageWrapper *wrapper) const { ++ // return true; ++ // } ++ + bool ParseFromArray(const void *data, int size) { + if (data == nullptr || size <= 0) { + return false; +@@ -96,6 +101,10 @@ struct RawMessage { + return true; + } + ++ // bool ParseFromArenaMessageWrapper(const ArenaMessageWrapper &wrapper) { ++ // return true; ++ // } ++ + int ByteSize() const { return static_cast(message.size()); } + + static std::string TypeName() { return "apollo.cyber.message.RawMessage"; } +diff --git a/cyber/message/raw_message_traits.h b/cyber/message/raw_message_traits.h +index 70e868f..5d4b21f 100644 +--- a/cyber/message/raw_message_traits.h ++++ b/cyber/message/raw_message_traits.h +@@ -21,6 +21,7 @@ + #include + #include + ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/raw_message.h" + + namespace apollo { +@@ -38,6 +39,16 @@ inline bool ParseFromArray(const void* data, int size, RawMessage* message) { + + inline int ByteSize(const RawMessage& message) { return message.ByteSize(); } + ++inline bool SerializeToArenaMessageWrapper(const RawMessage& message, ++ ArenaMessageWrapper* wrapper) { ++ return false; ++} ++ ++inline bool ParseFromArenaMessageWrapper(ArenaMessageWrapper* wrapper, ++ RawMessage* message) { ++ return false; ++} ++ + } // namespace message + } // namespace cyber + } // namespace apollo +diff --git a/cyber/node/BUILD b/cyber/node/BUILD +index 366d6b0..3d7bffc 100644 +--- a/cyber/node/BUILD ++++ b/cyber/node/BUILD +@@ -17,6 +17,7 @@ apollo_cc_library( + "writer.h", + "writer_base.h", + ], ++ linkopts = ["-lbvar"], + deps = [ + "//cyber/blocker:cyber_blocker", + "//cyber/common:cyber_common", +@@ -32,6 +33,7 @@ apollo_cc_library( + "//cyber/transport:cyber_transport", + "//cyber/event:cyber_event", + "//cyber/proto:role_attributes_cc_proto", ++ # "//cyber/statistics:apollo_statistics", + ], + ) + +diff --git a/cyber/node/node.cc b/cyber/node/node.cc +index b524121..0c974ca 100644 +--- a/cyber/node/node.cc ++++ b/cyber/node/node.cc +@@ -16,14 +16,9 @@ + + #include "cyber/node/node.h" + +-#include "cyber/common/global_data.h" +-#include "cyber/time/time.h" +- + namespace apollo { + namespace cyber { + +-using proto::RoleType; +- + Node::Node(const std::string& node_name, const std::string& name_space) + : node_name_(node_name), name_space_(name_space) { + node_channel_impl_.reset(new NodeChannelImpl(node_name)); +diff --git a/cyber/node/node.h b/cyber/node/node.h +index 87a3def..b03844b 100644 +--- a/cyber/node/node.h ++++ b/cyber/node/node.h +@@ -39,14 +39,14 @@ class TimerComponent; + * A module can have different types of communication by defining + * read/write and/or service/client in a node. + * @warning Duplicate name is not allowed in topo objects, such as node, +- * reader/writer, service/clinet in the topo. ++ * reader/writer, service/client in the topo. + */ + class Node { + public: + template + friend class Component; + friend class TimerComponent; +- friend bool Init(const char*); ++ friend bool Init(const char*, const std::string&); + friend std::unique_ptr CreateNode(const std::string&, + const std::string&); + virtual ~Node(); +diff --git a/cyber/node/reader.h b/cyber/node/reader.h +index 83f4fb5..5c098d0 100644 +--- a/cyber/node/reader.h ++++ b/cyber/node/reader.h +@@ -35,6 +35,7 @@ + #include "cyber/node/reader_base.h" + #include "cyber/scheduler/scheduler_factory.h" + #include "cyber/service_discovery/topology_manager.h" ++#include "cyber/statistics/statistics.h" + #include "cyber/time/time.h" + #include "cyber/transport/transport.h" + +@@ -259,11 +260,34 @@ bool Reader::Init() { + if (init_.exchange(true)) { + return true; + } ++ auto statistics_center = statistics::Statistics::Instance(); ++ if (!statistics_center->RegisterChanVar(role_attr_)) { ++ AWARN << "Failed to register reader var!"; ++ } + std::function&)> func; + if (reader_func_ != nullptr) { + func = [this](const std::shared_ptr& msg) { ++ uint64_t process_start_time; ++ uint64_t proc_done_time; ++ uint64_t proc_start_time; ++ + this->Enqueue(msg); + this->reader_func_(msg); ++ // sampling proc latency in microsecond ++ proc_done_time = Time::Now().ToMicrosecond(); ++ proc_start_time = ++ static_cast(latest_recv_time_sec_ * 1000000UL); ++ ++ statistics::Statistics::Instance()->SamplingProcLatency( ++ this->role_attr_, (proc_done_time - proc_start_time)); ++ if (statistics::Statistics::Instance()->GetProcStatus( ++ this->role_attr_, &process_start_time)) { ++ auto cyber_latency = proc_start_time - process_start_time; ++ if (process_start_time > 0 && cyber_latency > 0) { ++ statistics::Statistics::Instance()->SamplingCyberLatency( ++ this->role_attr_, cyber_latency); ++ } ++ } + }; + } else { + func = [this](const std::shared_ptr& msg) { this->Enqueue(msg); }; +diff --git a/cyber/node/reader_base.h b/cyber/node/reader_base.h +index 57e393f..ae5caaf 100644 +--- a/cyber/node/reader_base.h ++++ b/cyber/node/reader_base.h +@@ -158,7 +158,7 @@ class ReaderBase { + /** + * @brief One Channel is related to one Receiver. + * ReceiverManager is in charge of attaching one Receiver to its responding +- * Channel. We pass a DataDispatche's callback func to this Receiver so when a ++ * Channel. We pass a DataDispatcher's callback func to this Receiver so when a + * message is received, it will be push to the `ChannelBuffer`, and + * `DataVisitor` will `Fetch` data and pass to `Reader`'s callback func + * +diff --git a/cyber/node/writer.h b/cyber/node/writer.h +index b4a7a69..aad5f25 100644 +--- a/cyber/node/writer.h ++++ b/cyber/node/writer.h +@@ -100,6 +100,12 @@ class Writer : public WriterBase { + */ + void GetReaders(std::vector* readers) override; + ++ /** ++ * @brief Acquire message instance to send ++ * ++ */ ++ std::shared_ptr AcquireMessage(); ++ + private: + void JoinTheTopology(); + void LeaveTheTopology(); +@@ -231,6 +237,23 @@ void Writer::GetReaders(std::vector* readers) { + channel_manager_->GetReadersOfChannel(role_attr_.channel_name(), readers); + } + ++template ++std::shared_ptr Writer::AcquireMessage() { ++ if (!WriterBase::IsInit()) { ++ AERROR << "Please Acquire message after init writer!"; ++ auto m = std::make_shared(); ++ return m; ++ } ++ ++ std::shared_ptr m(nullptr); ++ if (transmitter_->AcquireMessage(m)) { ++ return m; ++ } else { ++ m = std::make_shared(); ++ return m; ++ } ++} ++ + } // namespace cyber + } // namespace apollo + +diff --git a/cyber/node/writer_base.h b/cyber/node/writer_base.h +index 6e2fa22..389cb82 100644 +--- a/cyber/node/writer_base.h ++++ b/cyber/node/writer_base.h +@@ -83,6 +83,13 @@ class WriterBase { + return role_attr_.channel_name(); + } + ++ /** ++ * @brief Get Writer's Channel id ++ * ++ * @return const uint64_t& const reference to the channel id ++ */ ++ const uint64_t GetChannelId() const { return role_attr_.channel_id(); } ++ + /** + * @brief Is Writer initialized? + * +diff --git a/cyber/parameter/BUILD b/cyber/parameter/BUILD +index d4868ac..8639b90 100644 +--- a/cyber/parameter/BUILD ++++ b/cyber/parameter/BUILD +@@ -21,7 +21,7 @@ apollo_cc_library( + "//cyber/proto:parameter_cc_proto", + "//cyber/node:cyber_node", + "//cyber/service:cyber_service", +- "@fastrtps", ++ "@fastdds", + ], + ) + +diff --git a/cyber/parameter/parameter_client.h b/cyber/parameter/parameter_client.h +index c0345f3..5c29701 100644 +--- a/cyber/parameter/parameter_client.h ++++ b/cyber/parameter/parameter_client.h +@@ -69,7 +69,7 @@ class ParameterClient { + * @brief Set the Parameter object + * + * @param parameter parameter to be set +- * @return true set parameter succues ++ * @return true set parameter success + * @return false 1. call service timeout + * 2. parameter not exists + * The corresponding log will be recorded at the same time +diff --git a/cyber/proto/BUILD b/cyber/proto/BUILD +index 118fb16..346e690 100644 +--- a/cyber/proto/BUILD ++++ b/cyber/proto/BUILD +@@ -47,10 +47,10 @@ proto_library( + name = "cyber_conf_proto", + srcs = ["cyber_conf.proto"], + deps = [ ++ ":perf_conf_proto", ++ ":run_mode_conf_proto", + ":scheduler_conf_proto", + ":transport_conf_proto", +- ":run_mode_conf_proto", +- ":perf_conf_proto", + ], + ) + +@@ -74,12 +74,17 @@ proto_library( + srcs = ["unit_test.proto"], + ) + ++proto_library( ++ name = "simple_proto", ++ srcs = ["simple.proto"], ++) ++ + proto_library( + name = "scheduler_conf_proto", + srcs = ["scheduler_conf.proto"], + deps = [ +- ":classic_conf_proto", + ":choreography_conf_proto", ++ ":classic_conf_proto", + ], + ) + +diff --git a/cyber/proto/simple.proto b/cyber/proto/simple.proto +new file mode 100644 +index 0000000..5cd64a0 +--- /dev/null ++++ b/cyber/proto/simple.proto +@@ -0,0 +1,12 @@ ++syntax = "proto2"; ++ ++package apollo.cyber.proto; ++ ++message SimpleMessage { ++ optional int32 integer = 1; ++ optional string text = 2; ++} ++ ++message SimpleRepeatedMessage { ++ repeated SimpleMessage message = 1; ++} +diff --git a/cyber/proto/transport_conf.proto b/cyber/proto/transport_conf.proto +index f7f34b2..b6db252 100644 +--- a/cyber/proto/transport_conf.proto ++++ b/cyber/proto/transport_conf.proto +@@ -14,10 +14,25 @@ message ShmMulticastLocator { + optional uint32 port = 2; + }; + ++message ArenaChannelConf { ++ optional string channel_name = 1; ++ // the acutal arena segment size is equal with max_msg_size * max_pool_size + meta, ++ // so max_msg_size * max_pool_size should be less than the limit of ArenaAddressAllocator: ++ // 2^31 - 128 * 1024 * 1024, which is hardcode in the underlying implementation ++ optional uint64 max_msg_size = 2 [default = 33554432]; ++ optional uint64 max_pool_size = 3 [default = 32]; ++ optional uint64 shared_buffer_size = 4 [default = 0]; ++}; ++ ++message ArenaShmConf { ++ repeated ArenaChannelConf arena_channel_conf = 1; ++}; ++ + message ShmConf { + optional string notifier_type = 1; + optional string shm_type = 2; + optional ShmMulticastLocator shm_locator = 3; ++ optional ArenaShmConf arena_shm_conf = 4; + }; + + message RtpsParticipantAttr { +diff --git a/cyber/python/cyber_py3/cyber.py b/cyber/python/cyber_py3/cyber.py +index 67912c2..466e414 100644 +--- a/cyber/python/cyber_py3/cyber.py ++++ b/cyber/python/cyber_py3/cyber.py +@@ -35,7 +35,7 @@ PY_CALLBACK_TYPE_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p) + APOLLO_DISTRIBUTION_HOME = os.environ.get( + 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') + +-if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): ++if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): + wrapper_lib_path = os.path.join( + APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") + +diff --git a/cyber/python/cyber_py3/cyber_time.py b/cyber/python/cyber_py3/cyber_time.py +index 303fb02..ba0f93c 100644 +--- a/cyber/python/cyber_py3/cyber_time.py ++++ b/cyber/python/cyber_py3/cyber_time.py +@@ -25,7 +25,7 @@ import sys + APOLLO_DISTRIBUTION_HOME = os.environ.get( + 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') + +-if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): ++if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): + wrapper_lib_path = os.path.join( + APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") + +diff --git a/cyber/python/cyber_py3/cyber_timer.py b/cyber/python/cyber_py3/cyber_timer.py +index 5c1911a..3123843 100644 +--- a/cyber/python/cyber_py3/cyber_timer.py ++++ b/cyber/python/cyber_py3/cyber_timer.py +@@ -30,7 +30,7 @@ APOLLO_DISTRIBUTION_HOME = os.environ.get( + 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') + + # init vars +-if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): ++if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): + wrapper_lib_path = os.path.join( + APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") + +diff --git a/cyber/python/cyber_py3/parameter.py b/cyber/python/cyber_py3/parameter.py +index 03a91bc..60ef028 100644 +--- a/cyber/python/cyber_py3/parameter.py ++++ b/cyber/python/cyber_py3/parameter.py +@@ -29,7 +29,7 @@ CYBER_DIR = os.path.split(CYBER_PATH)[0] + APOLLO_DISTRIBUTION_HOME = os.environ.get( + 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') + +-if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): ++if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): + wrapper_lib_path = os.path.join( + APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") + +diff --git a/cyber/python/cyber_py3/record.py b/cyber/python/cyber_py3/record.py +index de5cd42..31d820e 100644 +--- a/cyber/python/cyber_py3/record.py ++++ b/cyber/python/cyber_py3/record.py +@@ -30,7 +30,7 @@ from google.protobuf.descriptor_pb2 import FileDescriptorProto + APOLLO_DISTRIBUTION_HOME = os.environ.get( + 'APOLLO_DISTRIBUTION_HOME', '/opt/apollo/neo') + +-if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo'): ++if APOLLO_DISTRIBUTION_HOME.startswith('/opt/apollo/neo') or APOLLO_DISTRIBUTION_HOME.startswith('/home'): + wrapper_lib_path = os.path.join( + APOLLO_DISTRIBUTION_HOME, "lib", "cyber/python/internal") + +diff --git a/cyber/python/cyber_py3/test/BUILD b/cyber/python/cyber_py3/test/BUILD +index 22a15f1..f519a52 100644 +--- a/cyber/python/cyber_py3/test/BUILD ++++ b/cyber/python/cyber_py3/test/BUILD +@@ -16,20 +16,26 @@ py_test( + name = "init_test", + timeout = "short", + srcs = ["init_test.py"], ++ imports = [ ++ "../../internal", ++ ], + deps = [ + "//cyber/python/cyber_py3:cyber", + ], + ) + +-# py_test( +-# name = "cyber_test", +-# timeout = "short", +-# srcs = ["cyber_test.py"], +-# deps = [ +-# "//cyber/python/cyber_py3:cyber", +-# "//cyber/proto:simple_py_pb2", +-# ], +-# ) ++py_test( ++ name = "cyber_test", ++ timeout = "short", ++ srcs = ["cyber_test.py"], ++ imports = [ ++ "../../internal", ++ ], ++ deps = [ ++ "//cyber/proto:simple_py_pb2", ++ "//cyber/python/cyber_py3:cyber", ++ ], ++) + # FIXME(all): parameter_test seems to run forever + # py_test( + # name = "parameter_test", +@@ -45,6 +51,9 @@ py_test( + name = "cyber_time_test", + timeout = "short", + srcs = ["cyber_time_test.py"], ++ imports = [ ++ "../../internal", ++ ], + deps = [ + "//cyber/python/cyber_py3:cyber", + "//cyber/python/cyber_py3:cyber_time", +@@ -62,4 +71,4 @@ py_test( + # ], + #) + +-apollo_package() +\ No newline at end of file ++apollo_package() +diff --git a/cyber/python/internal/BUILD b/cyber/python/internal/BUILD +index e5ee8e0..6b95e3b 100644 +--- a/cyber/python/internal/BUILD ++++ b/cyber/python/internal/BUILD +@@ -86,7 +86,7 @@ apollo_cc_library( + hdrs = ["py_time.h"], + deps = [ + "//cyber", +- "@fastrtps", ++ "@fastdds", + "@local_config_python//:python_headers", + "@local_config_python//:python_lib", + ], +diff --git a/cyber/python/internal/py_cyber.cc b/cyber/python/internal/py_cyber.cc +index a8dca54..3b0982c 100644 +--- a/cyber/python/internal/py_cyber.cc ++++ b/cyber/python/internal/py_cyber.cc +@@ -89,7 +89,8 @@ template + T PyObjectToPtr(PyObject *pyobj, const std::string &type_ptr) { + T obj_ptr = (T)PyCapsule_GetPointer(pyobj, type_ptr.c_str()); + if (obj_ptr == nullptr) { +- AERROR << "PyObjectToPtr failed,type->" << type_ptr << "pyobj: " << pyobj; ++ AERROR << "PyObjectToPtr failed,type->" << type_ptr << " " ++ << "pyobj: " << pyobj; + } + return obj_ptr; + } +@@ -139,11 +140,12 @@ PyObject *cyber_delete_PyWriter(PyObject *self, PyObject *args) { + + PyObject *cyber_PyWriter_write(PyObject *self, PyObject *args) { + PyObject *pyobj_writer = nullptr; +- char *data = nullptr; +- Py_ssize_t len = 0; +- if (!PyArg_ParseTuple(args, const_cast("Os#:cyber_PyWriter_write"), +- &pyobj_writer, &data, &len)) { ++ Py_buffer buffer; ++ // Py_ssize_t len = 0; ++ if (!PyArg_ParseTuple(args, const_cast("Oy*:cyber_PyWriter_write"), ++ &pyobj_writer, &buffer)) { + AERROR << "cyber_PyWriter_write:cyber_PyWriter_write failed!"; ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(1); + } + +@@ -152,11 +154,14 @@ PyObject *cyber_PyWriter_write(PyObject *self, PyObject *args) { + + if (nullptr == writer) { + AERROR << "cyber_PyWriter_write:writer ptr is null!"; ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(1); + } + +- std::string data_str(data, len); ++ std::string data_str( ++ const_cast(static_cast(buffer.buf)), buffer.len); + int ret = writer->write(data_str); ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(ret); + } + +@@ -297,11 +302,12 @@ PyObject *cyber_delete_PyClient(PyObject *self, PyObject *args) { + + PyObject *cyber_PyClient_send_request(PyObject *self, PyObject *args) { + PyObject *pyobj_client = nullptr; +- char *data = nullptr; +- Py_ssize_t len = 0; +- if (!PyArg_ParseTuple(args, const_cast("Os#:PyClient_send_request"), +- &pyobj_client, &data, &len)) { ++ Py_buffer buffer; ++ // Py_ssize_t len = 0; ++ if (!PyArg_ParseTuple(args, const_cast("Oy*:PyClient_send_request"), ++ &pyobj_client, &buffer)) { + AERROR << "cyber_PyClient_send_request:PyArg_ParseTuple failed!"; ++ PyBuffer_Release(&buffer); + return PYOBJECT_NULL_STRING; + } + +@@ -310,14 +316,17 @@ PyObject *cyber_PyClient_send_request(PyObject *self, PyObject *args) { + + if (nullptr == client) { + AERROR << "cyber_PyClient_send_request:client ptr is null!"; ++ PyBuffer_Release(&buffer); + return PYOBJECT_NULL_STRING; + } + +- std::string data_str(data, len); ++ std::string data_str( ++ const_cast(static_cast(buffer.buf)), buffer.len); + ADEBUG << "c++:PyClient_send_request data->[ " << data_str << "]"; + const std::string response_str = + client->send_request((std::string const &)data_str); + ADEBUG << "c++:response data->[ " << response_str << "]"; ++ PyBuffer_Release(&buffer); + return C_STR_TO_PY_BYTES(response_str); + } + +@@ -406,11 +415,12 @@ PyObject *cyber_PyService_read(PyObject *self, PyObject *args) { + + PyObject *cyber_PyService_write(PyObject *self, PyObject *args) { + PyObject *pyobj_service = nullptr; +- char *data = nullptr; +- Py_ssize_t len = 0; +- if (!PyArg_ParseTuple(args, const_cast("Os#:cyber_PyService_write"), +- &pyobj_service, &data, &len)) { ++ Py_buffer buffer; ++ // Py_ssize_t len = 0; ++ if (!PyArg_ParseTuple(args, const_cast("Oy*:cyber_PyService_write"), ++ &pyobj_service, &buffer)) { + AERROR << "cyber_PyService_write:PyArg_ParseTuple failed!"; ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(1); + } + +@@ -419,12 +429,15 @@ PyObject *cyber_PyService_write(PyObject *self, PyObject *args) { + + if (nullptr == service) { + AERROR << "cyber_PyService_write:writer ptr is null!"; ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(1); + } + +- std::string data_str(data, len); ++ std::string data_str( ++ const_cast(static_cast(buffer.buf)), buffer.len); + ADEBUG << "c++:PyService_write data->[ " << data_str << "]"; + int ret = service->write((std::string const &)data_str); ++ PyBuffer_Release(&buffer); + return PyInt_FromLong(ret); + } + +@@ -594,24 +607,29 @@ PyObject *cyber_PyNode_shutdown(PyObject *self, PyObject *args) { + + PyObject *cyber_PyNode_register_message(PyObject *self, PyObject *args) { + PyObject *pyobj_node = nullptr; +- char *desc = nullptr; +- int len = 0; ++ Py_buffer buffer; ++ // int len = 0; + if (!PyArg_ParseTuple(args, +- const_cast("Os#:cyber_PyNode_register_message"), +- &pyobj_node, &desc, &len)) { ++ const_cast("Oy*:cyber_PyNode_register_message"), ++ &pyobj_node, &buffer)) { + AERROR << "cyber_PyNode_register_message: failed!"; + Py_INCREF(Py_None); ++ PyBuffer_Release(&buffer); + return Py_None; + } ++ std::string desc_str( ++ const_cast(static_cast(buffer.buf)), buffer.len); + PyNode *node = PyObjectToPtr(pyobj_node, "apollo_cyber_pynode"); + if (nullptr == node) { +- AERROR << "cyber_PyNode_register_message:node ptr is null! desc->" << desc; ++ AERROR << "cyber_PyNode_register_message:node ptr is null! desc->" ++ << desc_str; + Py_INCREF(Py_None); ++ PyBuffer_Release(&buffer); + return Py_None; + } +- std::string desc_str(desc, len); + node->register_message((std::string const &)desc_str); + Py_INCREF(Py_None); ++ PyBuffer_Release(&buffer); + return Py_None; + } + +diff --git a/cyber/python/internal/py_cyber.h b/cyber/python/internal/py_cyber.h +index 3f0d750..b1cca07 100644 +--- a/cyber/python/internal/py_cyber.h ++++ b/cyber/python/internal/py_cyber.h +@@ -16,6 +16,7 @@ + + #ifndef CYBER_PYTHON_INTERNAL_PY_CYBER_H_ + #define CYBER_PYTHON_INTERNAL_PY_CYBER_H_ ++#define PY_SSIZE_T_CLEAN + + #include + +diff --git a/cyber/record/file/record_file_writer.cc b/cyber/record/file/record_file_writer.cc +index 1f0d80d..3f53273 100644 +--- a/cyber/record/file/record_file_writer.cc ++++ b/cyber/record/file/record_file_writer.cc +@@ -222,7 +222,7 @@ bool RecordFileWriter::WriteMessage(const proto::SingleMessage& message) { + header_.chunk_interval()) { + need_flush = true; + } +- if (header_.chunk_raw_size() > 0 && ++ if (!in_writing_ && header_.chunk_raw_size() > 0 && + chunk_active_->header_.raw_size() > header_.chunk_raw_size()) { + need_flush = true; + } +@@ -248,9 +248,11 @@ void RecordFileWriter::Flush() { + if (chunk_flush_->empty()) { + continue; + } ++ in_writing_ = true; + if (!WriteChunk(chunk_flush_->header_, *(chunk_flush_->body_.get()))) { + AERROR << "Write chunk fail."; + } ++ in_writing_ = false; + chunk_flush_->clear(); + } + } +diff --git a/cyber/record/file/record_file_writer.h b/cyber/record/file/record_file_writer.h +index 0a9481c..2f95f91 100644 +--- a/cyber/record/file/record_file_writer.h ++++ b/cyber/record/file/record_file_writer.h +@@ -93,6 +93,7 @@ class RecordFileWriter : public RecordFileBase { + bool WriteIndex(); + void Flush(); + std::atomic_bool is_writing_; ++ std::atomic_bool in_writing_{false}; + std::unique_ptr chunk_active_ = nullptr; + std::unique_ptr chunk_flush_ = nullptr; + std::shared_ptr flush_thread_ = nullptr; +diff --git a/cyber/record/header_builder.h b/cyber/record/header_builder.h +index 6a38350..3b89cfe 100644 +--- a/cyber/record/header_builder.h ++++ b/cyber/record/header_builder.h +@@ -66,7 +66,7 @@ class HeaderBuilder { + proto::CompressType::COMPRESS_NONE; + static const uint64_t CHUNK_INTERVAL_ = 20 * 1000 * 1000 * 1000ULL; // 20s + static const uint64_t SEGMENT_INTERVAL_ = 60 * 1000 * 1000 * 1000ULL; // 60s +- static const uint64_t CHUNK_RAW_SIZE_ = 1 * 1024 * 1024ULL; // 1MB ++ static const uint64_t CHUNK_RAW_SIZE_ = 16 * 1024 * 1024ULL; // 16MB + static const uint64_t SEGMENT_RAW_SIZE_ = 2048 * 1024 * 1024ULL; // 2GB + }; + +diff --git a/cyber/ros_bridge/BUILD b/cyber/ros_bridge/BUILD +new file mode 100644 +index 0000000..3378128 +--- /dev/null ++++ b/cyber/ros_bridge/BUILD +@@ -0,0 +1,59 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_binary", "apollo_package") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_data", ++ srcs = glob([ ++ "conf/**", ++ ]), ++) ++ ++apollo_cc_library( ++ name = "converter_base", ++ hdrs = [ ++ "converter_base/message_converter.h", ++ "converter_base/converter_base.h", ++ "converter_base/convert_ros_quadruple.h", ++ "converter_base/convert_ros_triple.h", ++ "converter_base/convert_ros_double.h", ++ "converter_base/convert_ros_single.h", ++ "converter_base/convert_apollo_quadruple.h", ++ "converter_base/convert_apollo_triple.h", ++ "converter_base/convert_apollo_double.h", ++ "converter_base/convert_apollo_single.h", ++ "converter_base/converter_interface.h", ++ ++ "common/bridge_argument.h", ++ "common/ros_bridge_gflags.h", ++ "common/utils.h", ++ "common/macros.h", ++ ], ++ srcs = [ ++ "common/ros_bridge_gflags.cc", ++ "common/bridge_argument.cc", ++ ], ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "@com_github_gflags_gflags//:gflags", ++ "@ros", ++ ], ++) ++ ++apollo_cc_binary( ++ name = "ros_bridge", ++ srcs = ["ros_bridge.cc"], ++ linkopts = [ ++ "-ltcmalloc", ++ "-lprofiler", ++ ], ++ deps = [ ++ ":converter_base", ++ "//cyber/ros_bridge/proto:ros_bridge_conf_proto", ++ ] ++) ++ ++apollo_package() ++cpplint() +diff --git a/cyber/ros_bridge/common/bridge_argument.cc b/cyber/ros_bridge/common/bridge_argument.cc +new file mode 100644 +index 0000000..75c35fa +--- /dev/null ++++ b/cyber/ros_bridge/common/bridge_argument.cc +@@ -0,0 +1,112 @@ ++/****************************************************************************** ++ * Copyright 2018 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/common/bridge_argument.h" ++ ++#include ++#include ++ ++namespace apollo { ++namespace cyber { ++ ++void BridgeArgument::DisplayUsage() { ++ AINFO << "Usage: \n " << binary_name_ << " [OPTION]...\n" ++ << "Description: \n" ++ << " -h, --help: help information \n" ++ << " -c, --cpuprofile: enable gperftools cpu profile\n" ++ << " -o, --profile_filename=filename: the filename to dump the " ++ "profile to, default value is ${binary_name}_cpu.prof. Only work " ++ "with -c option\n" ++ << " -H, --heapprofile: enable gperftools heap profile\n" ++ << " -O, --heapprofile_filename=filename: the filename to dump the " ++ "profile to, default value is ${binary_name}_mem.prof. Only work " ++ "with -H option\n" ++ << "Example:\n" ++ << " " << binary_name_ << " -h\n" ++ << " " << binary_name_ << " -c -H "; ++} ++ ++void BridgeArgument::ParseArgument(const int argc, char* const argv[]) { ++ binary_name_ = std::string(basename(argv[0])); ++ GetOptions(argc, argv); ++ ++ if (enable_cpuprofile_ && profile_filename_.empty()) { ++ profile_filename_ = binary_name_ + std::string("_cpu.prof"); ++ } ++ ++ if (enable_heapprofile_ && heapprofile_filename_.empty()) { ++ heapprofile_filename_ = binary_name_ + std::string("_mem.prof"); ++ } ++ ++ AINFO << "binary_name_ is " << binary_name_; ++} ++ ++void BridgeArgument::GetOptions(const int argc, char* const argv[]) { ++ opterr = 0; // extern int opterr ++ int long_index = 0; ++ const std::string short_opts = "hco:HO:"; ++ static const struct option long_opts[] = { ++ {"help", no_argument, nullptr, 'h'}, ++ {"cpuprofile", no_argument, nullptr, 'c'}, ++ {"profile_filename", required_argument, nullptr, 'o'}, ++ {"heapprofile", no_argument, nullptr, 'H'}, ++ {"heapprofile_filename", required_argument, nullptr, 'O'}, ++ {NULL, no_argument, nullptr, 0}}; ++ ++ // log command for info ++ std::string cmd(""); ++ for (int i = 0; i < argc; ++i) { ++ cmd += argv[i]; ++ cmd += " "; ++ } ++ AINFO << "command: " << cmd; ++ ++ do { ++ int opt = ++ getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index); ++ if (opt == -1) { ++ break; ++ } ++ switch (opt) { ++ case 'c': ++ enable_cpuprofile_ = true; ++ break; ++ case 'o': ++ profile_filename_ = std::string(optarg); ++ break; ++ case 'H': ++ enable_heapprofile_ = true; ++ break; ++ case 'O': ++ heapprofile_filename_ = std::string(optarg); ++ break; ++ case 'h': ++ DisplayUsage(); ++ exit(0); ++ default: ++ break; ++ } ++ } while (true); ++ ++ if (optind < argc) { ++ AINFO << "Found non-option ARGV-element \"" << argv[optind++] << "\""; ++ DisplayUsage(); ++ exit(1); ++ } ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/common/bridge_argument.h b/cyber/ros_bridge/common/bridge_argument.h +new file mode 100644 +index 0000000..482a812 +--- /dev/null ++++ b/cyber/ros_bridge/common/bridge_argument.h +@@ -0,0 +1,57 @@ ++/****************************************************************************** ++ * Copyright 2018 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cyber/common/global_data.h" ++#include "cyber/common/log.h" ++#include "cyber/common/types.h" ++ ++namespace apollo { ++namespace cyber { ++ ++class BridgeArgument { ++ public: ++ BridgeArgument() = default; ++ virtual ~BridgeArgument() = default; ++ void DisplayUsage(); ++ void ParseArgument(int argc, char* const argv[]); ++ void GetOptions(const int argc, char* const argv[]); ++ const std::string& GetBinaryName() const; ++ const bool GetEnableCpuprofile() const { return enable_cpuprofile_; } ++ const std::string GetProfileFilename() const { return profile_filename_; } ++ const bool GetEnableHeapprofile() const { return enable_heapprofile_; } ++ const std::string GetHeapProfileFilename() const { ++ return heapprofile_filename_; ++ } ++ ++ private: ++ std::string binary_name_; ++ bool enable_cpuprofile_ = false; ++ std::string profile_filename_; ++ bool enable_heapprofile_ = false; ++ std::string heapprofile_filename_; ++}; ++ ++inline const std::string& BridgeArgument::GetBinaryName() const { ++ return binary_name_; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/common/macros.h b/cyber/ros_bridge/common/macros.h +new file mode 100644 +index 0000000..feccf11 +--- /dev/null ++++ b/cyber/ros_bridge/common/macros.h +@@ -0,0 +1,26 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef ROS_BRIDGE_MACROS_H_ ++#define ROS_BRIDGE_MACROS_H_ ++ ++// replacement macro for eprosima namespace to eprosima_wrap ++// for adapting different version fastdds on a single process ++#ifndef eprosima ++#define eprosima eprosima_wrap ++#endif ++ ++#endif // ROS_BRIDGE_MACROS_H_ +diff --git a/cyber/ros_bridge/common/ros_bridge_gflags.cc b/cyber/ros_bridge/common/ros_bridge_gflags.cc +new file mode 100644 +index 0000000..aeb32e7 +--- /dev/null ++++ b/cyber/ros_bridge/common/ros_bridge_gflags.cc +@@ -0,0 +1,32 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++/** ++ * @file ros_bridge_gflags.h ++ * @brief The gflags used by ros bridge binary ++ */ ++ ++#include "cyber/ros_bridge/common/ros_bridge_gflags.h" ++ ++namespace apollo { ++namespace cyber { ++ ++// config path ++DEFINE_string(bridge_conf_path, ++ "ros_bridge/conf/ros_bridge_conf.pb.txt", "ros config file path"); ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/common/ros_bridge_gflags.h b/cyber/ros_bridge/common/ros_bridge_gflags.h +new file mode 100644 +index 0000000..6efd55f +--- /dev/null ++++ b/cyber/ros_bridge/common/ros_bridge_gflags.h +@@ -0,0 +1,33 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++/** ++ * @file ros_bridge_gflags.h ++ * @brief The gflags used by ros bridge binary ++ */ ++ ++#pragma once ++ ++#include "gflags/gflags.h" ++ ++namespace apollo { ++namespace cyber { ++ ++// config path ++DECLARE_string(bridge_conf_path); ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/common/utils.h b/cyber/ros_bridge/common/utils.h +new file mode 100644 +index 0000000..5ee9df8 +--- /dev/null ++++ b/cyber/ros_bridge/common/utils.h +@@ -0,0 +1,34 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++ ++namespace apollo { ++namespace cyber { ++ ++std::string GetFullConverterClassName(const std::string& class_name) { ++ static const std::string kNameSpace = "apollo::cyber::"; ++ // If the class name already has namespace in it, do nothing. ++ if (class_name.find("::") != std::string::npos) { ++ return class_name; ++ } ++ return kNameSpace + class_name; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt b/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt +new file mode 100644 +index 0000000..3c1ae1d +--- /dev/null ++++ b/cyber/ros_bridge/conf/ros_bridge_conf.pb.txt +@@ -0,0 +1,19 @@ ++converter { ++ type: "LidarPointcloud" ++} ++ ++converter { ++ type: "HeadingMsgFusion" ++} ++ ++converter { ++ type: "ImuMsgConverter" ++} ++ ++converter { ++ type: "NavMsgConverter" ++} ++ ++converter { ++ type: "OdometryMsgConverter" ++} +diff --git a/cyber/ros_bridge/converter_base/convert_apollo_double.h b/cyber/ros_bridge/converter_base/convert_apollo_double.h +new file mode 100644 +index 0000000..7a0136a +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_apollo_double.h +@@ -0,0 +1,384 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_APOLLO_ROS_SINGLE_H_ ++#define CYBER_APOLLO_ROS_SINGLE_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ auto func = [this, ros_publisher_0, ++ apollo_blocker_1](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1](const std::shared_ptr in) { ++#endif ++ auto out = std::make_shared(); ++ if (!apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(in, msg1)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ auto func = [this, apollo_blocker_1, ros_publisher_0, ++ ros_publisher_1](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(in, msg1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ auto func = [this, apollo_blocker_1, ros_publisher_0, ros_publisher_1, ++ ros_publisher_2](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(in, msg1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ auto ros_publisher_3 = ++ ros_node_->create_publisher(ros_topic_name_3, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ ros_publishers_.push_back(std::move(ros_publisher_3)); ++ auto func = [this, apollo_blocker_1, ros_publisher_0, ros_publisher_1, ++ ros_publisher_2, ++ ros_publisher_3](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(in, msg1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++ ros_publisher_3->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h b/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h +new file mode 100644 +index 0000000..815a5e0 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_apollo_quadruple.h +@@ -0,0 +1,503 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_APOLLO_ROS_SINGLE_H_ ++#define CYBER_APOLLO_ROS_SINGLE_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ apollo::cyber::ReaderConfig reader_cfg_3; ++ reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); ++ auto apollo_reader_3 = ++ cyber_node_->template CreateReader(reader_cfg_3); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ auto apollo_blocker_3 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_3.channel_name); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ auto func = [this, ros_publisher_0, apollo_blocker_1, apollo_blocker_2, ++ apollo_blocker_3](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ++ apollo_blocker_3](const std::shared_ptr in) { ++#endif ++ auto out = std::make_shared(); ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty() && ++ !apollo_blocker_3->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(in, msg1, msg2, msg3)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ apollo_readers_.push_back(std::move(apollo_reader_3)); ++ ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++}; // NOLINT ++ ++// template ++// bool ApolloRosMessageConverter, ++// std::shared_ptr, ++// std::shared_ptr, ++// std::shared_ptr>, ++// OutputTypes>>::Init() ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ apollo::cyber::ReaderConfig reader_cfg_3; ++ reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); ++ auto apollo_reader_3 = ++ cyber_node_->template CreateReader(reader_cfg_3); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ auto apollo_blocker_3 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_3.channel_name); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, ++ ros_publisher_0, ++ ros_publisher_1](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ++ apollo_blocker_3](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty() && ++ !apollo_blocker_3->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(in, msg1, msg2, msg3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ apollo_readers_.push_back(std::move(apollo_reader_3)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ apollo::cyber::ReaderConfig reader_cfg_3; ++ reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); ++ auto apollo_reader_3 = ++ cyber_node_->template CreateReader(reader_cfg_3); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ auto apollo_blocker_3 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_3.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, ++ ros_publisher_0, ros_publisher_1, ++ ros_publisher_2](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ++ apollo_blocker_3](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(in, msg1, msg2, msg3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ apollo_readers_.push_back(std::move(apollo_reader_3)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ apollo::cyber::ReaderConfig reader_cfg_3; ++ reader_cfg_3.channel_name = converter_conf_.apollo_channel_name_3(); ++ auto apollo_reader_3 = ++ cyber_node_->template CreateReader(reader_cfg_3); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ auto apollo_blocker_3 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_3.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ auto ros_publisher_3 = ++ ros_node_->create_publisher(ros_topic_name_3, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ ros_publishers_.push_back(std::move(ros_publisher_3)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, apollo_blocker_3, ++ ros_publisher_0, ros_publisher_1, ros_publisher_2, ++ ros_publisher_3](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ++ apollo_blocker_3](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty() && ++ !apollo_blocker_3->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto msg3 = apollo_blocker_3->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(in, msg1, msg2, msg3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++ ros_publisher_3->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ apollo_readers_.push_back(std::move(apollo_reader_3)); ++ ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_apollo_single.h b/cyber/ros_bridge/converter_base/convert_apollo_single.h +new file mode 100644 +index 0000000..aa6bab6 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_apollo_single.h +@@ -0,0 +1,325 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_APOLLO_ROS_SINGLE_H_ ++#define CYBER_APOLLO_ROS_SINGLE_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class ApolloRosMessageConverter>, ++ OutputTypes>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes>& input, ++ OutputTypes>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter>, ++ OutputTypes>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ // ros_publishers_.push_back(ros_publisher_0); ++ auto func = [this, ros_publisher_0](const std::shared_ptr in) { ++#else ++ auto func = [this](const std::shared_ptr in) { ++#endif ++ std::shared_ptr out(new OutType0); ++ auto in_container = ++ InputTypes>{std::make_tuple(in)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++ AERROR << "out of convert"; ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out); ++#endif ++ AERROR << "after ros publish"; ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes>& input, ++ OutputTypes, ++ std::shared_ptr>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ auto func = [this, ros_publisher_0, ++ ros_publisher_1](const std::shared_ptr in) { ++#else ++ auto func = [this](const std::shared_ptr in) { ++#endif ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto in_container = ++ InputTypes>{std::make_tuple(in)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++#endif ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ auto func = [this, ros_publisher_0, ros_publisher_1, ++ ros_publisher_2](const std::shared_ptr in) { ++#else ++ auto func = [this](const std::shared_ptr in) { ++#endif ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto in_container = ++ InputTypes>{std::make_tuple(in)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++#endif ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ auto ros_publisher_3 = ++ ros_node_->create_publisher(ros_topic_name_3, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ ros_publishers_.push_back(std::move(ros_publisher_3)); ++ auto func = [this, ros_publisher_0, ros_publisher_1, ros_publisher_2, ++ ros_publisher_3](const std::shared_ptr in) { ++#else ++ auto func = [this](const std::shared_ptr in) { ++#endif ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ auto in_container = ++ InputTypes>{std::make_tuple(in)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++ ros_publisher_3->publish(*out_2); ++#endif ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_apollo_triple.h b/cyber/ros_bridge/converter_base/convert_apollo_triple.h +new file mode 100644 +index 0000000..e1a5140 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_apollo_triple.h +@@ -0,0 +1,450 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_APOLLO_ROS_SINGLE_H_ ++#define CYBER_APOLLO_ROS_SINGLE_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ auto func = [this, ros_publisher_0, apollo_blocker_1, ++ apollo_blocker_2](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, ++ apollo_blocker_2](const std::shared_ptr in) { ++#endif ++ auto out = std::make_shared(); ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, ++ ros_publisher_1](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, ++ apollo_blocker_2](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, ++ ros_publisher_1, ++ ros_publisher_2](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, ++ apollo_blocker_2](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_1->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ ++ return true; ++} ++ ++template ++class ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++}; ++ ++template ++bool ApolloRosMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>>::Init() { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo::cyber::ReaderConfig reader_cfg_0; ++ reader_cfg_0.channel_name = converter_conf_.apollo_channel_name_0(); ++ ++ apollo::cyber::ReaderConfig reader_cfg_1; ++ reader_cfg_1.channel_name = converter_conf_.apollo_channel_name_1(); ++ auto apollo_reader_1 = ++ cyber_node_->template CreateReader(reader_cfg_1); ++ ++ apollo::cyber::ReaderConfig reader_cfg_2; ++ reader_cfg_2.channel_name = converter_conf_.apollo_channel_name_2(); ++ auto apollo_reader_2 = ++ cyber_node_->template CreateReader(reader_cfg_2); ++ ++ auto apollo_blocker_1 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_1.channel_name); ++ auto apollo_blocker_2 = ++ blocker::BlockerManager::Instance()->GetBlocker( ++ reader_cfg_2.channel_name); ++ ++ std::string ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ std::string ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ std::string ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ std::string ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ auto ros_publisher_0 = ++ ros_node_->create_publisher(ros_topic_name_0, 10); ++ auto ros_publisher_1 = ++ ros_node_->create_publisher(ros_topic_name_1, 10); ++ auto ros_publisher_2 = ++ ros_node_->create_publisher(ros_topic_name_2, 10); ++ auto ros_publisher_3 = ++ ros_node_->create_publisher(ros_topic_name_3, 10); ++ ros_publishers_.push_back(std::move(ros_publisher_0)); ++ ros_publishers_.push_back(std::move(ros_publisher_1)); ++ ros_publishers_.push_back(std::move(ros_publisher_2)); ++ ros_publishers_.push_back(std::move(ros_publisher_3)); ++ auto func = [this, apollo_blocker_1, apollo_blocker_2, ros_publisher_0, ++ ros_publisher_1, ros_publisher_2, ++ ros_publisher_3](const std::shared_ptr in) { ++#else ++ auto func = [this, apollo_blocker_1, ++ apollo_blocker_2](const std::shared_ptr in) { ++#endif ++ if (!apollo_blocker_1->IsPublishedEmpty() && ++ !apollo_blocker_2->IsPublishedEmpty()) { ++ auto msg1 = apollo_blocker_1->GetLatestPublishedPtr(); ++ auto msg2 = apollo_blocker_2->GetLatestPublishedPtr(); ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple(in, msg1, msg2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_publisher_0->publish(*out_0); ++ ros_publisher_1->publish(*out_1); ++ ros_publisher_2->publish(*out_2); ++ ros_publisher_3->publish(*out_2); ++#endif ++ } ++ }; ++ auto apollo_reader_0 = ++ cyber_node_->template CreateReader(reader_cfg_0, func); ++ apollo_readers_.push_back(std::move(apollo_reader_0)); ++ apollo_readers_.push_back(std::move(apollo_reader_1)); ++ apollo_readers_.push_back(std::move(apollo_reader_2)); ++ ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_ros_base.h b/cyber/ros_bridge/converter_base/convert_ros_base.h +new file mode 100644 +index 0000000..a127f1a +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_ros_base.h +@@ -0,0 +1,63 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_ROS_APOLLO_BASE_H_ ++#define CYBER_ROS_APOLLO_BASE_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class RosApolloMessageConverter : public MessageConverter { ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override; ++ ++ protected: ++ virtual bool ConvertMsg( ++ const std::shared_ptr& ros_msg0, const std::shared_ptr& ros_msg1, ++ const std::shared_ptr& ros_msg2, const std::shared_ptr& ros_msg3, ++ std::shared_ptr& apollo_msg0, std::shared_ptr& apollo_msg1, ++ std::shared_ptr& apollo_msg2, std::shared_ptr& apollo_msg3) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(const std::shared_ptr& ros_msg0, ++ const std::shared_ptr& ros_msg1, ++ const std::shared_ptr& ros_msg2, ++ const std::shared_ptr& ros_msg3); ++#endif ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_ros_double.h b/cyber/ros_bridge/converter_base/convert_ros_double.h +new file mode 100644 +index 0000000..bd8b5b0 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_ros_double.h +@@ -0,0 +1,452 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_ROS_APOLLO_DOUBLE_H_ ++#define CYBER_ROS_APOLLO_DOUBLE_H_ ++ ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ auto writer_attrs = ++ std::make_shared(); ++ writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ apollo_attrs_.push_back(writer_attrs); ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*writer_attrs); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1) { ++ auto out = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ std::shared_ptr> apollo_writer_3_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++ apollo_writer_3_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[3]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ apollo_writer_3_->Write(out_3); ++ } ++#endif ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_ros_quadruple.h b/cyber/ros_bridge/converter_base/convert_ros_quadruple.h +new file mode 100644 +index 0000000..8e80160 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_ros_quadruple.h +@@ -0,0 +1,551 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_ROS_APOLLO_TRIPLE_H_ ++#define CYBER_ROS_APOLLO_TRIPLE_H_ ++ ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ auto writer_attrs = ++ std::make_shared(); ++ writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ apollo_attrs_.push_back(writer_attrs); ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*writer_attrs); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_3))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[3].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2, ++ std::shared_ptr ros_msg3) { ++ auto out = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ typename InType3::SharedPtr internal_in_prt_3 = ++ std::make_shared(*ros_msg3.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1, ++ internal_in_prt_2, internal_in_prt_3)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_3))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[3].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2, ++ std::shared_ptr ros_msg3) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ typename InType3::SharedPtr internal_in_prt_3 = ++ std::make_shared(*ros_msg3.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1, ++ internal_in_prt_2, internal_in_prt_3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_3))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[3].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2, ++ std::shared_ptr ros_msg3) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ typename InType3::SharedPtr internal_in_prt_3 = ++ std::make_shared(*ros_msg3.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1, ++ internal_in_prt_2, internal_in_prt_3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ std::shared_ptr> apollo_writer_3_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ auto ros_topic_name_3 = converter_conf_.ros_topic_name_3(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++ apollo_writer_3_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[3]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_3))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[3].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2, ++ std::shared_ptr ros_msg3) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ typename InType3::SharedPtr internal_in_prt_3 = ++ std::make_shared(*ros_msg3.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(internal_in_prt_0, internal_in_prt_1, ++ internal_in_prt_2, internal_in_prt_3)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ apollo_writer_3_->Write(out_3); ++ } ++#endif ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_ros_single.h b/cyber/ros_bridge/converter_base/convert_ros_single.h +new file mode 100644 +index 0000000..3e0f391 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_ros_single.h +@@ -0,0 +1,364 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_ROS_APOLLO_SINGLE_H_ ++#define CYBER_ROS_APOLLO_SINGLE_H_ ++ ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class RosApolloMessageConverter>, ++ OutputTypes>> ++ : public MessageConverter { ++ private: ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ AERROR << "load config failed"; ++ return false; ++ } ++ ++ auto writer_attrs = ++ std::make_shared(); ++ writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ apollo_attrs_.push_back(writer_attrs); ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*writer_attrs); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_subscriptions_.push_back( ++ std::move(ros_node_->create_subscription( ++ ros_topic_name_0, 10, ++ std::bind( ++ &RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes>>::TopicCallback, ++ this, std::placeholders::_1)))); ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes>& input, ++ OutputTypes>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0) { ++ auto out = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt = ++ std::make_shared(*ros_msg0.get()); ++ auto in_container = ++ InputTypes>{std::make_tuple(internal_in_prt)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_subscriptions_.push_back( ++ std::move(ros_node_->create_subscription( ++ ros_topic_name_0, 10, ++ std::bind( ++ &RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, ++ std::shared_ptr>>::TopicCallback, ++ this, std::placeholders::_1)))); ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes>& input, ++ OutputTypes, ++ std::shared_ptr>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt = ++ std::make_shared(*ros_msg0.get()); ++ auto in_container = ++ InputTypes>{std::make_tuple(internal_in_prt)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ private: ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_subscriptions_.push_back( ++ std::move(ros_node_->create_subscription( ++ ros_topic_name_0, 10, ++ std::bind( ++ &RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, ++ std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this, std::placeholders::_1)))); ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt = ++ std::make_shared(*ros_msg0.get()); ++ auto in_container = ++ InputTypes>{std::make_tuple(internal_in_prt)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ std::shared_ptr> apollo_writer_3_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++ apollo_writer_3_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[3]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_subscriptions_.push_back( ++ std::move(ros_node_->create_subscription( ++ ros_topic_name_0, 10, ++ std::bind( ++ &RosApolloMessageConverter< ++ InputTypes>, ++ OutputTypes, ++ std::shared_ptr, ++ std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this, std::placeholders::_1)))); ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt = ++ std::make_shared(*ros_msg0.get()); ++ auto in_container = ++ InputTypes>{std::make_tuple(internal_in_prt)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ apollo_writer_3_->Write(out_3); ++ } ++#endif ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/convert_ros_triple.h b/cyber/ros_bridge/converter_base/convert_ros_triple.h +new file mode 100644 +index 0000000..0d576fc +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/convert_ros_triple.h +@@ -0,0 +1,509 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_ROS_APOLLO_TRIPLE_H_ ++#define CYBER_ROS_APOLLO_TRIPLE_H_ ++ ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/converter_base.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ auto writer_attrs = ++ std::make_shared(); ++ writer_attrs->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ apollo_attrs_.push_back(writer_attrs); ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*writer_attrs); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2) { ++ auto out = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple( ++ internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; ++ auto out_container = ++ OutputTypes>{std::make_tuple(out)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple( ++ internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>> : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>& output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple( ++ internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ } ++#endif ++}; ++ ++template ++class RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>> ++ : public MessageConverter { ++ private: ++#ifdef RCLCPP__RCLCPP_HPP_ ++ typedef message_filters::sync_policies::ApproximateTime ++ approximate_sync_policy; ++ std::shared_ptr> ++ syncApproximate_; ++#endif ++ std::shared_ptr> apollo_writer_0_ = nullptr; ++ std::shared_ptr> apollo_writer_1_ = nullptr; ++ std::shared_ptr> apollo_writer_2_ = nullptr; ++ std::shared_ptr> apollo_writer_3_ = nullptr; ++ ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ MessageConverter::Init(); ++ if (!init_.load()) { ++ return false; ++ } ++ if (!LoadConfig(&converter_conf_)) { ++ return false; ++ } ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[0]->set_channel_name(converter_conf_.apollo_channel_name_0()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[1]->set_channel_name(converter_conf_.apollo_channel_name_1()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[2]->set_channel_name(converter_conf_.apollo_channel_name_2()); ++ ++ apollo_attrs_.push_back( ++ std::make_shared()); ++ apollo_attrs_[3]->set_channel_name(converter_conf_.apollo_channel_name_3()); ++ ++ auto ros_topic_name_0 = converter_conf_.ros_topic_name_0(); ++ auto ros_topic_name_1 = converter_conf_.ros_topic_name_1(); ++ auto ros_topic_name_2 = converter_conf_.ros_topic_name_2(); ++ ++ apollo_writer_0_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[0]); ++ apollo_writer_1_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[1]); ++ apollo_writer_2_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[2]); ++ apollo_writer_3_ = ++ cyber_node_->template CreateWriter(*apollo_attrs_[3]); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_0))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_1))); ++ ros_msg_subs_.push_back( ++ std::move(std::make_shared>( ++ ros_node_, ros_topic_name_2))); ++ syncApproximate_ = std::make_shared< ++ message_filters::Synchronizer>( ++ approximate_sync_policy(10), ++ *dynamic_cast*>( ++ ros_msg_subs_[0].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[1].get()), ++ *dynamic_cast*>( ++ ros_msg_subs_[2].get())); ++ syncApproximate_->registerCallback( ++ &RosApolloMessageConverter< ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, ++ std::shared_ptr>>::TopicCallback, ++ this); ++ ++ ros_spin_thread_ = ++ std::make_shared(&MessageConverter::NodeSpin, this); ++#endif ++ return true; ++ } ++ ++ protected: ++ virtual bool ConvertMsg( ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>& input, ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>& ++ output) = 0; ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ private: ++ void TopicCallback(std::shared_ptr ros_msg0, ++ std::shared_ptr ros_msg1, ++ std::shared_ptr ros_msg2) { ++ auto out_0 = std::make_shared(); ++ auto out_1 = std::make_shared(); ++ auto out_2 = std::make_shared(); ++ auto out_3 = std::make_shared(); ++ typename InType0::SharedPtr internal_in_prt_0 = ++ std::make_shared(*ros_msg0.get()); ++ typename InType1::SharedPtr internal_in_prt_1 = ++ std::make_shared(*ros_msg1.get()); ++ typename InType2::SharedPtr internal_in_prt_2 = ++ std::make_shared(*ros_msg2.get()); ++ auto in_container = ++ InputTypes, std::shared_ptr, ++ std::shared_ptr>{std::make_tuple( ++ internal_in_prt_0, internal_in_prt_1, internal_in_prt_2)}; ++ auto out_container = ++ OutputTypes, std::shared_ptr, ++ std::shared_ptr, std::shared_ptr>{ ++ std::make_tuple(out_0, out_1, out_2, out_3)}; ++ this->ConvertMsg(in_container, out_container); ++ apollo_writer_0_->Write(out_0); ++ apollo_writer_1_->Write(out_1); ++ apollo_writer_2_->Write(out_2); ++ apollo_writer_3_->Write(out_3); ++ } ++#endif ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/converter_base.h b/cyber/ros_bridge/converter_base/converter_base.h +new file mode 100644 +index 0000000..5cbb418 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/converter_base.h +@@ -0,0 +1,77 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_APOLLO_ROS_BASE_H_ ++#define CYBER_APOLLO_ROS_BASE_H_ ++ ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++template ++struct InputTypes { ++ std::tuple values; ++ static constexpr size_t NInputs = sizeof...(Types); ++}; ++ ++template ++struct OutputTypes { ++ std::tuple values; ++ static constexpr size_t NOutputs = sizeof...(Types); ++}; ++ ++template ++class ApolloRosMessageConverter : public MessageConverter { ++ public: ++ ApolloRosMessageConverter() {} ++ ~ApolloRosMessageConverter() override {} ++ ++ bool Init() override { ++ AERROR << "input output not support"; ++ return false; ++ }; ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes& input, OutputTypes& output) = 0; ++}; ++ ++template ++class RosApolloMessageConverter : public MessageConverter { ++ public: ++ RosApolloMessageConverter() {} ++ ~RosApolloMessageConverter() override {} ++ ++ bool Init() override { ++ AERROR << "input output not support"; ++ return false; ++ }; ++ ++ protected: ++ virtual bool ConvertMsg(InputTypes& input, OutputTypes& output) = 0; ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_APOLLO_ROS_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converter_base/converter_interface.h b/cyber/ros_bridge/converter_base/converter_interface.h +new file mode 100644 +index 0000000..6667d19 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/converter_interface.h +@@ -0,0 +1,29 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_CONVERTER_INTERFACE_H_ ++#define CYBER_CONVERTER_INTERFACE_H_ ++ ++#include "cyber/ros_bridge/converter_base/convert_apollo_double.h" ++#include "cyber/ros_bridge/converter_base/convert_apollo_quadruple.h" ++#include "cyber/ros_bridge/converter_base/convert_apollo_single.h" ++#include "cyber/ros_bridge/converter_base/convert_apollo_triple.h" ++#include "cyber/ros_bridge/converter_base/convert_ros_double.h" ++#include "cyber/ros_bridge/converter_base/convert_ros_quadruple.h" ++#include "cyber/ros_bridge/converter_base/convert_ros_single.h" ++#include "cyber/ros_bridge/converter_base/convert_ros_triple.h" ++ ++#endif +diff --git a/cyber/ros_bridge/converter_base/message_converter.h b/cyber/ros_bridge/converter_base/message_converter.h +new file mode 100644 +index 0000000..c6a2b05 +--- /dev/null ++++ b/cyber/ros_bridge/converter_base/message_converter.h +@@ -0,0 +1,149 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_MESSAGE_CONVERTER_H_ ++#define CYBER_MESSAGE_CONVERTER_H_ ++ ++#include // NOLINT ++#include // NOLINT ++#include // NOLINT ++#include // NOLINT ++#include // NOLINT ++#include // NOLINT ++ ++#include // NOLINT ++ ++#include "cyber/ros_bridge/proto/converter_conf.pb.h" ++ ++#include "cyber/cyber.h" ++#include "cyber/node/reader_base.h" ++#include "cyber/node/writer_base.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++#include "cyber/ros_bridge/common/macros.h" ++ ++#if __has_include("rclcpp/rclcpp.hpp") ++#include "message_filters/subscriber.h" ++#include "message_filters/sync_policies/approximate_time.h" ++#include "message_filters/synchronizer.h" ++#include "rclcpp/rclcpp.hpp" ++#include "ros_adapter/ros_distro.h" ++#endif ++ ++namespace apollo { ++namespace cyber { ++ ++class MessageConverter { ++ public: ++ MessageConverter() : init_(false) {} ++ ++ virtual ~MessageConverter() {} ++ ++ virtual bool Init() { ++ if (init_.exchange(true)) { ++ return true; ++ } ++ LoadConfig(&converter_conf_); ++ cyber_node_ = std::move( ++ CreateNode(node_name_ + "_" + converter_conf_.name() + "_apollo")); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ ros_node_ = std::make_shared<::rclcpp::Node>( ++ node_name_ + "_" + converter_conf_.name() + "_ros"); ++ ros_node_exec_ = ++ std::make_shared<::rclcpp::executors::SingleThreadedExecutor>(); ++#endif ++ return true; ++ } ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ void NodeSpin() { ++ ros_node_exec_->add_node(std::shared_ptr(ros_node_)); ++ ros_node_exec_->spin(); ++ } ++#endif ++ ++ bool IsInit() const { return init_.load(); } ++ ++ protected: ++ bool LoadConfig(ConverterConf* config) { ++ int status; ++ std::string class_name = ++ abi::__cxa_demangle(typeid(*this).name(), 0, 0, &status); ++ std::string delimiter = "::"; ++ std::string sub_class_name; ++ std::string conf_file_prefix; ++ ++ auto pos = class_name.rfind(delimiter); ++ if (pos == std::string::npos) { ++ sub_class_name = class_name; ++ } else { ++ sub_class_name = class_name.substr(pos + delimiter.length()); ++ } ++ ++ for (int i = 0; i < sub_class_name.length(); i++) { ++ if (std::isupper(sub_class_name[i]) && i > 0) { ++ conf_file_prefix.push_back('_'); ++ } ++ conf_file_prefix.push_back(std::tolower(sub_class_name[i])); ++ } ++ ++ std::string config_path = ++ apollo::cyber::plugin_manager::PluginManager::Instance() ++ ->GetPluginConfPath( ++ class_name, "conf/" + conf_file_prefix + ".pb.txt"); ++ if (!apollo::cyber::common::PathExists(config_path)) { ++ config_path = apollo::cyber::plugin_manager::PluginManager::Instance() ++ ->GetPluginConfPath( ++ class_name, std::string("conf/default.pb.txt")); ++ } ++ ++ if (!apollo::cyber::common::GetProtoFromFile(config_path, config)) { ++ AERROR << "Load config of " << class_name << " failed!"; ++ return false; ++ } ++ AINFO << "Load the [" << class_name ++ << "] config file successfully, file path: " << config_path; ++ return true; ++ } ++ ++ protected: ++ std::atomic init_; ++ std::unique_ptr cyber_node_; ++ std::vector> ++ apollo_attrs_; ++ std::vector> apollo_readers_; ++ std::vector> apollo_writers_; ++#ifdef RCLCPP__RCLCPP_HPP_ ++ std::vector> ros_publishers_; ++ std::vector> ros_subscriptions_; ++#if defined(ROS_DISTRO_FOXY) || defined(ROS_DISTRO_GALACTIC) ++ std::vector> ++#else ++ std::vector>> ++#endif ++ ros_msg_subs_; ++ std::shared_ptr<::rclcpp::Node> ros_node_ = nullptr; ++ std::shared_ptr<::rclcpp::executors::SingleThreadedExecutor> ros_node_exec_ = ++ nullptr; ++ std::shared_ptr ros_spin_thread_; ++#endif ++ const std::string node_name_ = "converter_base"; ++ ConverterConf converter_conf_; ++}; ++ ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_MESSAGE_CONVERTER_H_ +diff --git a/cyber/ros_bridge/converters/BUILD b/cyber/ros_bridge/converters/BUILD +new file mode 100644 +index 0000000..3cac8b1 +--- /dev/null ++++ b/cyber/ros_bridge/converters/BUILD +@@ -0,0 +1,3 @@ ++load("//tools:apollo_package.bzl", "apollo_package") ++ ++apollo_package() +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/BUILD b/cyber/ros_bridge/converters/common_plugins/BUILD +new file mode 100644 +index 0000000..3cac8b1 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/BUILD +@@ -0,0 +1,3 @@ ++load("//tools:apollo_package.bzl", "apollo_package") ++ ++apollo_package() +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD +new file mode 100755 +index 0000000..609edeb +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/BUILD +@@ -0,0 +1,104 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") ++load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_files", ++ srcs = glob([ ++ "conf/**", ++ "data/**", ++ ]), ++) ++ ++apollo_plugin( ++ name = "libheading_msg_fusion.so", ++ srcs = ["heading_msg_fusion.cc"], ++ hdrs = [ ++ "heading_msg_fusion.h", ++ "quaternion_math.h", ++ ], ++ description = ":heading_msg_plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "//modules/common_msgs/sensor_msgs:heading_proto", ++ "@ros" ++ ], ++) ++ ++apollo_plugin( ++ name = "libimu_msg_converter.so", ++ srcs = ["imu_msg_converter.cc"], ++ hdrs = [ ++ "imu_msg_converter.h", ++ "quaternion_math.h", ++ ], ++ description = ":imu_plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "//modules/common_msgs/localization_msgs:imu_proto", ++ "//modules/common_msgs/sensor_msgs:imu_proto", ++ "@ros" ++ ], ++) ++ ++apollo_plugin( ++ name = "libnav_msg_converter.so", ++ srcs = ["nav_msg_converter.cc"], ++ hdrs = ["nav_msg_converter.h"], ++ description = ":nav_plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "//modules/common_msgs/sensor_msgs:gnss_best_pose_proto", ++ "//modules/common_msgs/sensor_msgs:ins_proto", ++ "@ros" ++ ], ++) ++ ++apollo_plugin( ++ name = "libodometry_msg_converter.so", ++ srcs = ["odometry_msg_converter.cc"], ++ hdrs = ["odometry_msg_converter.h"], ++ description = ":odometry_msg_plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "//modules/common_msgs/localization_msgs:gps_proto", ++ "@ros" ++ ], ++) ++ ++apollo_plugin( ++ name = "libodometry_parser.so", ++ srcs = ["odometry_parser.cc"], ++ hdrs = [ ++ "odometry_parser.h", ++ "quaternion_math.h", ++ ], ++ description = ":odometry_plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "@ros", ++ "@proj", ++ "@eigen" ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt +new file mode 100755 +index 0000000..bb25a96 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/heading_msg_fusion.pb.txt +@@ -0,0 +1,4 @@ ++name: "heading" ++apollo_channel_name_0: "/apollo/sensor/gnss/heading" ++ros_topic_name_0: "/gps/fix" ++ros_topic_name_1: "/odometry" +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt +new file mode 100755 +index 0000000..7b2f35f +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/imu_msg_converter.pb.txt +@@ -0,0 +1,4 @@ ++name: "imu" ++apollo_channel_name_0: "/apollo/sensor/gnss/imu" ++apollo_channel_name_1: "/apollo/sensor/gnss/corrected_imu" ++ros_topic_name_0: "/imu/data" +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt +new file mode 100755 +index 0000000..318dd5f +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/nav_msg_converter.pb.txt +@@ -0,0 +1,5 @@ ++name: "nav" ++apollo_channel_name_0: "/apollo/sensor/gnss/best_pose" ++apollo_channel_name_1: "/apollo/sensor/gnss/ins_stat" ++ros_topic_name_0: "/gps/fix" ++ +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt +new file mode 100755 +index 0000000..ac2e6ab +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_msg_converter.pb.txt +@@ -0,0 +1,3 @@ ++name: "odometry" ++apollo_channel_name_0: "/apollo/sensor/gnss/odometry" ++ros_topic_name_0: "/odometry" +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt +new file mode 100755 +index 0000000..162142d +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/conf/odometry_parser.pb.txt +@@ -0,0 +1,5 @@ ++name: "odometry_parser" ++apollo_channel_name_0: "/apollo/sensor/gnss/odometry" ++ros_topic_name_0: "/imu" ++ros_topic_name_1: "/gps" ++ros_topic_name_2: "/odom" +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc +new file mode 100755 +index 0000000..3c30af9 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.cc +@@ -0,0 +1,97 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h" // NOLINT ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" ++ ++namespace apollo { ++namespace cyber { ++ ++bool HeadingMsgFusion::ConvertMsg( ++ InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto ros_nav_ptr = std::get<0>(in.values); ++ auto ros_odometry_ptr = std::get<1>(in.values); ++ auto& ros_nav = (*ros_nav_ptr); ++ auto& ros_odometry = (*ros_odometry_ptr); ++ ++ auto heading_msg = std::get<0>(out.values); ++ ++ auto unix_msg_time = ++ ros_nav.header.stamp.sec + ros_nav.header.stamp.nanosec / 1e9; ++ ++ double quaternion[4]; ++ double euler_angles[3]; ++ ++ quaternion[0] = ros_odometry.pose.pose.orientation.x; ++ quaternion[1] = ros_odometry.pose.pose.orientation.y; ++ quaternion[2] = ros_odometry.pose.pose.orientation.z; ++ quaternion[3] = ros_odometry.pose.pose.orientation.w; ++ ++ QuaternionToEuler(quaternion, euler_angles); ++ auto pitch = euler_angles[1]; ++ auto heading = QuaternionToHeading(euler_angles[2]); ++ ++ heading_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ heading_msg->mutable_header()->set_module_name("gnss"); ++ heading_msg->set_measurement_time(unix_msg_time); ++ ++ if (ros_nav.status.status == -1) { ++ heading_msg->set_solution_status(19); ++ heading_msg->set_position_type(0); ++ } else if (ros_nav.status.status == 0) { ++ heading_msg->set_solution_status(0); ++ heading_msg->set_position_type(16); ++ } else if (ros_nav.status.status == 1) { ++ heading_msg->set_solution_status(0); ++ heading_msg->set_position_type(18); ++ } else if (ros_nav.status.status == 2) { ++ heading_msg->set_solution_status(0); ++ heading_msg->set_position_type(50); ++ } ++ heading_msg->set_heading(heading); ++ heading_msg->set_pitch(pitch); ++ ++ /* ++ pose covariance: ++ [ ++ xx, xy, xz, xroll, xpitch, xyaw, ++ yx, yy, yz, yroll, ypitch, yyaw, ++ zx, zy, zz, zroll, zpitch, zzaw, ++ rollx, rolly, rollz, rollroll, rollpitch, rollyaw, ++ pitchx, pitchy, pitchz, pitchroll, pitchpitch, pitchyaw, ++ yawx, yawy, yawz, yawroll, yawpitch, yawyaw ++ ] ++ thus pitch_stddev = sqrt(covariance[28]), yaw_stddev = sqrt(covariance[35]) ++ */ ++ ++ auto covariance = ros_odometry.pose.covariance; ++ auto pitch_variance = covariance[28]; ++ auto yaw_variance = covariance[35]; ++ ++ double pitch_stddev = sqrt(pitch_variance); ++ double yaw_stddev = sqrt(yaw_variance); ++ ++ heading_msg->set_heading_std_dev(yaw_stddev); ++ heading_msg->set_pitch_std_dev(pitch_stddev); ++ ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h +new file mode 100755 +index 0000000..ccdc408 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_fusion.h +@@ -0,0 +1,86 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/sensor_msgs/heading.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") ++#include "sensor_msgs/msg/nav_sat_fix.hpp" ++#define ROS_NAVFOUND_FOUND ++#endif ++ ++#if __has_include("nav_msgs/msg/odometry.hpp") ++#include "nav_msgs/msg/odometry.hpp" ++#define ROS_ODOMETRY_FOUND ++#endif ++ ++#if defined(ROS_NAVFOUND_FOUND) && defined(ROS_ODOMETRY_FOUND) ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using RosNavMsg = sensor_msgs::msg::NavSatFix; ++using RosOdometryMsg = nav_msgs::msg::Odometry; ++#else ++// fake wrap ++using RosNavMsg = apollo::cyber::proto::SimpleMessage; ++using RosOdometryMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using OutputMsg = apollo::drivers::gnss::Heading; ++ ++using RosNavMsgPtr = std::shared_ptr; ++using RosOdometryMsgPtr = std::shared_ptr; ++ ++using OutputMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class HeadingMsgFusion : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, ++ OutputTypes> { ++ public: ++ HeadingMsgFusion() {} ++ ~HeadingMsgFusion() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputTypes input message container ++ * @param OutputTypes output message container ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::HeadingMsgFusion, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml +new file mode 100755 +index 0000000..c92615c +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/heading_msg_plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc +new file mode 100755 +index 0000000..449afa3 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.cc +@@ -0,0 +1,85 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h" // NOLINT ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" ++ ++namespace apollo { ++namespace cyber { ++ ++bool ImuMsgConverter::ConvertMsg( ++ InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto ros_imu_ptr = std::get<0>(in.values); ++ auto& ros_imu = (*ros_imu_ptr); ++ ++ auto imu_msg = std::get<0>(out.values); ++ auto corrected_imu_msg = std::get<1>(out.values); ++ ++ // ros header time is unix time, ++ // while measurement_time of apollo imu is gps time ++ double unix_msg_time = ++ ros_imu.header.stamp.sec + ros_imu.header.stamp.nanosec / 1e9; ++ imu_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ imu_msg->mutable_header()->set_module_name("gnss"); ++ ++ imu_msg->set_measurement_time(unix_msg_time); ++ imu_msg->set_measurement_span(0.0); ++ imu_msg->mutable_linear_acceleration()->set_x(ros_imu.linear_acceleration.x); ++ imu_msg->mutable_linear_acceleration()->set_y(ros_imu.linear_acceleration.y); ++ imu_msg->mutable_linear_acceleration()->set_z(ros_imu.linear_acceleration.z); ++ imu_msg->mutable_angular_velocity()->set_x(ros_imu.angular_velocity.x); ++ imu_msg->mutable_angular_velocity()->set_y(ros_imu.angular_velocity.y); ++ imu_msg->mutable_angular_velocity()->set_z(ros_imu.angular_velocity.z); ++ ++ corrected_imu_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ corrected_imu_msg->mutable_header()->set_module_name("gnss"); ++ corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_x( ++ ros_imu.linear_acceleration.x); ++ corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_y( ++ ros_imu.linear_acceleration.y); ++ corrected_imu_msg->mutable_imu()->mutable_linear_acceleration()->set_z( ++ ros_imu.linear_acceleration.z); ++ corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_x( ++ ros_imu.angular_velocity.x); ++ corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_y( ++ ros_imu.angular_velocity.y); ++ corrected_imu_msg->mutable_imu()->mutable_angular_velocity()->set_z( ++ ros_imu.angular_velocity.z); ++ double quaternion[4]; ++ double euler_angles[3]; ++ ++ quaternion[0] = ros_imu.orientation.x; ++ quaternion[1] = ros_imu.orientation.y; ++ quaternion[2] = ros_imu.orientation.z; ++ quaternion[3] = ros_imu.orientation.w; ++ ++ QuaternionToEuler(quaternion, euler_angles); ++ auto heading = QuaternionToHeading(euler_angles[2]); ++ corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_x( ++ euler_angles[0]); ++ corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_y( ++ euler_angles[1]); ++ corrected_imu_msg->mutable_imu()->mutable_euler_angles()->set_z( ++ euler_angles[2]); ++ ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h +new file mode 100755 +index 0000000..64f7a00 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_msg_converter.h +@@ -0,0 +1,77 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/localization_msgs/imu.pb.h" ++#include "modules/common_msgs/sensor_msgs/imu.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("sensor_msgs/msg/imu.hpp") ++#include "sensor_msgs/msg/imu.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using RosImuMsg = sensor_msgs::msg::Imu; ++#else ++// fake wrap ++using RosImuMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using ImuMsg = apollo::drivers::gnss::Imu; ++using CorrectedImuMsg = apollo::localization::CorrectedImu; ++ ++using RosImuMsgPtr = std::shared_ptr; ++ ++using ImuMsgPtr = std::shared_ptr; ++using CorrectedImuMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class ImuMsgConverter : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, ++ OutputTypes> { ++ public: ++ ImuMsgConverter() {} ++ ~ImuMsgConverter() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputTypes input message container ++ * @param OutputTypes output message container ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::ImuMsgConverter, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml +new file mode 100755 +index 0000000..1d36b10 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/imu_plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc +new file mode 100755 +index 0000000..4dcabf7 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.cc +@@ -0,0 +1,78 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h" // NOLINT ++#include ++ ++namespace apollo { ++namespace cyber { ++ ++bool NavMsgConverter::ConvertMsg( ++ InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto ros_nav_ptr = std::get<0>(in.values); ++ auto& ros_nav = (*ros_nav_ptr); ++ ++ auto best_pose_msg = std::get<0>(out.values); ++ auto ins_stat_msg = std::get<1>(out.values); ++ ++ auto unix_msg_time = ++ ros_nav.header.stamp.sec + ros_nav.header.stamp.nanosec / 1e9; ++ best_pose_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ best_pose_msg->mutable_header()->set_module_name("gnss"); ++ ++ ins_stat_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ ins_stat_msg->mutable_header()->set_module_name("gnss"); ++ ++ best_pose_msg->set_measurement_time(unix_msg_time); ++ best_pose_msg->set_latitude(ros_nav.latitude); ++ best_pose_msg->set_longitude(ros_nav.longitude); ++ best_pose_msg->set_height_msl(ros_nav.altitude); ++ best_pose_msg->set_undulation(0); ++ best_pose_msg->set_datum_id(apollo::drivers::gnss::DatumId::WGS84); ++ best_pose_msg->set_latitude_std_dev(sqrt(ros_nav.position_covariance[4])); ++ best_pose_msg->set_longitude_std_dev(sqrt(ros_nav.position_covariance[0])); ++ best_pose_msg->set_height_std_dev(sqrt(ros_nav.position_covariance[8])); ++ if (ros_nav.status.status == -1) { ++ best_pose_msg->set_sol_status( ++ apollo::drivers::gnss::SolutionStatus::INVALID_FIX); ++ best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::NONE); ++ ins_stat_msg->set_pos_type(0); ++ } else if (ros_nav.status.status == 0) { ++ best_pose_msg->set_sol_status( ++ apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); ++ best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::SINGLE); ++ ins_stat_msg->set_pos_type(1); ++ } else if (ros_nav.status.status == 1) { ++ best_pose_msg->set_sol_status( ++ apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); ++ best_pose_msg->set_sol_type(apollo::drivers::gnss::SolutionType::WAAS); ++ ins_stat_msg->set_pos_type(2); ++ } else if (ros_nav.status.status == 2) { ++ best_pose_msg->set_sol_status( ++ apollo::drivers::gnss::SolutionStatus::SOL_COMPUTED); ++ best_pose_msg->set_sol_type( ++ apollo::drivers::gnss::SolutionType::NARROW_INT); ++ ins_stat_msg->set_pos_type(2); ++ } ++ ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h +new file mode 100755 +index 0000000..1fa83ab +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_msg_converter.h +@@ -0,0 +1,77 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/sensor_msgs/gnss_best_pose.pb.h" ++#include "modules/common_msgs/sensor_msgs/ins.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") ++#include "sensor_msgs/msg/nav_sat_fix.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using RosNavMsg = sensor_msgs::msg::NavSatFix; ++#else ++// fake wrap ++using RosNavMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using BestPoseMsg = apollo::drivers::gnss::GnssBestPose; ++using InsStatMsg = apollo::drivers::gnss::InsStat; ++ ++using RosNavMsgPtr = std::shared_ptr; ++ ++using BestPoseMsgPtr = std::shared_ptr; ++using InsStatMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class NavMsgConverter : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, ++ OutputTypes> { ++ public: ++ NavMsgConverter() {} ++ ~NavMsgConverter() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputTypes input message container ++ * @param OutputTypes output message container ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::NavMsgConverter, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml +new file mode 100755 +index 0000000..95e7c02 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/nav_plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc +new file mode 100755 +index 0000000..4bbd809 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.cc +@@ -0,0 +1,66 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h" // NOLINT ++ ++namespace apollo { ++namespace cyber { ++ ++bool OdometryMsgConverter::ConvertMsg(InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto ros_odometry_ptr = std::get<0>(in.values); ++ auto& ros_odometry = (*ros_odometry_ptr); ++ ++ auto odometry_msg = std::get<0>(out.values); ++ ++ auto unix_msg_time = ++ ros_odometry.header.stamp.sec + ros_odometry.header.stamp.nanosec / 1e9; ++ odometry_msg->mutable_header()->set_timestamp_sec(unix_msg_time); ++ odometry_msg->mutable_header()->set_module_name("gnss"); ++ odometry_msg->mutable_localization()->mutable_position()->set_x( ++ ros_odometry.pose.pose.position.x); ++ odometry_msg->mutable_localization()->mutable_position()->set_y( ++ ros_odometry.pose.pose.position.y); ++ odometry_msg->mutable_localization()->mutable_position()->set_z( ++ ros_odometry.pose.pose.position.z); ++ odometry_msg->mutable_localization()->mutable_linear_velocity()->set_x( ++ ros_odometry.twist.twist.linear.x); ++ odometry_msg->mutable_localization()->mutable_linear_velocity()->set_y( ++ ros_odometry.twist.twist.linear.y); ++ odometry_msg->mutable_localization()->mutable_linear_velocity()->set_z( ++ ros_odometry.twist.twist.linear.z); ++ odometry_msg->mutable_localization()->mutable_angular_velocity()->set_x( ++ ros_odometry.twist.twist.angular.x); ++ odometry_msg->mutable_localization()->mutable_angular_velocity()->set_y( ++ ros_odometry.twist.twist.angular.y); ++ odometry_msg->mutable_localization()->mutable_angular_velocity()->set_z( ++ ros_odometry.twist.twist.angular.z); ++ odometry_msg->mutable_localization()->mutable_orientation()->set_qx( ++ ros_odometry.pose.pose.orientation.x); ++ odometry_msg->mutable_localization()->mutable_orientation()->set_qy( ++ ros_odometry.pose.pose.orientation.y); ++ odometry_msg->mutable_localization()->mutable_orientation()->set_qz( ++ ros_odometry.pose.pose.orientation.z); ++ odometry_msg->mutable_localization()->mutable_orientation()->set_qw( ++ ros_odometry.pose.pose.orientation.w); ++ ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h +new file mode 100755 +index 0000000..29ae889 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_converter.h +@@ -0,0 +1,74 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/localization_msgs/gps.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("nav_msgs/msg/odometry.hpp") ++#include "nav_msgs/msg/odometry.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using RosOdometryMsg = nav_msgs::msg::Odometry; ++#else ++// fake wrap ++using RosOdometryMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using OdometryOutputMsg = apollo::localization::Gps; ++ ++using RosOdometryMsgPtr = std::shared_ptr; ++ ++using OdometryOutputMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class OdometryMsgConverter ++ : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, OutputTypes> { ++ public: ++ OdometryMsgConverter() {} ++ ~OdometryMsgConverter() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputTypes input message container ++ * @param OutputTypes output message container ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::OdometryMsgConverter, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml +new file mode 100755 +index 0000000..f7456c8 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_msg_plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc +new file mode 100755 +index 0000000..8d03ee8 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.cc +@@ -0,0 +1,140 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h" // NOLINT ++#include "cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h" ++ ++namespace apollo { ++namespace cyber { ++ ++void OdometryParser::imuCallback(std::shared_ptr msg) { ++#ifdef ENABLE_ROS_MSG ++ imu_received_.store(true); ++ auto current_time = msg->header.stamp.sec + msg->header.stamp.nanosec / 1e9; ++ double dt = current_time - last_time_; ++ last_time_ = current_time; ++ ++ F_(0, 3) = dt; ++ F_(1, 4) = dt; ++ F_(2, 5) = dt; ++ ++ X_ = F_ * X_; ++ P_ = F_ * P_ * F_.transpose() + Q_; ++ ++ X_(3) += msg->linear_acceleration.x * dt; ++ X_(4) += msg->linear_acceleration.y * dt; ++ X_(5) += msg->linear_acceleration.z * dt; ++ ++ double euler_angles[3]; ++ ++ quaternion_[0] = msg->orientation.x; ++ quaternion_[1] = msg->orientation.y; ++ quaternion_[2] = msg->orientation.z; ++ quaternion_[3] = msg->orientation.w; ++ ++ QuaternionToEuler(quaternion_, euler_angles); ++ auto roll = euler_angles[0]; ++ auto pitch = euler_angles[1]; ++ auto yaw = euler_angles[2]; ++ ++ X_(6) = roll; ++ X_(7) = pitch; ++ X_(8) = yaw; ++#endif ++} ++ ++void OdometryParser::gpsCallback(std::shared_ptr msg) { ++#ifdef ENABLE_ROS_MSG ++ gps_received_.store(true); ++ constexpr double DEG_TO_RAD_LOCAL = M_PI / 180.0; ++ Eigen::VectorXd Z(9); ++ ++ double lon = msg->longitude; ++ double lat = msg->latitude; ++ double px = lon * DEG_TO_RAD_LOCAL; ++ double py = lat * DEG_TO_RAD_LOCAL; ++ ++ if (utm_target_ == NULL) { ++ std::string proj4_text; ++ int zone = static_cast(std::ceil((lon + 180.0) / 6.0)); ++ proj4_text = "+proj=utm +zone=" + std::to_string(zone) + ++ " +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"; ++ utm_target_ = pj_init_plus(proj4_text.c_str()); ++ } ++ pj_transform(wgs84pj_source_, utm_target_, 1, 1, &px, &py, NULL); ++ ++ Z << px, py, msg->altitude, 0, 0, 0, 0, 0, 0; ++ ++ Eigen::MatrixXd y = Z - H_ * X_; ++ Eigen::MatrixXd S = H_ * P_ * H_.transpose() + R_; ++ Eigen::MatrixXd K = P_ * H_.transpose() * S.inverse(); ++ X_ = X_ + K * y; ++ P_ = (Eigen::MatrixXd::Identity(9, 9) - K * H_) * P_; ++#endif ++} ++ ++void OdometryParser::publishOdometry() { ++#ifdef ENABLE_ROS_MSG ++ if (!gps_received_.load() || !imu_received_.load()) { ++ return; ++ } ++ RosOdomMsg odom_msg; ++ odom_msg.header.stamp = ros_node_->get_clock()->now(); ++ ++ odom_msg.pose.pose.position.x = X_(0); ++ odom_msg.pose.pose.position.y = X_(1); ++ odom_msg.pose.pose.position.z = X_(2); ++ ++ odom_msg.pose.pose.orientation.x = quaternion_[0]; ++ odom_msg.pose.pose.orientation.y = quaternion_[1]; ++ odom_msg.pose.pose.orientation.z = quaternion_[2]; ++ odom_msg.pose.pose.orientation.w = quaternion_[3]; ++ ++ odom_msg.twist.twist.linear.x = X_(3); ++ odom_msg.twist.twist.linear.y = X_(4); ++ odom_msg.twist.twist.linear.z = X_(5); ++ ++ for (int i = 0; i < 6; ++i) { ++ for (int j = 0; j < 6; ++j) { ++ if (i < 3 && j < 3) { ++ odom_msg.pose.covariance[i * 6 + j] = P_(i, j); ++ } else if (i >= 3 && j >= 3) { ++ odom_msg.pose.covariance[i * 6 + j] = P_(i + 3, j + 3); ++ } ++ } ++ } ++ ++ for (int i = 0; i < 3; ++i) { ++ for (int j = 0; j < 3; ++j) { ++ odom_msg.twist.covariance[i * 6 + j] = P_(i + 3, j + 3); ++ } ++ } ++ ++ odom_pub_->publish(odom_msg); ++ imu_received_.store(false); ++ imu_received_.store(false); ++#endif ++} ++ ++bool OdometryParser::ConvertMsg(InputTypes& in, ++ OutputTypes& out) { ++ // do nothing ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo ++ +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h +new file mode 100755 +index 0000000..da94679 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_parser.h +@@ -0,0 +1,152 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H ++#include // NOLINT ++ ++#include // NOLINT ++ ++#if __has_include("sensor_msgs/msg/nav_sat_fix.hpp") ++#include "sensor_msgs/msg/nav_sat_fix.hpp" ++#define ROS_NAVFOUND_FOUND ++#endif ++ ++#if __has_include("sensor_msgs/msg/imu.hpp") ++#include "sensor_msgs/msg/imu.hpp" ++#define ROS_IMU_FOUND ++#endif ++ ++#if __has_include("nav_msgs/msg/odometry.hpp") ++#include "nav_msgs/msg/odometry.hpp" ++#define ROS_ODOMETRY_FOUND ++#endif ++ ++#if defined(ROS_NAVFOUND_FOUND) && defined(ROS_IMU_FOUND) && \ ++ defined(ROS_ODOMETRY_FOUND) ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using RosNavMsg = sensor_msgs::msg::NavSatFix; ++using RosImuMsg = sensor_msgs::msg::Imu; ++using RosWrapMsg = std_msgs::msg::Header; ++using RosOdomMsg = nav_msgs::msg::Odometry; ++#else ++// fake wrap ++using RosNavMsg = apollo::cyber::proto::SimpleMessage; ++using RosImuMsg = apollo::cyber::proto::SimpleMessage; ++using RosWrapMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using OutputWrapMsg = apollo::cyber::proto::SimpleMessage; ++ ++using RosWrapMsgPtr = std::shared_ptr; ++using OutputWrapMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class OdometryParser ++ : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, OutputTypes> { ++ public: ++ OdometryParser() { ++#ifdef ENABLE_ROS_MSG ++ imu_sub_ = ros_node_->create_subscription( ++ converter_conf_.ros_topic_name_0(), 10, ++ std::bind(&OdometryParser::imuCallback, this, std::placeholders::_1)); ++ gps_sub_ = ros_node_->create_subscription( ++ converter_conf_.ros_topic_name_1(), 10, ++ std::bind(&OdometryParser::gpsCallback, this, std::placeholders::_1)); ++ odom_pub_ = ros_node_->create_publisher( ++ converter_conf_.ros_topic_name_2(), 10); ++ timer_ = ros_node_->create_wall_timer( ++ std::chrono::milliseconds(100), ++ std::bind(&OdometryParser::publishOdometry, this)); ++#endif ++ ++ wgs84pj_source_ = pj_init_plus("+proj=latlong +ellps=WGS84"); ++ X_ = Eigen::VectorXd::Zero(9); ++ P_ = Eigen::MatrixXd::Identity(9, 9); ++ F_ = Eigen::MatrixXd::Identity(9, 9); ++ H_ = Eigen::MatrixXd::Identity(9, 9); ++ R_ = Eigen::MatrixXd::Identity(9, 9) * 0.1; ++ Q_ = Eigen::MatrixXd::Identity(9, 9) * 0.01; ++ last_time_ = apollo::cyber::Time::Now().ToSecond(); ++ } ++ ~OdometryParser() {} ++ ++ void imuCallback(std::shared_ptr msg); ++ ++ void gpsCallback(std::shared_ptr msg); ++ ++ void publishOdometry(); ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputTypes input message container ++ * @param OutputTypes output message container ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++ ++ private: ++ projPJ wgs84pj_source_ = NULL; ++ projPJ utm_target_ = NULL; ++#ifdef ENABLE_ROS_MSG ++ ::rclcpp::SubscriptionBase::SharedPtr imu_sub_; ++ ::rclcpp::SubscriptionBase::SharedPtr gps_sub_; ++ ::rclcpp::Publisher::SharedPtr odom_pub_; ++ ::rclcpp::TimerBase::SharedPtr timer_; ++#endif ++ ++ std::atomic imu_received_ = false; ++ std::atomic gps_received_ = false; ++ ++ double last_time_; ++ ++ double quaternion_[4]; ++ ++ // Kalman filter ++ Eigen::VectorXd X_; // State vector: [x, y, z, vx, vy, vz, roll, pitch, yaw] ++ Eigen::MatrixXd P_; // Covariance matrix ++ Eigen::MatrixXd F_; // State transition matrix ++ Eigen::MatrixXd H_; // Measurement matrix ++ Eigen::MatrixXd R_; // Measurement noise covariance matrix ++ Eigen::MatrixXd Q_; // Process noise covariance matrix ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::OdometryParser, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml +new file mode 100755 +index 0000000..449c0d8 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/odometry_plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h +new file mode 100644 +index 0000000..8af76f3 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/gnss_msg_converter/quaternion_math.h +@@ -0,0 +1,50 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include ++ ++namespace apollo { ++namespace cyber { ++ ++inline void QuaternionToEuler(const double quaternion[4], double att[3]) { ++ double dcm21 = ++ 2 * (quaternion[2] * quaternion[3] + quaternion[0] * quaternion[1]); ++ double dcm20 = ++ 2 * (quaternion[1] * quaternion[3] - quaternion[0] * quaternion[2]); ++ double dcm22 = quaternion[0] * quaternion[0] - quaternion[1] * quaternion[1] - ++ quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3]; ++ double dcm01 = ++ 2 * (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]); ++ double dcm11 = quaternion[0] * quaternion[0] - quaternion[1] * quaternion[1] + ++ quaternion[2] * quaternion[2] - quaternion[3] * quaternion[3]; ++ ++ att[0] = std::asin(dcm21); // the angle rotate respect to X ++ att[1] = std::atan2(-dcm20, dcm22); // the angle rotate respect to Y ++ att[2] = std::atan2(dcm01, dcm11); // the angle rotate respect to Z ++ ++ return; ++} ++ ++inline double QuaternionToHeading(double yaw) { ++ double a = std::fmod(yaw + M_PI_2 + M_PI, 2.0 * M_PI); ++ if (a < 0.0) { ++ a += (2.0 * M_PI); ++ } ++ return a - M_PI; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD +new file mode 100755 +index 0000000..73c9547 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/BUILD +@@ -0,0 +1,33 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") ++load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_files", ++ srcs = glob([ ++ "conf/**", ++ "data/**", ++ ]), ++) ++ ++apollo_plugin( ++ name = "liblocalization_estimate.so", ++ srcs = ["localization_estimate.cc"], ++ hdrs = ["localization_estimate.h"], ++ description = ":localization_estimate.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//modules/common_msgs/localization_msgs:localization_proto", ++ "//modules/common_msgs/transform_msgs:transform_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "@ros" ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt +new file mode 100755 +index 0000000..4fb4ca5 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/conf/localization_estimate.pb.txt +@@ -0,0 +1,4 @@ ++name: "lidar" ++apollo_channel_name_0: "/apollo/vanjee/pointcloud2" ++apollo_channel_name_1: "/apollo/localization/pose" ++ros_topic_name_0: "/pose" +diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc +new file mode 100755 +index 0000000..7bc83e5 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.cc +@@ -0,0 +1,86 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h" // NOLINT ++ ++namespace apollo { ++namespace cyber { ++ ++bool LocalizationEstimate::ConvertMsg( ++ InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto ros_odometry_ptr = std::get<0>(in.values); ++ auto& ros_odometry = (*ros_odometry_ptr); ++ auto localization_estimate = std::get<0>(out.values); ++ auto tf = std::get<1>(out.values); ++ ++ auto unix_msg_time = ++ ros_odometry.header.stamp.sec + ros_odometry.header.stamp.nanosec / 1e9; ++ localization_estimate->mutable_header()->set_timestamp_sec(unix_msg_time); ++ localization_estimate->mutable_header()->set_module_name("localization"); ++ localization_estimate->set_measurement_time(unix_msg_time); ++ localization_estimate->mutable_pose()->mutable_position()->set_x( ++ ros_odometry.pose.pose.position.x); ++ localization_estimate->mutable_pose()->mutable_position()->set_y( ++ ros_odometry.pose.pose.position.y); ++ localization_estimate->mutable_pose()->mutable_position()->set_z( ++ ros_odometry.pose.pose.position.z); ++ localization_estimate->mutable_pose()->mutable_linear_velocity()->set_x( ++ ros_odometry.twist.twist.linear.x); ++ localization_estimate->mutable_pose()->mutable_linear_velocity()->set_y( ++ ros_odometry.twist.twist.linear.y); ++ localization_estimate->mutable_pose()->mutable_linear_velocity()->set_z( ++ ros_odometry.twist.twist.linear.z); ++ localization_estimate->mutable_pose()->mutable_angular_velocity()->set_x( ++ ros_odometry.twist.twist.angular.x); ++ localization_estimate->mutable_pose()->mutable_angular_velocity()->set_y( ++ ros_odometry.twist.twist.angular.y); ++ localization_estimate->mutable_pose()->mutable_angular_velocity()->set_z( ++ ros_odometry.twist.twist.angular.z); ++ localization_estimate->mutable_pose()->mutable_orientation()->set_qx( ++ ros_odometry.pose.pose.orientation.x); ++ localization_estimate->mutable_pose()->mutable_orientation()->set_qy( ++ ros_odometry.pose.pose.orientation.y); ++ localization_estimate->mutable_pose()->mutable_orientation()->set_qz( ++ ros_odometry.pose.pose.orientation.z); ++ localization_estimate->mutable_pose()->mutable_orientation()->set_qw( ++ ros_odometry.pose.pose.orientation.w); ++ ++ auto single_tf = tf->add_transforms(); ++ single_tf->mutable_header()->set_timestamp_sec(unix_msg_time); ++ single_tf->mutable_header()->set_frame_id("world"); ++ single_tf->set_child_frame_id("localization"); ++ single_tf->mutable_transform()->mutable_translation()->set_x( ++ ros_odometry.pose.pose.position.x); ++ single_tf->mutable_transform()->mutable_translation()->set_y( ++ ros_odometry.pose.pose.position.y); ++ single_tf->mutable_transform()->mutable_translation()->set_z( ++ ros_odometry.pose.pose.position.z); ++ single_tf->mutable_transform()->mutable_rotation()->set_qx( ++ ros_odometry.pose.pose.orientation.x); ++ single_tf->mutable_transform()->mutable_rotation()->set_qy( ++ ros_odometry.pose.pose.orientation.y); ++ single_tf->mutable_transform()->mutable_rotation()->set_qz( ++ ros_odometry.pose.pose.orientation.z); ++ single_tf->mutable_transform()->mutable_rotation()->set_qw( ++ ros_odometry.pose.pose.orientation.w); ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h +new file mode 100755 +index 0000000..da13923 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.h +@@ -0,0 +1,76 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/localization_msgs/localization.pb.h" ++#include "modules/common_msgs/transform_msgs/transform.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("nav_msgs/msg/odometry.hpp") ++#include "nav_msgs/msg/odometry.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using InputMsg = nav_msgs::msg::Odometry; ++#else ++using InputMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using LocalizationMsg = apollo::localization::LocalizationEstimate; ++using TransformMsg = apollo::transform::TransformStampeds; ++ ++using LocalizationMsgPtr = std::shared_ptr; ++using TransformMsgPtr = std::shared_ptr; ++using InputMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class LocalizationEstimate ++ : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, ++ OutputTypes> { ++ public: ++ LocalizationEstimate() {} ++ ~LocalizationEstimate() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputMsgPtr shared pointer of input message ++ * @param OutputMsgPtr shared pointer of output message ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::LocalizationEstimate, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml +new file mode 100755 +index 0000000..61a1569 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/localization_msg_converter/localization_estimate.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD +new file mode 100755 +index 0000000..eb2e8b6 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/BUILD +@@ -0,0 +1,32 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") ++load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_files", ++ srcs = glob([ ++ "conf/**", ++ "data/**", ++ ]), ++) ++ ++apollo_plugin( ++ name = "liblidar_pointcloud_plugin.so", ++ srcs = ["lidar_pointcloud.cc"], ++ hdrs = ["lidar_pointcloud.h"], ++ description = ":plugins.xml", ++ deps = [ ++ "//cyber", ++ "//modules/common_msgs/sensor_msgs:pointcloud_proto", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "@ros" ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt +new file mode 100755 +index 0000000..4245cd3 +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/conf/default.pb.txt +@@ -0,0 +1,3 @@ ++name: "lidar" ++apollo_channel_name_0: "/apollo/sample/pointcloud2" ++ros_topic_name_0: "/sample_pointcloud2" +diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc +new file mode 100755 +index 0000000..616d8ff +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.cc +@@ -0,0 +1,230 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h" // NOLINT ++ ++namespace apollo { ++namespace cyber { ++ ++#ifdef ENABLE_ROS_MSG ++void ParseField(sensor_msgs::msg::PointField field, ++ std::shared_ptr point_clouds, ++ std::string field_name, ++ sensor_msgs::msg::PointCloud2& raw_message) { ++ switch (field.datatype) { ++ case sensor_msgs::msg::PointField::INT8: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::UINT8: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::INT16: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::UINT16: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::INT32: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::UINT32: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::FLOAT32: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ case sensor_msgs::msg::PointField::FLOAT64: { ++ sensor_msgs::PointCloud2ConstIterator iter(raw_message, ++ field_name); ++ int index = 0; ++ for (; iter != iter.end(); ++iter) { ++ if (field_name == "intensity") { ++ point_clouds->mutable_point(index)->set_intensity( ++ static_cast(*iter)); ++ } else { ++ point_clouds->mutable_point(index)->set_timestamp( ++ static_cast(*iter)); ++ AERROR << *iter; ++ } ++ index++; ++ } ++ break; ++ } ++ default: ++ throw std::runtime_error("Unsupported PointField datatype"); ++ } ++} ++#endif ++ ++bool LidarPointcloud::ConvertMsg(InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto in_msg = std::get<0>(in.values); ++ auto out_msg = std::get<0>(out.values); ++ float x, y, z; ++ float intensity = -1.0; ++ double timestamp = 0.0; ++ auto& cloud_msg = (*in_msg); ++ ++ bool has_x = false, has_y = false, has_z = false, has_intensity = false, ++ has_time = false; ++ std::string time_field_name; ++ sensor_msgs::msg::PointField time_field_type; ++ sensor_msgs::msg::PointField intensity_field_type; ++ for (const auto& field : cloud_msg.fields) { ++ if (field.name == "x") has_x = true; ++ if (field.name == "y") has_y = true; ++ if (field.name == "z") has_z = true; ++ if (field.name == "intensity") { ++ has_intensity = true; ++ intensity_field_type = field; ++ } ++ if (field.name == "t" || field.name == "time" || ++ field.name == "timestamp") { ++ has_time = true; ++ time_field_type = field; ++ time_field_name = field.name; ++ } ++ } ++ if (!(has_x && has_y && has_z)) { ++ AERROR << "PointCloud2 does not contain x, y, z fields."; ++ return false; ++ } ++ ++ sensor_msgs::PointCloud2ConstIterator iter_x(cloud_msg, "x"); ++ sensor_msgs::PointCloud2ConstIterator iter_y(cloud_msg, "y"); ++ sensor_msgs::PointCloud2ConstIterator iter_z(cloud_msg, "z"); ++ ++ for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) { ++ x = *iter_x; ++ y = *iter_y; ++ z = *iter_z; ++ ++ auto pointcloud = out_msg->add_point(); ++ pointcloud->set_x(x); ++ pointcloud->set_y(y); ++ pointcloud->set_z(z); ++ } ++ if (has_time) { ++ ParseField(time_field_type, out_msg, time_field_name, cloud_msg); ++ } ++ if (has_intensity) { ++ ParseField(intensity_field_type, out_msg, "intensity", cloud_msg); ++ } ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h +new file mode 100755 +index 0000000..11a628c +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/lidar_pointcloud.h +@@ -0,0 +1,83 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "modules/common_msgs/sensor_msgs/pointcloud.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("sensor_msgs/point_cloud2_iterator.hpp") ++#include "sensor_msgs/point_cloud2_iterator.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using InputMsg = sensor_msgs::msg::PointCloud2; ++#else ++using InputMsg = apollo::cyber::proto::SimpleMessage; ++#endif ++ ++using OutputMsg = apollo::drivers::PointCloud; ++ ++using InputMsgPtr = std::shared_ptr; ++using OutputMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class LidarPointcloud ++ : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, OutputTypes> { ++ public: ++ LidarPointcloud() {} ++ ~LidarPointcloud() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputMsgPtr shared pointer of input message ++ * @param OutputMsgPtr shared pointer of output message ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, OutputTypes&); ++ ++#ifdef ENABLE_ROS_MSG ++ inline int FindFieldIndex( ++ std::string name, sensor_msgs::msg::PointCloud2& cloud_msg) { // NOLINT ++ for (int i = 0; i < cloud_msg.fields.size(); i++) { ++ if (cloud_msg.fields[i].name == name) { ++ return i; ++ } ++ } ++ return -1; ++ } ++#endif ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::LidarPointcloud, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml +new file mode 100755 +index 0000000..612c10f +--- /dev/null ++++ b/cyber/ros_bridge/converters/common_plugins/pointcloud_msg_converter/plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD b/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD +new file mode 100644 +index 0000000..108b103 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/BUILD +@@ -0,0 +1,34 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") ++load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_files", ++ srcs = glob([ ++ "conf/**", ++ "data/**", ++ ]), ++) ++ ++# import ros repository is new feature of cyber 2.0 ++# depend on the env configuration provided by the apollo tool ++# currently under development ++apollo_plugin( ++ name = "libapollo_ros_converter_plugin.so", ++ srcs = ["apollo_ros_converter.cc"], ++ hdrs = ["apollo_ros_converter.h"], ++ description = ":plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ # "@ros" ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc +new file mode 100644 +index 0000000..6b29474 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.cc +@@ -0,0 +1,34 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++bool ApolloRosConverter::ConvertMsg(InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto in_msg = std::get<0>(in.values); ++ auto out_msg = std::get<0>(out.values); ++ out_msg->data = in_msg->text(); ++ // out->data = in->text(); ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h +new file mode 100644 +index 0000000..757ead1 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/apollo_ros_converter.h +@@ -0,0 +1,69 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("std_msgs/msg/string.hpp") ++#include "std_msgs/msg/int32.hpp" ++#include "std_msgs/msg/int64.hpp" ++#include "std_msgs/msg/int8.hpp" ++#include "std_msgs/msg/string.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++using InputMsg0 = apollo::cyber::proto::SimpleMessage; ++#ifdef ENABLE_ROS_MSG ++using OutputMsg0 = std_msgs::msg::String; ++#else ++using OutputMsg0 = apollo::cyber::proto::SimpleRepeatedMessage; ++#endif ++using OutputMsg0Ptr = std::shared_ptr; ++using InputMsg0Ptr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class ApolloRosConverter ++ : public apollo::cyber::ApolloRosMessageConverter< ++ InputTypes, OutputTypes> { ++ public: ++ ApolloRosConverter() {} ++ ~ApolloRosConverter() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputMsgPtr shared pointer of input message ++ * @param OutputMsgPtr shared pointer of output message ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes&, ++ OutputTypes&); ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::ApolloRosConverter, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt +new file mode 100644 +index 0000000..455afec +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/conf/default.pb.txt +@@ -0,0 +1,2 @@ ++apollo_channel_name: "/apollo/test1" ++ros_topic_name: "ros_test1" +diff --git a/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml b/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml +new file mode 100644 +index 0000000..016eb7d +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/apollo_ros_converter/plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD b/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD +new file mode 100644 +index 0000000..57f1c42 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/BUILD +@@ -0,0 +1,34 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_package", "apollo_plugin") ++load("//tools/platform:build_defs.bzl", "if_aarch64", "if_gpu") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++filegroup( ++ name = "runtime_files", ++ srcs = glob([ ++ "conf/**", ++ "data/**", ++ ]), ++) ++ ++# import ros repository is new feature of cyber 2.0 ++# depend on the env configuration provided by the apollo tool ++# currently under development ++apollo_plugin( ++ name = "libros_apollo_converter_plugin.so", ++ srcs = ["ros_apollo_converter.cc"], ++ hdrs = ["ros_apollo_converter.h"], ++ description = ":plugins.xml", ++ deps = [ ++ "//cyber", ++ "//cyber/proto:simple_proto", ++ "//cyber/ros_bridge:converter_base", ++ "//cyber/ros_bridge/proto:converter_conf_proto", ++ "@ros" ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt b/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt +new file mode 100644 +index 0000000..362809d +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/conf/default.pb.txt +@@ -0,0 +1,2 @@ ++apollo_channel_name_0: "/apollo/test2" ++ros_topic_name_0: "/chatter" +diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml b/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml +new file mode 100644 +index 0000000..4ff4aef +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/plugins.xml +@@ -0,0 +1,3 @@ ++ ++ ++ +\ No newline at end of file +diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc +new file mode 100644 +index 0000000..89fbcb8 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.cc +@@ -0,0 +1,33 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h" ++ ++namespace apollo { ++namespace cyber { ++ ++bool RosApolloConverter::ConvertMsg(InputTypes& in, ++ OutputTypes& out) { ++#ifdef ENABLE_ROS_MSG ++ auto in_msg = std::get<0>(in.values); ++ auto out_msg = std::get<0>(out.values); ++ out_msg->set_text(in_msg->data.c_str()); ++#endif ++ return true; ++} ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h +new file mode 100644 +index 0000000..c7ed499 +--- /dev/null ++++ b/cyber/ros_bridge/converters/examples/ros_apollo_converter/ros_apollo_converter.h +@@ -0,0 +1,66 @@ ++/****************************************************************************** ++ * Copyright 2023 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#include ++ ++#include "cyber/ros_bridge/converter_base/converter_interface.h" ++ ++#include "cyber/proto/simple.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++ ++#if __has_include("std_msgs/msg/string.hpp") ++#include "std_msgs/msg/string.hpp" ++#define ENABLE_ROS_MSG ++#endif ++ ++#ifdef ENABLE_ROS_MSG ++using InputMsg = std_msgs::msg::String; ++#else ++using InputMsg = apollo::cyber::proto::SimpleRepeatedMessage; ++#endif ++using OutputMsg = apollo::cyber::proto::SimpleMessage; ++using InputMsgPtr = std::shared_ptr; ++using OutputMsgPtr = std::shared_ptr; ++ ++namespace apollo { ++namespace cyber { ++ ++class RosApolloConverter ++ : public apollo::cyber::RosApolloMessageConverter< ++ InputTypes, OutputTypes> { ++ public: ++ RosApolloConverter() {} ++ ~RosApolloConverter() {} ++ ++ /** ++ * @brief convert the message between ros and apollo ++ * ++ * @param InputMsgPtr shared pointer of input message ++ * @param OutputMsgPtr shared pointer of output message ++ * @return result, true for success ++ */ ++ virtual bool ConvertMsg(InputTypes& in, ++ OutputTypes& out); // NOLINT ++}; ++ ++CYBER_PLUGIN_MANAGER_REGISTER_PLUGIN(apollo::cyber::RosApolloConverter, ++ apollo::cyber::MessageConverter) ++ ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/ros_bridge/proto/BUILD b/cyber/ros_bridge/proto/BUILD +new file mode 100644 +index 0000000..5d8e890 +--- /dev/null ++++ b/cyber/ros_bridge/proto/BUILD +@@ -0,0 +1,16 @@ ++load("//tools/proto:proto.bzl", "proto_library") ++load("//tools:apollo_package.bzl", "apollo_package") ++ ++package(default_visibility = ["//visibility:public"]) ++ ++proto_library( ++ name = "converter_conf_proto", ++ srcs = ["converter_conf.proto"], ++) ++ ++proto_library( ++ name = "ros_bridge_conf_proto", ++ srcs = ["ros_bridge_conf.proto"], ++) ++ ++apollo_package() +\ No newline at end of file +diff --git a/cyber/ros_bridge/proto/converter_conf.proto b/cyber/ros_bridge/proto/converter_conf.proto +new file mode 100644 +index 0000000..91b4abe +--- /dev/null ++++ b/cyber/ros_bridge/proto/converter_conf.proto +@@ -0,0 +1,15 @@ ++syntax = "proto2"; ++ ++package apollo.cyber; ++ ++message ConverterConf { ++ optional string name = 1; ++ optional string apollo_channel_name_0 = 2; ++ optional string apollo_channel_name_1 = 3; ++ optional string apollo_channel_name_2 = 4; ++ optional string apollo_channel_name_3 = 5; ++ optional string ros_topic_name_0 = 6; ++ optional string ros_topic_name_1 = 7; ++ optional string ros_topic_name_2 = 8; ++ optional string ros_topic_name_3 = 9; ++} +\ No newline at end of file +diff --git a/cyber/ros_bridge/proto/ros_bridge_conf.proto b/cyber/ros_bridge/proto/ros_bridge_conf.proto +new file mode 100644 +index 0000000..e4fe62f +--- /dev/null ++++ b/cyber/ros_bridge/proto/ros_bridge_conf.proto +@@ -0,0 +1,13 @@ ++syntax = "proto2"; ++ ++package apollo.cyber; ++ ++message BridgeConf { ++ // The contained converter list of the ros bridge pipeline. ++ repeated PluginDeclareInfo converter = 1; ++} ++ ++message PluginDeclareInfo { ++ // classname of converter ++ optional string type = 1; ++} +diff --git a/cyber/ros_bridge/ros_bridge.cc b/cyber/ros_bridge/ros_bridge.cc +new file mode 100644 +index 0000000..8b9f5d2 +--- /dev/null ++++ b/cyber/ros_bridge/ros_bridge.cc +@@ -0,0 +1,99 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include ++ ++#include "cyber/ros_bridge/common/macros.h" ++ ++#include "cyber/ros_bridge/proto/ros_bridge_conf.pb.h" ++#include "cyber/cyber.h" ++#include "cyber/plugin_manager/plugin_manager.h" ++#include "cyber/ros_bridge/common/bridge_argument.h" ++#include "cyber/ros_bridge/common/ros_bridge_gflags.h" ++#include "cyber/ros_bridge/common/utils.h" ++#include "cyber/ros_bridge/converter_base/message_converter.h" ++ ++#include "gperftools/heap-profiler.h" ++#include "gperftools/malloc_extension.h" ++#include "gperftools/profiler.h" ++ ++#if __has_include("rclcpp/rclcpp.hpp") ++#include "rclcpp/rclcpp.hpp" ++#endif ++ ++using apollo::cyber::BridgeArgument; ++using apollo::cyber::MessageConverter; ++using apollo::cyber::plugin_manager::PluginManager; ++using namespace apollo::cyber::common; // NOLINT ++ ++int main(int argc, char** argv) { ++ apollo::cyber::BridgeConf bridge_conf; ++ std::vector> converter_list_; ++ ++ BridgeArgument bridge_args; ++ bridge_args.ParseArgument(argc, argv); ++ ++ apollo::cyber::Init(argv[0]); ++ ++#ifdef RCLCPP__RCLCPP_HPP_ ++ rclcpp::init(argc, argv); ++#endif ++ ++ PluginManager::Instance()->LoadInstalledPlugins(); ++ ++ auto config_path = ++ GetAbsolutePath(WorkRoot(), apollo::cyber::FLAGS_bridge_conf_path); ++ if (!GetProtoFromFile(config_path, &bridge_conf)) { ++ AERROR << "parse ros bridge config failed!"; ++ return 1; ++ } ++ ++ for (int i = 0; i < bridge_conf.converter_size(); i++) { ++ auto converter = ++ PluginManager::Instance()->CreateInstance( ++ apollo::cyber::GetFullConverterClassName( ++ bridge_conf.converter(i).type())); ++ ACHECK(converter->Init()) ++ << "Can not init converter " << bridge_conf.converter(i).type(); ++ converter_list_.push_back(converter); ++ } ++ ++ if (bridge_args.GetEnableCpuprofile()) { ++ auto profile_filename = bridge_args.GetProfileFilename(); ++ ProfilerStart(profile_filename.c_str()); ++ } ++ ++ if (bridge_args.GetEnableHeapprofile()) { ++ auto profile_filename = bridge_args.GetHeapProfileFilename(); ++ HeapProfilerStart(profile_filename.c_str()); ++ } ++ ++ apollo::cyber::WaitForShutdown(); ++#ifdef RCLCPP__RCLCPP_HPP_ ++ rclcpp::shutdown(); ++#endif ++ ++ if (bridge_args.GetEnableCpuprofile()) { ++ ProfilerStop(); ++ } ++ ++ if (bridge_args.GetEnableHeapprofile()) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++ ++ return 0; ++} +diff --git a/cyber/service_discovery/BUILD b/cyber/service_discovery/BUILD +index aa8ccb4..5b9de22 100644 +--- a/cyber/service_discovery/BUILD ++++ b/cyber/service_discovery/BUILD +@@ -36,7 +36,6 @@ apollo_cc_library( + "//cyber/common:cyber_common", + "//cyber:cyber_binary", + "//cyber/proto:role_attributes_cc_proto", +- "@fastrtps", + "//cyber:cyber_state", + "//cyber/message:cyber_message", + "//cyber/proto:proto_desc_cc_proto", +@@ -45,6 +44,11 @@ apollo_cc_library( + ], + ) + ++apollo_cc_library( ++ name = "subscriber_listener", ++ hdrs = ["communication/subscriber_listener.h"] ++) ++ + apollo_cc_library( + name = "cyber_service_discovery_role", + srcs = ["role/role.cc"], +diff --git a/cyber/service_discovery/communication/participant_listener.cc b/cyber/service_discovery/communication/participant_listener.cc +index ed5cc94..71d020d 100644 +--- a/cyber/service_discovery/communication/participant_listener.cc ++++ b/cyber/service_discovery/communication/participant_listener.cc +@@ -30,9 +30,20 @@ ParticipantListener::~ParticipantListener() { + callback_ = nullptr; + } + +-void ParticipantListener::onParticipantDiscovery( +- eprosima::fastrtps::Participant* p, +- eprosima::fastrtps::ParticipantDiscoveryInfo info) { ++/** ++ * @brief Event handler for participant discovery. ++ * ++ * This function is called when a new participant is discovered in the DDS domain. ++ * ++ * @param p Pointer to the DomainParticipant. This parameter is unused in this function. ++ * DomainParticipant represents an entity that participates in a DDS domain, ++ * allowing publishers and subscribers to communicate. ++ * @param info An rvalue reference to the ParticipantDiscoveryInfo, which contains ++ * information about the discovered participant. ++ */ ++void ParticipantListener::on_participant_discovery( ++ eprosima::fastdds::dds::DomainParticipant* p, ++ eprosima::fastrtps::rtps::ParticipantDiscoveryInfo&& info) { + RETURN_IF_NULL(callback_); + (void)p; + std::lock_guard lock(mutex_); +diff --git a/cyber/service_discovery/communication/participant_listener.h b/cyber/service_discovery/communication/participant_listener.h +index 91cc20d..d80994b 100644 +--- a/cyber/service_discovery/communication/participant_listener.h ++++ b/cyber/service_discovery/communication/participant_listener.h +@@ -20,25 +20,27 @@ + #include + #include + ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/domain/DomainParticipantListener.hpp" + #include "fastrtps/Domain.h" +-#include "fastrtps/participant/Participant.h" +-#include "fastrtps/participant/ParticipantListener.h" + + namespace apollo { + namespace cyber { + namespace service_discovery { + +-class ParticipantListener : public eprosima::fastrtps::ParticipantListener { ++class ParticipantListener ++ : public eprosima::fastdds::dds::DomainParticipantListener { + public: + using ChangeFunc = std::function; ++ const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info)>; + + explicit ParticipantListener(const ChangeFunc& callback); + virtual ~ParticipantListener(); + +- virtual void onParticipantDiscovery( +- eprosima::fastrtps::Participant* p, +- eprosima::fastrtps::ParticipantDiscoveryInfo info); ++ void on_participant_discovery( ++ eprosima::fastdds::dds::DomainParticipant* p, ++ eprosima::fastrtps::rtps::ParticipantDiscoveryInfo&& info) override; + + private: + ChangeFunc callback_; +diff --git a/cyber/service_discovery/communication/subscriber_listener.cc b/cyber/service_discovery/communication/subscriber_listener.cc +index 1501b5a..dcf9581 100644 +--- a/cyber/service_discovery/communication/subscriber_listener.cc ++++ b/cyber/service_discovery/communication/subscriber_listener.cc +@@ -16,15 +16,23 @@ + + #include "cyber/service_discovery/communication/subscriber_listener.h" + ++#include ++ ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/subscriber/InstanceState.hpp" ++ ++#include "fastdds/dds/topic/TopicDescription.hpp" ++ + #include "cyber/common/log.h" + #include "cyber/transport/rtps/underlay_message.h" +-#include "cyber/transport/rtps/underlay_message_type.h" + + namespace apollo { + namespace cyber { + namespace service_discovery { + +-SubscriberListener::SubscriberListener(const NewMsgCallback& callback) ++SubscriberListener::SubscriberListener( ++ const transport::rtps::subsciber_callback& callback) + : callback_(callback) {} + + SubscriberListener::~SubscriberListener() { +@@ -32,22 +40,28 @@ SubscriberListener::~SubscriberListener() { + callback_ = nullptr; + } + +-void SubscriberListener::onNewDataMessage(eprosima::fastrtps::Subscriber* sub) { ++void SubscriberListener::on_data_available( ++ eprosima::fastdds::dds::DataReader* reader) { + RETURN_IF_NULL(callback_); + +- std::lock_guard lock(mutex_); +- eprosima::fastrtps::SampleInfo_t m_info; ++ eprosima::fastdds::dds::SampleInfo m_info; + cyber::transport::UnderlayMessage m; +- RETURN_IF(!sub->takeNextData(reinterpret_cast(&m), &m_info)); +- RETURN_IF(m_info.sampleKind != eprosima::fastrtps::ALIVE); +- +- callback_(m.data()); ++ while (reader->take_next_sample(reinterpret_cast(&m), &m_info) == ++ eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { ++ if (m_info.valid_data) { ++ // parameter 1 and 2 are not used ++ callback_(std::make_shared(m.data()), 0, msg_info_); ++ } else { ++ AERROR << "Remote writer for topic " ++ << reader->get_topicdescription()->get_name() << " is dead"; ++ } ++ } + } + +-void SubscriberListener::onSubscriptionMatched( +- eprosima::fastrtps::Subscriber* sub, +- eprosima::fastrtps::MatchingInfo& info) { +- (void)sub; ++void SubscriberListener::on_subscription_matched( ++ eprosima::fastdds::dds::DataReader* reader, ++ const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) { ++ (void)reader; + (void)info; + } + +diff --git a/cyber/service_discovery/communication/subscriber_listener.h b/cyber/service_discovery/communication/subscriber_listener.h +index 1c63c1f..586ecb3 100644 +--- a/cyber/service_discovery/communication/subscriber_listener.h ++++ b/cyber/service_discovery/communication/subscriber_listener.h +@@ -21,28 +21,33 @@ + #include + #include + +-#include "fastrtps/Domain.h" +-#include "fastrtps/subscriber/SampleInfo.h" +-#include "fastrtps/subscriber/Subscriber.h" +-#include "fastrtps/subscriber/SubscriberListener.h" ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/subscriber/DataReader.hpp" ++#include "fastdds/dds/subscriber/SampleInfo.hpp" ++#include "fastdds/dds/subscriber/SubscriberListener.hpp" ++ ++#include "cyber/transport/common/common_type.h" + + namespace apollo { + namespace cyber { + namespace service_discovery { + +-class SubscriberListener : public eprosima::fastrtps::SubscriberListener { ++class SubscriberListener : public eprosima::fastdds::dds::SubscriberListener { + public: +- using NewMsgCallback = std::function; +- +- explicit SubscriberListener(const NewMsgCallback& callback); ++ explicit SubscriberListener( ++ const transport::rtps::subsciber_callback& callback); + virtual ~SubscriberListener(); + +- void onNewDataMessage(eprosima::fastrtps::Subscriber* sub); +- void onSubscriptionMatched(eprosima::fastrtps::Subscriber* sub, +- eprosima::fastrtps::MatchingInfo& info); // NOLINT ++ void on_data_available(eprosima::fastdds::dds::DataReader* reader) override; ++ void on_subscription_matched( ++ eprosima::fastdds::dds::DataReader* reader, ++ const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) ++ override; // NOLINT + + private: +- NewMsgCallback callback_; ++ transport::rtps::subsciber_callback callback_; ++ transport::MessageInfo msg_info_; + std::mutex mutex_; + }; + +diff --git a/cyber/service_discovery/specific_manager/channel_manager.cc b/cyber/service_discovery/specific_manager/channel_manager.cc +index adc6c15..8a6c2cc 100644 +--- a/cyber/service_discovery/specific_manager/channel_manager.cc ++++ b/cyber/service_discovery/specific_manager/channel_manager.cc +@@ -1,5 +1,5 @@ + /****************************************************************************** +- * Copyright 2018 The Apollo Authors. All Rights Reserved. ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -17,7 +17,6 @@ + #include "cyber/service_discovery/specific_manager/channel_manager.h" + + #include +-#include + #include + + #include "cyber/common/global_data.h" +@@ -25,8 +24,6 @@ + #include "cyber/message/message_traits.h" + #include "cyber/message/py_message.h" + #include "cyber/message/raw_message.h" +-#include "cyber/state.h" +-#include "cyber/time/time.h" + + namespace apollo { + namespace cyber { +diff --git a/cyber/service_discovery/specific_manager/channel_manager.h b/cyber/service_discovery/specific_manager/channel_manager.h +index 69aba27..46de5f3 100644 +--- a/cyber/service_discovery/specific_manager/channel_manager.h ++++ b/cyber/service_discovery/specific_manager/channel_manager.h +@@ -23,6 +23,7 @@ + #include + #include + ++#include "cyber/proto/role_attributes.pb.h" + #include "cyber/service_discovery/container/graph.h" + #include "cyber/service_discovery/container/multi_value_warehouse.h" + #include "cyber/service_discovery/container/single_value_warehouse.h" +diff --git a/cyber/service_discovery/specific_manager/channel_manager_test.cc b/cyber/service_discovery/specific_manager/channel_manager_test.cc +index a83303c..c3f44c5 100644 +--- a/cyber/service_discovery/specific_manager/channel_manager_test.cc ++++ b/cyber/service_discovery/specific_manager/channel_manager_test.cc +@@ -16,15 +16,13 @@ + + #include "cyber/service_discovery/specific_manager/channel_manager.h" + +-#include + #include + #include + #include "gtest/gtest.h" + ++#include "cyber/proto/unit_test.pb.h" + #include "cyber/common/global_data.h" + #include "cyber/message/message_traits.h" +-#include "cyber/message/protobuf_factory.h" +-#include "cyber/proto/unit_test.pb.h" + #include "cyber/transport/common/identity.h" + + namespace apollo { +diff --git a/cyber/service_discovery/specific_manager/manager.cc b/cyber/service_discovery/specific_manager/manager.cc +index 353ef73..e97e3aa 100644 +--- a/cyber/service_discovery/specific_manager/manager.cc ++++ b/cyber/service_discovery/specific_manager/manager.cc +@@ -21,15 +21,12 @@ + #include "cyber/message/message_traits.h" + #include "cyber/time/time.h" + #include "cyber/transport/qos/qos_profile_conf.h" +-#include "cyber/transport/rtps/attributes_filler.h" + #include "cyber/transport/rtps/underlay_message.h" +-#include "cyber/transport/rtps/underlay_message_type.h" + + namespace apollo { + namespace cyber { + namespace service_discovery { + +-using transport::AttributesFiller; + using transport::QosProfileConf; + + Manager::Manager() +@@ -39,15 +36,14 @@ Manager::Manager() + change_type_(proto::ChangeType::CHANGE_PARTICIPANT), + channel_name_(""), + publisher_(nullptr), +- subscriber_(nullptr), +- listener_(nullptr) { ++ subscriber_(nullptr) { + host_name_ = common::GlobalData::Instance()->HostName(); + process_id_ = common::GlobalData::Instance()->ProcessId(); + } + + Manager::~Manager() { Shutdown(); } + +-bool Manager::StartDiscovery(RtpsParticipant* participant) { ++bool Manager::StartDiscovery(const ParticipantPtr& participant) { + if (participant == nullptr) { + return false; + } +@@ -59,6 +55,7 @@ bool Manager::StartDiscovery(RtpsParticipant* participant) { + StopDiscovery(); + return false; + } ++ participant_ = participant; + return true; + } + +@@ -66,24 +63,6 @@ void Manager::StopDiscovery() { + if (!is_discovery_started_.exchange(false)) { + return; + } +- +- { +- std::lock_guard lg(lock_); +- if (publisher_ != nullptr) { +- eprosima::fastrtps::Domain::removePublisher(publisher_); +- publisher_ = nullptr; +- } +- } +- +- if (subscriber_ != nullptr) { +- eprosima::fastrtps::Domain::removeSubscriber(subscriber_); +- subscriber_ = nullptr; +- } +- +- if (listener_ != nullptr) { +- delete listener_; +- listener_ = nullptr; +- } + } + + void Manager::Shutdown() { +@@ -137,28 +116,16 @@ void Manager::RemoveChangeListener(const ChangeConnection& conn) { + local_conn.Disconnect(); + } + +-bool Manager::CreatePublisher(RtpsParticipant* participant) { +- RtpsPublisherAttr pub_attr; +- RETURN_VAL_IF( +- !AttributesFiller::FillInPubAttr( +- channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, &pub_attr), +- false); +- publisher_ = +- eprosima::fastrtps::Domain::createPublisher(participant, pub_attr); ++bool Manager::CreatePublisher(const ParticipantPtr& participant) { ++ publisher_ = participant->CreatePublisher( ++ this->channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE); + return publisher_ != nullptr; + } + +-bool Manager::CreateSubscriber(RtpsParticipant* participant) { +- RtpsSubscriberAttr sub_attr; +- RETURN_VAL_IF( +- !AttributesFiller::FillInSubAttr( +- channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, &sub_attr), +- false); +- listener_ = new SubscriberListener( ++bool Manager::CreateSubscriber(const ParticipantPtr& participant) { ++ subscriber_ = participant->CreateSubscriber( ++ this->channel_name_, QosProfileConf::QOS_PROFILE_TOPO_CHANGE, + std::bind(&Manager::OnRemoteChange, this, std::placeholders::_1)); +- +- subscriber_ = eprosima::fastrtps::Domain::createSubscriber( +- participant, sub_attr, listener_); + return subscriber_ != nullptr; + } + +@@ -185,14 +152,14 @@ void Manager::Convert(const RoleAttributes& attr, RoleType role, + + void Manager::Notify(const ChangeMsg& msg) { signal_(msg); } + +-void Manager::OnRemoteChange(const std::string& msg_str) { ++void Manager::OnRemoteChange(const std::shared_ptr& msg_str) { + if (is_shutdown_.load()) { + ADEBUG << "the manager has been shut down."; + return; + } + + ChangeMsg msg; +- RETURN_IF(!message::ParseFromString(msg_str, &msg)); ++ RETURN_IF(!message::ParseFromString(*msg_str, &msg)); + if (IsFromSameProcess(msg)) { + return; + } +@@ -211,7 +178,7 @@ bool Manager::Publish(const ChangeMsg& msg) { + { + std::lock_guard lg(lock_); + if (publisher_ != nullptr) { +- return publisher_->write(reinterpret_cast(&m)); ++ return publisher_->Write(m); + } + } + return true; +diff --git a/cyber/service_discovery/specific_manager/manager.h b/cyber/service_discovery/specific_manager/manager.h +index 22b8341..d2aebcb 100644 +--- a/cyber/service_discovery/specific_manager/manager.h ++++ b/cyber/service_discovery/specific_manager/manager.h +@@ -19,19 +19,22 @@ + + #include + #include ++#include + #include + #include + +-#include "fastrtps/Domain.h" +-#include "fastrtps/attributes/PublisherAttributes.h" +-#include "fastrtps/attributes/SubscriberAttributes.h" +-#include "fastrtps/participant/Participant.h" +-#include "fastrtps/publisher/Publisher.h" +-#include "fastrtps/subscriber/Subscriber.h" ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/publisher/qos/PublisherQos.hpp" ++#include "fastdds/dds/subscriber/qos/SubscriberQos.hpp" + +-#include "cyber/base/signal.h" + #include "cyber/proto/topology_change.pb.h" ++ ++#include "cyber/base/signal.h" + #include "cyber/service_discovery/communication/subscriber_listener.h" ++#include "cyber/transport/rtps/participant.h" ++#include "cyber/transport/rtps/publisher.h" ++#include "cyber/transport/rtps/subscriber.h" + + namespace apollo { + namespace cyber { +@@ -53,11 +56,9 @@ class Manager { + using ChangeSignal = base::Signal; + using ChangeFunc = std::function; + using ChangeConnection = base::Connection; +- +- using RtpsParticipant = eprosima::fastrtps::Participant; +- using RtpsPublisherAttr = eprosima::fastrtps::PublisherAttributes; +- using RtpsSubscriberAttr = eprosima::fastrtps::SubscriberAttributes; +- ++ using ParticipantPtr = std::shared_ptr; ++ using PublisherPtr = std::shared_ptr; ++ using SubscriberPtr = std::shared_ptr; + /** + * @brief Construct a new Manager object + */ +@@ -75,7 +76,7 @@ class Manager { + * @return true if start successfully + * @return false if start fail + */ +- bool StartDiscovery(RtpsParticipant* participant); ++ bool StartDiscovery(const ParticipantPtr& participant); + + /** + * @brief Stop topology discovery +@@ -136,8 +137,8 @@ class Manager { + int process_id) = 0; + + protected: +- bool CreatePublisher(RtpsParticipant* participant); +- bool CreateSubscriber(RtpsParticipant* participant); ++ bool CreatePublisher(const ParticipantPtr& participant); ++ bool CreateSubscriber(const ParticipantPtr& participant); + + virtual bool Check(const RoleAttributes& attr) = 0; + virtual void Dispose(const ChangeMsg& msg) = 0; +@@ -148,7 +149,7 @@ class Manager { + + void Notify(const ChangeMsg& msg); + bool Publish(const ChangeMsg& msg); +- void OnRemoteChange(const std::string& msg_str); ++ void OnRemoteChange(const std::shared_ptr& msg_str); + bool IsFromSameProcess(const ChangeMsg& msg); + + std::atomic is_shutdown_; +@@ -158,10 +159,10 @@ class Manager { + std::string host_name_; + int process_id_; + std::string channel_name_; +- eprosima::fastrtps::Publisher* publisher_; ++ PublisherPtr publisher_; ++ SubscriberPtr subscriber_; ++ ParticipantPtr participant_; + std::mutex lock_; +- eprosima::fastrtps::Subscriber* subscriber_; +- SubscriberListener* listener_; + + ChangeSignal signal_; + }; +diff --git a/cyber/service_discovery/specific_manager/node_manager.cc b/cyber/service_discovery/specific_manager/node_manager.cc +index 8fde169..a48559a 100644 +--- a/cyber/service_discovery/specific_manager/node_manager.cc ++++ b/cyber/service_discovery/specific_manager/node_manager.cc +@@ -18,7 +18,6 @@ + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/state.h" +-#include "cyber/time/time.h" + + namespace apollo { + namespace cyber { +diff --git a/cyber/service_discovery/specific_manager/service_manager.cc b/cyber/service_discovery/specific_manager/service_manager.cc +index 273b87c..19e39be 100644 +--- a/cyber/service_discovery/specific_manager/service_manager.cc ++++ b/cyber/service_discovery/specific_manager/service_manager.cc +@@ -15,10 +15,8 @@ + *****************************************************************************/ + + #include "cyber/service_discovery/specific_manager/service_manager.h" +-#include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/common/util.h" +-#include "cyber/time/time.h" + + namespace apollo { + namespace cyber { +diff --git a/cyber/service_discovery/topology_manager.cc b/cyber/service_discovery/topology_manager.cc +index 419f9bd..a2fd97d 100644 +--- a/cyber/service_discovery/topology_manager.cc ++++ b/cyber/service_discovery/topology_manager.cc +@@ -29,8 +29,7 @@ TopologyManager::TopologyManager() + node_manager_(nullptr), + channel_manager_(nullptr), + service_manager_(nullptr), +- participant_(nullptr), +- participant_listener_(nullptr) { ++ participant_(nullptr) { + Init(); + } + +@@ -48,9 +47,6 @@ void TopologyManager::Shutdown() { + service_manager_->Shutdown(); + participant_->Shutdown(); + +- delete participant_listener_; +- participant_listener_ = nullptr; +- + change_signal_.DisconnectAllSlots(); + } + +@@ -80,8 +76,6 @@ bool TopologyManager::Init() { + if (!result) { + AERROR << "init manager failed."; + participant_ = nullptr; +- delete participant_listener_; +- participant_listener_ = nullptr; + node_manager_ = nullptr; + channel_manager_ = nullptr; + service_manager_ = nullptr; +@@ -93,29 +87,34 @@ bool TopologyManager::Init() { + } + + bool TopologyManager::InitNodeManager() { +- return node_manager_->StartDiscovery(participant_->fastrtps_participant()); ++ return node_manager_->StartDiscovery(participant_); + } + + bool TopologyManager::InitChannelManager() { +- return channel_manager_->StartDiscovery(participant_->fastrtps_participant()); ++ return channel_manager_->StartDiscovery(participant_); + } + + bool TopologyManager::InitServiceManager() { +- return service_manager_->StartDiscovery(participant_->fastrtps_participant()); ++ return service_manager_->StartDiscovery(participant_); + } + + bool TopologyManager::CreateParticipant() { + std::string participant_name = + common::GlobalData::Instance()->HostName() + '+' + + std::to_string(common::GlobalData::Instance()->ProcessId()); +- participant_listener_ = new ParticipantListener(std::bind( +- &TopologyManager::OnParticipantChange, this, std::placeholders::_1)); + participant_ = std::make_shared( +- participant_name, 11511, participant_listener_); ++ participant_name, 11511, ++ new ParticipantListener(std::bind(&TopologyManager::OnParticipantChange, ++ this, std::placeholders::_1))); ++ if (!participant_->Init()) { ++ AERROR << "init participant failed"; ++ return false; ++ } + return true; + } + +-void TopologyManager::OnParticipantChange(const PartInfo& info) { ++void TopologyManager::OnParticipantChange( ++ const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info) { + ChangeMsg msg; + if (!Convert(info, &msg)) { + return; +@@ -135,28 +134,39 @@ void TopologyManager::OnParticipantChange(const PartInfo& info) { + change_signal_(msg); + } + +-bool TopologyManager::Convert(const PartInfo& info, ChangeMsg* msg) { +- auto guid = info.rtps.m_guid; +- auto status = info.rtps.m_status; ++bool TopologyManager::Convert( ++ const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info, ++ ChangeMsg* msg) { ++ auto guid = info.info.m_guid; + std::string participant_name(""); +- OperateType opt_type = OperateType::OPT_JOIN; ++ OperateType opt_type; + +- switch (status) { +- case eprosima::fastrtps::rtps::DISCOVERY_STATUS::DISCOVERED_RTPSPARTICIPANT: +- participant_name = info.rtps.m_RTPSParticipantName; ++ switch (info.status) { ++ case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: ++ DISCOVERED_PARTICIPANT: ++ participant_name = info.info.m_participantName; ++ AINFO << "discovery participant name:" << participant_name; + participant_names_[guid] = participant_name; + opt_type = OperateType::OPT_JOIN; + break; +- +- case eprosima::fastrtps::rtps::DISCOVERY_STATUS::REMOVED_RTPSPARTICIPANT: +- case eprosima::fastrtps::rtps::DISCOVERY_STATUS::DROPPED_RTPSPARTICIPANT: ++ case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: ++ REMOVED_PARTICIPANT: + if (participant_names_.find(guid) != participant_names_.end()) { + participant_name = participant_names_[guid]; ++ AINFO << "remove participant name:" << participant_name; ++ participant_names_.erase(guid); ++ } ++ opt_type = OperateType::OPT_LEAVE; ++ break; ++ case eprosima::fastrtps::rtps::ParticipantDiscoveryInfo::DISCOVERY_STATUS:: ++ DROPPED_PARTICIPANT: ++ if (participant_names_.find(guid) != participant_names_.end()) { ++ participant_name = participant_names_[guid]; ++ AINFO << "dropped participant name:" << participant_name; + participant_names_.erase(guid); + } + opt_type = OperateType::OPT_LEAVE; + break; +- + default: + break; + } +diff --git a/cyber/service_discovery/topology_manager.h b/cyber/service_discovery/topology_manager.h +index 44b47b5..dd5b23f 100644 +--- a/cyber/service_discovery/topology_manager.h ++++ b/cyber/service_discovery/topology_manager.h +@@ -66,9 +66,9 @@ class TopologyManager { + using ChangeSignal = base::Signal; + using ChangeFunc = std::function; + using ChangeConnection = base::Connection; ++ using ParticipantPtr = std::shared_ptr; + using PartNameContainer = + std::map; +- using PartInfo = eprosima::fastrtps::ParticipantDiscoveryInfo; + + virtual ~TopologyManager(); + +@@ -114,8 +114,10 @@ class TopologyManager { + bool InitServiceManager(); + + bool CreateParticipant(); +- void OnParticipantChange(const PartInfo& info); +- bool Convert(const PartInfo& info, ChangeMsg* change_msg); ++ void OnParticipantChange( ++ const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info); ++ bool Convert(const eprosima::fastrtps::rtps::ParticipantDiscoveryInfo& info, ++ ChangeMsg* change_msg); + bool ParseParticipantName(const std::string& participant_name, + std::string* host_name, int* process_id); + +@@ -123,9 +125,7 @@ class TopologyManager { + NodeManagerPtr node_manager_; /// shared ptr of NodeManager + ChannelManagerPtr channel_manager_; /// shared ptr of ChannelManager + ServiceManagerPtr service_manager_; /// shared ptr of ServiceManager +- /// rtps participant to publish and subscribe +- transport::ParticipantPtr participant_; +- ParticipantListener* participant_listener_; ++ ParticipantPtr participant_; + ChangeSignal change_signal_; /// topology changing signal, + ///< connect to `ChangeFunc`s + PartNameContainer participant_names_; /// other participant in the topology +diff --git a/cyber/setup.bash b/cyber/setup.bash +index cdabc56..1d0d690 100755 +--- a/cyber/setup.bash ++++ b/cyber/setup.bash +@@ -8,6 +8,7 @@ export CYBER_PATH="${APOLLO_ROOT_DIR}/cyber" + bazel_bin_path="${APOLLO_ROOT_DIR}/bazel-bin" + mainboard_path="${bazel_bin_path}/cyber/mainboard" + cyber_tool_path="${bazel_bin_path}/cyber/tools" ++performance_path="${cyber_tool_path}/cyber_performance" + recorder_path="${cyber_tool_path}/cyber_recorder" + launch_path="${cyber_tool_path}/cyber_launch" + channel_path="${cyber_tool_path}/cyber_channel" +@@ -20,7 +21,7 @@ visualizer_path="${bazel_bin_path}/modules/tools/visualizer" + for entry in "${mainboard_path}" \ + "${recorder_path}" "${monitor_path}" \ + "${channel_path}" "${node_path}" \ +- "${service_path}" \ ++ "${service_path}" "${performance_path}" \ + "${launch_path}" \ + "${visualizer_path}" ; do + pathprepend "${entry}" +@@ -38,9 +39,9 @@ export GLOG_alsologtostderr=0 + export GLOG_colorlogtostderr=1 + export GLOG_minloglevel=0 + +-export sysmo_start=0 +- + # for DEBUG log + #export GLOG_v=4 + +-source ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash ++[[ -e ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash ]] && source ${CYBER_PATH}/tools/cyber_tools_auto_complete.bash ++ ++export sysmo_start=0 +\ No newline at end of file +diff --git a/cyber/statistics/BUILD b/cyber/statistics/BUILD +new file mode 100644 +index 0000000..6593465 +--- /dev/null ++++ b/cyber/statistics/BUILD +@@ -0,0 +1,19 @@ ++load("//tools:cpplint.bzl", "cpplint") ++load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package") ++ ++apollo_cc_library( ++ name = "apollo_statistics", ++ srcs = ["statistics.cc"], ++ hdrs = ["statistics.h"], ++ linkopts = ["-lbvar"], ++ deps = [ ++ "//cyber/common:cyber_common", ++ "//cyber/proto:role_attributes_cc_proto", ++ "//cyber/time:cyber_time", ++ "@com_github_gflags_gflags//:gflags", ++ ], ++) ++ ++apollo_package() ++ ++cpplint() +diff --git a/cyber/statistics/statistics.cc b/cyber/statistics/statistics.cc +new file mode 100644 +index 0000000..f786473 +--- /dev/null ++++ b/cyber/statistics/statistics.cc +@@ -0,0 +1,130 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/statistics/statistics.h" ++ ++namespace apollo { ++namespace cyber { ++namespace statistics { ++ ++Statistics::Statistics() {} ++ ++bool Statistics::RegisterChanVar(const proto::RoleAttributes& role_attr) { ++ if (latency_map_.find(GetProcLatencyKey(role_attr)) != latency_map_.end()) { ++ AERROR << "Failed to create proc latency var: " ++ "reader with the same channel already exists."; ++ return false; ++ } ++ ++ if (latency_map_.find(GetTranLatencyKey(role_attr)) != latency_map_.end()) { ++ AERROR << "Failed to create tran latency var: " ++ "reader with the same channel already exists."; ++ return false; ++ } ++ ++ if (latency_map_.find(GetCyberLatencyKey(role_attr)) != latency_map_.end()) { ++ AERROR << "Failed to create cyber latency var: " ++ "reader with the same channel already exists."; ++ return false; ++ } ++ ++ latency_map_[GetProcLatencyKey(role_attr)] = ++ std::make_shared<::bvar::LatencyRecorder>( ++ role_attr.node_name() + "-" ++ + role_attr.channel_name(), "proc"); ++ if (role_attr.channel_name() != TIMER_COMPONENT_CHAN_NAME) { ++ latency_map_[GetTranLatencyKey(role_attr)] = ++ std::make_shared<::bvar::LatencyRecorder>( ++ role_attr.node_name() + "-" + ++ role_attr.channel_name(), "tran"); ++ latency_map_[GetCyberLatencyKey(role_attr)] = ++ std::make_shared<::bvar::LatencyRecorder>( ++ role_attr.node_name() + "-" + ++ role_attr.channel_name(), "cyber"); ++ status_map_[GetStartProcessStatusKey(role_attr)] = ++ std::make_shared<::bvar::Status>( ++ role_attr.node_name() + "-" + ++ role_attr.channel_name() + "-process", 0); ++ status_map_[GetTotalMsgsStatusKey(role_attr)] = ++ std::make_shared<::bvar::Status>( ++ role_attr.node_name() + "-" + ++ role_attr.channel_name() + "-total-msgs-nums", 0); ++ adder_map_[GetTotalRecvStatusKey(role_attr)] = ++ std::make_shared<::bvar::Adder>( ++ role_attr.node_name() + ++ "-" + role_attr.channel_name() + "-recv-msgs-nums"); ++ } ++ return true; ++} ++ ++StatusVarPtr Statistics::GetProcStatusVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = status_map_.find(GetStartProcessStatusKey(role_attr)); ++ if (v == status_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++LatencyVarPtr Statistics::GetChanProcVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = latency_map_.find(GetProcLatencyKey(role_attr)); ++ if (v == latency_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++LatencyVarPtr Statistics::GetChanTranVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = latency_map_.find(GetTranLatencyKey(role_attr)); ++ if (v == latency_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++LatencyVarPtr Statistics::GetChanCyberVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = latency_map_.find(GetCyberLatencyKey(role_attr)); ++ if (v == latency_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++StatusVarPtr Statistics::GetTotalMsgsStatusVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = status_map_.find(GetTotalMsgsStatusKey(role_attr)); ++ if (v == status_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++AdderVarPtr Statistics::GetAdderVar( ++ const proto::RoleAttributes& role_attr) { ++ auto v = adder_map_.find(GetTotalRecvStatusKey(role_attr)); ++ if (v == adder_map_.end()) { ++ return nullptr; ++ } ++ return v->second; ++} ++ ++ ++} // namespace statistics ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/statistics/statistics.h b/cyber/statistics/statistics.h +new file mode 100644 +index 0000000..3d651da +--- /dev/null ++++ b/cyber/statistics/statistics.h +@@ -0,0 +1,314 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#pragma once ++ ++#ifndef CYBER_STATISTICS_STATISTICS_H_ ++#define CYBER_STATISTICS_STATISTICS_H_ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "cyber/base/macros.h" ++#include "cyber/common/log.h" ++#include "cyber/proto/role_attributes.pb.h" ++#include "cyber/common/macros.h" ++#include "cyber/time/time.h" ++#include "third_party/var/bvar/bvar.h" ++ ++namespace apollo { ++namespace cyber { ++namespace statistics { ++ ++using LatencyVarPtr = std::shared_ptr<::bvar::LatencyRecorder>; ++using StatusVarPtr = std::shared_ptr<::bvar::Status>; ++using AdderVarPtr = std::shared_ptr<::bvar::Adder>; ++ ++struct SpanHandler { ++ std::string name; ++ uint64_t start_time; ++ uint64_t end_time; ++ std::shared_ptr<::bvar::LatencyRecorder> span_trace_node; ++ uint64_t min_ns = 0; ++}; ++ ++static const std::string TIMER_COMPONENT_CHAN_NAME = "_timer_component"; // NOLINT ++ ++class Statistics { ++ public: ++ ~Statistics() {} ++ bool RegisterChanVar(const proto::RoleAttributes& role_attr); ++ ++ inline bool CreateSpan(std::string name, uint64_t min_ns = 0); ++ inline bool StartSpan(std::string name); ++ inline bool EndSpan(std::string name); ++ ++ inline void DisableChanVar() { ++ disable_chan_var_ = true; ++ } ++ ++ template ++ std::shared_ptr<::bvar::Adder> CreateAdder( ++ const proto::RoleAttributes& role_attr) { ++ std::string expose_name = ++ role_attr.node_name() + "-" + role_attr.channel_name(); ++ return std::make_shared<::bvar::Adder>(expose_name); ++ } ++ ++ template ++ bool SamplingProcLatency( ++ const proto::RoleAttributes& role_attr, SampleT sample) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ auto var_ptr = GetChanProcVar(role_attr); ++ if (var_ptr != nullptr) { ++ (*var_ptr) << sample; ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ template ++ bool SamplingTranLatency( ++ const proto::RoleAttributes& role_attr, SampleT sample) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return true; ++ } ++ auto var_ptr = GetChanTranVar(role_attr); ++ if (var_ptr != nullptr) { ++ (*var_ptr) << sample; ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ template ++ bool SamplingCyberLatency( ++ const proto::RoleAttributes& role_attr, SampleT sample) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return true; ++ } ++ auto var_ptr = GetChanCyberVar(role_attr); ++ if (var_ptr != nullptr) { ++ (*var_ptr) << sample; ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ bool SetProcStatus(const proto::RoleAttributes& role_attr, uint64_t val) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return true; ++ } ++ auto var_ptr = GetProcStatusVar(role_attr); ++ if (var_ptr != nullptr) { ++ var_ptr->set_value(val); ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ bool GetProcStatus(const proto::RoleAttributes& role_attr, uint64_t* val) { ++ if (disable_chan_var_) { ++ *val = 0; ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return false; ++ } ++ auto var_ptr = GetProcStatusVar(role_attr); ++ if (var_ptr != nullptr) { ++ *val = var_ptr->get_value(); ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ bool SetTotalMsgsStatus(const proto::RoleAttributes& role_attr, int32_t val) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return true; ++ } ++ auto var_ptr = GetTotalMsgsStatusVar(role_attr); ++ if (var_ptr != nullptr) { ++ var_ptr->set_value(val); ++ } else { ++ return false; ++ } ++ return true; ++ } ++ ++ bool AddRecvCount(const proto::RoleAttributes& role_attr, int total_msg_val) { ++ if (disable_chan_var_) { ++ return true; ++ } ++ if (role_attr.channel_name() == TIMER_COMPONENT_CHAN_NAME) { ++ return true; ++ } ++ ++ auto var_ptr = GetAdderVar(role_attr); ++ if (var_ptr == nullptr) { ++ return true; ++ } ++ ++ if cyber_unlikely(first_recv_) { ++ (*var_ptr) << total_msg_val; ++ first_recv_ = false; ++ return true; ++ } ++ ++ (*var_ptr) << 1; ++ ++ return true; ++ } ++ ++ private: ++ LatencyVarPtr GetChanProcVar(const proto::RoleAttributes& role_attr); ++ ++ LatencyVarPtr GetChanTranVar(const proto::RoleAttributes& role_attr); ++ ++ LatencyVarPtr GetChanCyberVar(const proto::RoleAttributes& role_attr); ++ ++ StatusVarPtr GetProcStatusVar(const proto::RoleAttributes& role_attr); ++ ++ AdderVarPtr GetAdderVar(const proto::RoleAttributes& role_attr); ++ ++ StatusVarPtr GetTotalMsgsStatusVar(const proto::RoleAttributes& role_attr); ++ ++ inline uint64_t GetMicroTimeNow() const noexcept; ++ ++ inline const std::string GetProcLatencyKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + role_attr.channel_name() + "proc"; ++ } ++ ++ inline const std::string GetTranLatencyKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + role_attr.channel_name() + "tran"; ++ } ++ ++ inline const std::string GetCyberLatencyKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + role_attr.channel_name() + "cyber"; ++ } ++ ++ inline const std::string GetStartProcessStatusKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + \ ++ role_attr.channel_name() + "process-status"; ++ } ++ ++ inline const std::string GetTotalMsgsStatusKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + \ ++ role_attr.channel_name() + "total-sended-msgs"; ++ } ++ ++ inline const std::string GetTotalRecvStatusKey( ++ const proto::RoleAttributes& role_attr) { ++ return role_attr.node_name() + "-" + role_attr.channel_name() + "recv-msgs"; ++ } ++ ++ std::unordered_map latency_map_; ++ std::unordered_map status_map_; ++ std::unordered_map adder_map_; ++ ++ std::unordered_map> span_handlers_; ++ ++ bool first_recv_ = true; ++ bool disable_chan_var_ = false; ++ ++ DECLARE_SINGLETON(Statistics) ++}; ++ ++inline uint64_t Statistics::GetMicroTimeNow() const noexcept { ++ return Time::Now().ToMicrosecond(); ++} ++ ++inline bool Statistics::CreateSpan(std::string name, uint64_t min_ns) { ++ if (cyber_unlikely(span_handlers_.find(name) != span_handlers_.end())) { ++ AERROR << "span handler " << name << "has been created!"; ++ return false; ++ } ++ auto handler = std::make_shared(); ++ handler->name = name; ++ handler->span_trace_node = std::move( ++ std::make_shared<::bvar::LatencyRecorder>(name, "user", 1200)); ++ handler->min_ns = min_ns; ++ ++ span_handlers_[name] = std::move(handler); ++ return true; ++} ++ ++inline bool Statistics::StartSpan(std::string name) { ++ auto it = span_handlers_.find(name); ++ if (cyber_unlikely(it == span_handlers_.end())) { ++ AERROR << "span handler " << name << "not found!"; ++ return false; ++ } ++ it->second->start_time = std::move(GetMicroTimeNow()); ++ return true; ++} ++ ++inline bool Statistics::EndSpan(std::string name) { ++ auto it = span_handlers_.find(name); ++ if (cyber_unlikely(it == span_handlers_.end())) { ++ AERROR << "span handler " << name << "not found!"; ++ return false; ++ } ++ it->second->end_time = std::move(GetMicroTimeNow()); ++ auto handler = it->second; ++ auto diff = handler->end_time - handler->start_time; ++ if (cyber_unlikely(diff < handler->min_ns)) { ++ AWARN << "Time span less than preset value: " \ ++ << diff << " vs " << handler->min_ns; ++ return false; ++ } ++ if (cyber_unlikely(diff > INT32_MAX)) { ++ AWARN << "Time span is larger than INT32_MAX: " << diff << ", drop it..."; ++ return false; ++ } ++ *(handler->span_trace_node) << diff; ++ return true; ++} ++ ++} // namespace statistics ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_STATISTICS_STATISTICS_H_ +diff --git a/cyber/tools/cyber_launch/cyber_launch.py b/cyber/tools/cyber_launch/cyber_launch.py +index 7b1df7d..c13d126 100755 +--- a/cyber/tools/cyber_launch/cyber_launch.py ++++ b/cyber/tools/cyber_launch/cyber_launch.py +@@ -25,7 +25,7 @@ import subprocess + import sys + import time + import threading +-import traceback ++from datetime import datetime + + import xml.etree.ElementTree as ET + +@@ -48,13 +48,39 @@ COLOR_SEQ = "\033[1;%dm" + BOLD_SEQ = "\033[1m" + + COLORS = { +- 'INFO': GREEN, +- 'WARNING': YELLOW, +- 'DEBUG': BLUE, +- 'ERROR': RED, ++ 'INFO': GREEN, ++ 'WARNING': YELLOW, ++ 'DEBUG': BLUE, ++ 'ERROR': RED, + 'CRITICAL': YELLOW + } + ++logger = logging.Logger(__name__) ++ ++# file logger ++workspace_path = os.getenv('APOLLO_ENV_WORKROOT') or '/apollo' ++log_dir_path = os.path.join(workspace_path, 'data/log') ++if not os.path.exists(log_dir_path): ++ os.makedirs(log_dir_path) ++log_name = 'cyber_launch.log.INFO.{}.{}'.format( ++ datetime.now().strftime("%Y%m%d-%H%M%S"), str(g_process_pid)) ++log_file_path = os.path.join(log_dir_path, log_name) ++file_formater = logging.Formatter( ++ '%(levelname)s [%(asctime)s] %(lineno)s: %(message)s') ++file_hd = logging.FileHandler(filename=log_file_path) ++file_hd.setFormatter(file_formater) ++file_hd.setLevel(logging.INFO) ++logger.addHandler(file_hd) ++link_log_file = os.path.join(log_dir_path, 'cyber_launch.INFO') ++try: ++ if os.path.exists(link_log_file) or os.path.islink(link_log_file): ++ os.remove(link_log_file) ++ os.symlink(log_name, link_log_file) ++except Exception as e: ++ # Maybe mulitple process create link, ignore it ++ pass ++ ++ + class ColoredFormatter(logging.Formatter): + + def __init__(self, msg): +@@ -79,7 +105,6 @@ class ColoredFormatter(logging.Formatter): + color_formatter = ColoredFormatter("[%(levelname)-18s] %(message)s") + console = logging.StreamHandler() + console.setFormatter(color_formatter) +-logger = logging.Logger(__name__) + logger.addHandler(console) + + +@@ -105,17 +130,22 @@ def module_monitor(mod): + while True: + line = mod.popen.stdout.readline() + if line: +- logger.debug('%s# %s' % (mod.name, line.decode('utf8').strip('\n'))) ++ logger.debug('%s# %s' % ++ (mod.name, line.decode('utf8').strip('\n'))) + continue + time.sleep(0.01) + + + class ProcessWrapper(object): + +- def __init__(self, binary_path, dag_num, dag_list, plugin_list, process_name, process_type, +- sched_name, extra_args_list, exception_handler='', respawn_limit=g_default_respawn_limit): ++ def __init__(self, binary_path, dag_num, dag_list, plugin_list, ++ process_name, process_type, sched_name, extra_args_list, ++ exception_handler='', respawn_limit=g_default_respawn_limit, ++ cpu_profile_file='', mem_profile_file='', nice=0): + self.time_of_death = None + self.started = False ++ self.cpu_profile = False ++ self.mem_profile = False + self.binary_path = binary_path + self.dag_num = dag_num + self.dag_list = dag_list +@@ -131,6 +161,13 @@ class ProcessWrapper(object): + self.exception_handler = exception_handler + self.respawn_limit = respawn_limit + self.respawn_cnt = 0 ++ self.cpu_profile_file = cpu_profile_file ++ self.mem_profile_file = mem_profile_file ++ if self.cpu_profile_file != '': ++ self.cpu_profile = True ++ if self.mem_profile_file != '': ++ self.mem_profile = True ++ self.nice = nice + + def wait(self, timeout_secs=None): + """ +@@ -171,11 +208,19 @@ class ProcessWrapper(object): + args_list.append(self.sched_name) + if len(self.extra_args_list) != 0: + args_list.extend(self.extra_args_list) ++ if self.cpu_profile: ++ args_list.append('-c') ++ args_list.append('-o') ++ args_list.append(self.cpu_profile_file) ++ if self.mem_profile: ++ args_list.append('-H') ++ args_list.append('-O') ++ args_list.append(self.mem_profile_file) + + self.args = args_list + + try: +- self.popen = subprocess.Popen(args_list, stdout=subprocess.PIPE, ++ self.popen = subprocess.Popen(args_list, stdout=None, + stderr=subprocess.STDOUT) + except Exception as err: + logger.error('Subprocess Popen exception: ' + str(err)) +@@ -185,12 +230,23 @@ class ProcessWrapper(object): + logger.error('Start process [%s] failed.', self.name) + return 2 + +- th = threading.Thread(target=module_monitor, args=(self, )) +- th.setDaemon(True) +- th.start() ++ # th = threading.Thread(target=module_monitor, args=(self, )) ++ # th.setDaemon(True) ++ # th.start() + self.started = True + self.pid = self.popen.pid +- logger.info('Start process [%s] successfully. pid: %d', self.name, self.popen.pid) ++ if self.nice != 0: ++ sudo_check = subprocess.run( ++ ['sudo', '-n', 'true'], stdout=None, stderr=None) ++ if sudo_check.returncode == 0: ++ subprocess.run( ++ ["sudo", "renice", "-n", str(self.nice), "-p", str(self.pid)], ++ stdout=None, stderr=subprocess.STDOUT) ++ else: ++ logger.error( ++ 'Can not renice because users do not have sudo privileges') ++ logger.info( ++ 'Start process [%s] successfully. pid: %d', self.name, self.popen.pid) + logger.info('-' * 120) + return 0 + +@@ -248,9 +304,11 @@ class ProcessMonitor(object): + @type p: L{Process} + """ + if self.has_process(p.name): +- logger.error('Cannot add process due to duplicate name "%s".', p.name) ++ logger.error( ++ 'Cannot add process due to duplicate name "%s".', p.name) + elif self.is_shutdown: +- logger.error('Cannot add process [%s] due to monitor has been stopped.', p.name) ++ logger.error( ++ 'Cannot add process [%s] due to monitor has been stopped.', p.name) + else: + self.procs.append(p) + +@@ -274,13 +332,15 @@ class ProcessMonitor(object): + continue + if pw.exception_handler == "respawn": + if pw.respawn_cnt < pw.respawn_limit: +- logger.warning('child process [%s][%d] exit, respawn!', pw.name, pw.pid) ++ logger.warning( ++ 'child process [%s][%d] exit, respawn!', pw.name, pw.pid) + pw.start() + pw.respawn_cnt += 1 + else: + dead_cnt += 1 + elif pw.exception_handler == "exit": +- logger.warning('child process [%s][%d] exit, stop all', pw.name, pw.pid) ++ logger.warning( ++ 'child process [%s][%d] exit, stop all', pw.name, pw.pid) + # stop and exit + stop() + else: +@@ -318,10 +378,12 @@ class ProcessMonitor(object): + try: + p.wait(force_stop_timeout_secs) + except subprocess.TimeoutExpired as e: +- logger.warning("Begin force kill process [%s][%s].", p.name, p.pid) ++ logger.warning( ++ "Begin force kill process [%s][%s].", p.name, p.pid) + p.kill() + p.wait() +- logger.info('Process [%s] has been stopped. dag_file: %s', p.name, p.dag_list) ++ logger.info( ++ 'Process [%s] has been stopped. dag_file: %s', p.name, p.dag_list) + # Reset members + self.procs = [] + self.dead_cnt = 0 +@@ -386,37 +448,45 @@ def start(launch_file=''): + # start each process + for module in root.findall('module'): + module_name = get_param_value(module, 'name') +- process_name = get_param_value(module, 'process_name', 'mainboard_default_' + str(os.getpid())) ++ process_name = get_param_value( ++ module, 'process_name', 'mainboard_default_' + str(os.getpid())) + sched_name = get_param_value(module, 'sched_name', 'CYBER_DEFAULT') + process_type = get_param_value(module, 'type', 'library') ++ cpu_profile_file = get_param_value(module, 'cpuprofile') ++ mem_profile_file = get_param_value(module, 'memprofile') + exception_handler = get_param_value(module, 'exception_handler') + respawn_limit_txt = get_param_value(module, 'respawn_limit') + if respawn_limit_txt.isnumeric(): + respawn_limit = int(respawn_limit_txt) + else: + respawn_limit = g_default_respawn_limit ++ nice_val = get_param_value(module, 'nice', 0) + logger.info('Load module [%s] %s: [%s] [%s] conf, exception_handler: [%s], respawn_limit: [%d]', + module_name, process_type, process_name, sched_name, exception_handler, respawn_limit) + + if process_type == 'binary': + if len(process_name) == 0: +- logger.error('Start binary failed. Binary process_name is null.') ++ logger.error( ++ 'Start binary failed. Binary process_name is null.') + continue + pw = ProcessWrapper(process_name.split()[0], 0, [""], [], process_name, process_type, +- sched_name, [], exception_handler, respawn_limit) ++ sched_name, [], exception_handler, respawn_limit, nice=nice_val) + # Default is library + else: + dag_list = get_param_list(module, 'dag_conf') + if not dag_list: +- logger.error('module [%s] library dag conf is null.', module_name) ++ logger.error( ++ 'module [%s] library dag conf is null.', module_name) + continue + plugin_list = get_param_list(module, 'plugin') + extra_args_list = [] + extra_args = module.attrib.get('extra_args') + if extra_args is not None: + extra_args_list = extra_args.split() +- pw = ProcessWrapper(g_binary_name, 0, dag_list, plugin_list, process_name, process_type, +- sched_name, extra_args_list, exception_handler, respawn_limit) ++ pw = ProcessWrapper(g_binary_name, 0, dag_list, plugin_list, ++ process_name, process_type, sched_name, ++ extra_args_list, exception_handler, respawn_limit, ++ cpu_profile_file, mem_profile_file, nice_val) + result = pw.start() + if result != 0: + logger.error('Start manager [%s] failed. Stop all!', process_name) +diff --git a/cyber/tools/cyber_monitor/general_channel_message.cc b/cyber/tools/cyber_monitor/general_channel_message.cc +index db43ed3..bb26ef8 100644 +--- a/cyber/tools/cyber_monitor/general_channel_message.cc ++++ b/cyber/tools/cyber_monitor/general_channel_message.cc +@@ -21,6 +21,7 @@ + #include + #include + ++#include "cyber/common/global_data.h" + #include "cyber/record/record_message.h" + #include "cyber/tools/cyber_monitor/general_message.h" + #include "cyber/tools/cyber_monitor/screen.h" +@@ -121,9 +122,10 @@ GeneralChannelMessage* GeneralChannelMessage::OpenChannel( + } + + auto callback = +- [this]( ++ [this, channel_name]( + const std::shared_ptr& raw_msg) { + UpdateRawMessage(raw_msg); ++ UpdateChannelName(channel_name); + }; + + channel_reader_ = +diff --git a/cyber/tools/cyber_monitor/general_channel_message.h b/cyber/tools/cyber_monitor/general_channel_message.h +index e56f2d4..f16aa85 100644 +--- a/cyber/tools/cyber_monitor/general_channel_message.h ++++ b/cyber/tools/cyber_monitor/general_channel_message.h +@@ -151,6 +151,10 @@ class GeneralChannelMessage : public GeneralMessageBase { + channel_message_.reset(); + channel_message_ = raw_msg; + } ++ void UpdateChannelName(const std::string& channel_name) { ++ std::lock_guard _g(inner_lock_); ++ channel_name_ = channel_name; ++ } + + std::shared_ptr CopyMsgPtr(void) const { + decltype(channel_message_) channel_msg; +@@ -185,6 +189,7 @@ class GeneralChannelMessage : public GeneralMessageBase { + std::vector writers_; + + std::shared_ptr channel_message_; ++ std::string channel_name_; + std::shared_ptr> + channel_reader_; + mutable std::mutex inner_lock_; +diff --git a/cyber/tools/cyber_monitor/main.cc b/cyber/tools/cyber_monitor/main.cc +index f7777ea..79fb7db 100644 +--- a/cyber/tools/cyber_monitor/main.cc ++++ b/cyber/tools/cyber_monitor/main.cc +@@ -19,6 +19,7 @@ + + #include "cyber/init.h" + #include "cyber/service_discovery/topology_manager.h" ++#include "cyber/task/task.h" + #include "cyber/tools/cyber_monitor/cyber_topology_message.h" + #include "cyber/tools/cyber_monitor/general_channel_message.h" + #include "cyber/tools/cyber_monitor/screen.h" +@@ -82,8 +83,7 @@ int main(int argc, char *argv[]) { + case HELP: + printHelp(argv[0]); + return 0; +- default: { +- } ++ default: {} + } + + apollo::cyber::Init(argv[0]); +@@ -95,12 +95,18 @@ int main(int argc, char *argv[]) { + + auto topology_callback = + [&topology_msg](const apollo::cyber::proto::ChangeMsg &change_msg) { +- topology_msg.TopologyChanged(change_msg); ++ apollo::cyber::Async([&topology_msg, change_msg] { ++ topology_msg.TopologyChanged(change_msg); ++ }); + }; + + auto channel_manager = + apollo::cyber::service_discovery::TopologyManager::Instance() + ->channel_manager(); ++ if (channel_manager == nullptr) { ++ AERROR << "Cyber Service Discovery is not ready."; ++ return -1; ++ } + channel_manager->AddChangeListener(topology_callback); + + std::vector role_vec; +diff --git a/cyber/tools/cyber_performance/BUILD b/cyber/tools/cyber_performance/BUILD +new file mode 100644 +index 0000000..1e68ff3 +--- /dev/null ++++ b/cyber/tools/cyber_performance/BUILD +@@ -0,0 +1,13 @@ ++load("//tools/proto:proto.bzl", "apollo_py_binary") ++load("//tools:apollo_package.bzl", "apollo_package") ++ ++package( ++ default_visibility = ["//visibility:public"], ++) ++ ++apollo_py_binary( ++ name = "cyber_performance", ++ srcs = ["cyber_performance.py"], ++) ++ ++apollo_package() +\ No newline at end of file +diff --git a/cyber/tools/cyber_performance/cyber_performance.launch b/cyber/tools/cyber_performance/cyber_performance.launch +new file mode 100755 +index 0000000..2fe3b88 +--- /dev/null ++++ b/cyber/tools/cyber_performance/cyber_performance.launch +@@ -0,0 +1,11 @@ ++ ++ ++ cyber_performance ++ ++ binary ++ ++ cyber_performance ++ ++ respawn ++ ++ +\ No newline at end of file +diff --git a/cyber/tools/cyber_performance/cyber_performance.py b/cyber/tools/cyber_performance/cyber_performance.py +new file mode 100644 +index 0000000..d0f4a05 +--- /dev/null ++++ b/cyber/tools/cyber_performance/cyber_performance.py +@@ -0,0 +1,789 @@ ++#!/usr/bin/env python3 ++# **************************************************************************** ++# Copyright 2024 The Apollo Authors. All Rights Reserved. ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++# **************************************************************************** ++ ++import time ++import json ++import os ++import re ++import threading ++import platform ++import subprocess ++from queue import Queue ++from datetime import datetime ++from flask import Flask, jsonify, render_template_string ++from watchdog.observers import Observer ++from watchdog.events import FileSystemEventHandler ++from cyber.python.cyber_py3 import cyber ++ ++app = Flask(__name__) ++data_history = { ++ "time": Queue(maxsize = 20), ++ "data": {}, ++} ++today = datetime.now() ++data_lock = threading.Lock() ++if 'APOLLO_ENV_WORKROOT' in os.environ: ++ DIRECTORY_TO_WATCH = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "dumps") ++ PERFORMANCE_TO_WRITE = os.path.join(os.environ['APOLLO_ENV_WORKROOT'], "data") ++else: ++ DIRECTORY_TO_WATCH = os.path.join("/apollo", "dumps") ++ PERFORMANCE_TO_WRITE = os.path.join("/apollo", "data") ++if not os.path.exists(DIRECTORY_TO_WATCH): ++ os.mkdir(DIRECTORY_TO_WATCH) ++if not os.path.exists(PERFORMANCE_TO_WRITE): ++ os.mkdir(PERFORMANCE_TO_WRITE) ++dumps_fio = open( ++ os.path.join(PERFORMANCE_TO_WRITE, ++ "performance_dumps.{}.json".format(today.strftime("%m-%d-%Y"))), "a+") ++sample_times = 0 ++response = {} ++update_time = 5000 ++chasis_channle = "/apollo/canbus/chassis" ++iface_path = "/sys/class/net" ++autodrive = False ++machine = platform.machine() ++nethogs_buf = "" ++process_network_io = {} ++network_data_lock = threading.Lock() ++ ++sudo_prv = subprocess.run( ++ ['sudo', '-n', 'true'], stdout=None, stderr=None).returncode == 0 ++ ++remove_list = [] ++for i in os.listdir(DIRECTORY_TO_WATCH): ++ if i.startswith("performance_dumps"): ++ date_str = i.split(".")[1] ++ try: ++ file_save_date = datetime.strptime(date_str, "%m-%d-%Y") ++ except: ++ remove_list.append(os.path.join(DIRECTORY_TO_WATCH, i)) ++ continue ++ if (today - file_save_date).days > 30: ++ remove_list.append(os.path.join(DIRECTORY_TO_WATCH, i)) ++for i in remove_list: ++ os.remove(i) ++ ++cyber_instance = None ++debounce_period = 1 ++last_modified = {} ++ ++class CyberChannelecho(object): ++ ++ def __init__(self, channel_name): ++ cyber.init() ++ self.pattern = r"driving_mode:\s*(\w+)" ++ self.channel_name = channel_name ++ self.node = cyber.Node("listener_node_echo") ++ self.node.create_rawdata_reader(channel_name, self.callback) ++ ++ def callback(self, raw_data): ++ global autodrive ++ msgtype = cyber.ChannelUtils.get_msgtype(self.channel_name, 0).decode('utf-8') ++ text = cyber.ChannelUtils.get_debugstring_rawmsgdata(msgtype, raw_data).decode('utf-8') ++ match = re.search(self.pattern, text) ++ if match: ++ ret = match.group(1) ++ if ret == "COMPLETE_AUTO_DRIVE": ++ autodrive = True ++ else: ++ autodrive = False ++ ++def cyber_task(): ++ global cyber_instance ++ cyber_instance = CyberChannelecho(chasis_channle) ++ ++def watcher_run(): ++ global DIRECTORY_TO_WATCH ++ event_handler = Handler() ++ observer = Observer() ++ ++ observer.schedule(event_handler, DIRECTORY_TO_WATCH) ++ observer.start() ++ try: ++ while True: ++ time.sleep(5) ++ except KeyboardInterrupt: ++ observer.stop() ++ observer.join() ++ ++def gpu_memory_usage(pid): ++ gpu_mem_kernel_file = "/sys/kernel/debug/nvmap/iovmm/maps" ++ gpu_mem = 0 ++ ++ if pid == -1: ++ return gpu_mem ++ if machine == "aarch64": ++ total, processes = read_process_table(gpu_mem_kernel_file) ++ if total is not None: ++ for p in processes: ++ if pid == int(p[0]): ++ gpu_mem = int(p[3]) ++ break ++ else: ++ query_cmd = "nvidia-smi --query-compute-apps=pid,used_memory --format=csv,noheader,nounits" ++ p = subprocess.run(query_cmd, shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip().splitlines() ++ for line in stdout: ++ eles = [i.strip() for i in line.split(",")] ++ if len(eles) < 2: ++ break ++ if int(eles[0]) == pid: ++ gpu_mem = int(eles[1]) ++ break ++ return gpu_mem ++ ++def read_process_table(path_table): ++ """ ++ This method list all processes working with GPU ++ ++ ========== ============ ======== ============= ++ user process PID size ++ ========== ============ ======== ============= ++ user name process number dictionary ++ ========== ============ ======== ============= ++ ++ :return: list of all processes ++ :type spin: list ++ """ ++ if not os.path.exists(path_table): ++ return None, None ++ if not os.access(path_table, os.R_OK): ++ return None, None ++ MEM_TABLE_REG = re.compile(r'^(?P\w+)\s+(?P[^ ]+)\s+(?P\d+)\s+(?P\d+)(?P\w)\n') ++ TOT_TABLE_REG = re.compile(r'total\s+(?P\d+)(?P\w)') ++ ++ table = [] ++ total = {} ++ with open(path_table, "r") as fp: ++ for line in fp: ++ # Search line ++ match = re.search(MEM_TABLE_REG, line) ++ if match: ++ parsed_line = match.groupdict() ++ data = [ ++ parsed_line['PID'], ++ parsed_line['user'], ++ parsed_line['process'], ++ int(parsed_line['size']), ++ ] ++ table += [data] ++ continue ++ # Find total on table ++ match = re.search(TOT_TABLE_REG, line) ++ if match: ++ parsed_line = match.groupdict() ++ total = int(parsed_line['size']) ++ continue ++ # return total and table ++ return total, table ++ ++class Handler(FileSystemEventHandler): ++ @staticmethod ++ def on_any_event(event): ++ global data_history ++ global data_lock ++ global autodrive ++ global network_data_lock, process_network_io ++ ++ if event.is_directory: ++ return None ++ ++ elif event.event_type == 'created' or event.event_type == 'modified': ++ if not event.src_path.endswith(".system.data"): ++ return None ++ ++ current_time = time.time() ++ last_mod_time = last_modified.get(event.src_path, 0) ++ ++ if current_time - last_mod_time <= debounce_period: ++ return None ++ else: ++ last_modified[event.src_path] = current_time ++ ++ print(f'Event type: {event.event_type} path : {event.src_path}') ++ file_name = event.src_path.replace(DIRECTORY_TO_WATCH + "/", "") ++ process_name = file_name.replace(".system.data", "") ++ pid_file_name = event.src_path.replace(".system.data", ".data") ++ latency_file_name = event.src_path.replace(".system.data", ".latency.data") ++ while True: ++ with open(event.src_path, 'r') as f: ++ current_data = {} ++ current_data["autodrive"] = autodrive ++ contents = f.read().split("\n") ++ if len(contents) == 0: ++ continue ++ elif len(contents) == 1 and contents[0] == "": ++ continue ++ for line in contents: ++ if line == "": ++ continue ++ instance = line.strip().split(" : ") ++ if len(instance) == 1: ++ continue ++ ++ if instance[0].endswith("cpu_usage"): ++ current_data["BASIC - cpu_usage(%, single-core)"] = float(instance[1]) * 100 ++ elif instance[0].endswith("memory_resident"): ++ current_data["BASIC - memory(MB)"] = int(instance[1]) / 1024 / 1024 ++ elif instance[0].endswith("disk_read_bytes_second"): ++ current_data["BLOCK_DEVICE_IO - block_device_io_read(rkB/s)"] = int(instance[1]) / 1024 ++ elif instance[0].endswith("disk_write_bytes_second"): ++ current_data["BLOCK_DEVICE_IO - block_device_io_write(wkB/s)"] = int(instance[1]) / 1024 ++ else: ++ continue ++ break ++ pid = -1 ++ ++ with open(pid_file_name, "r") as pf: ++ contents = pf.readlines() ++ for line in contents: ++ if line == "": ++ continue ++ instance = line.strip().split(" : ") ++ if len(instance) == 1: ++ continue ++ if instance[0].endswith("_pid"): ++ pid = int(instance[1]) ++ break ++ gpu_mem = gpu_memory_usage(pid) ++ ++ with open(latency_file_name, "r") as lf: ++ contents = lf.readlines() ++ has_proc_info = False ++ for line in contents: ++ if "proc_latency :" in line: ++ instance = line.split(" : ") ++ latency_name = instance[0].replace("mainboard_", "") ++ latency_val = float((instance[1].strip())) / 1000 ++ else: ++ continue ++ has_proc_info = True ++ current_data[f"E2E_LATENCY - {latency_name}(ms)"] = latency_val ++ if not has_proc_info: ++ return ++ with network_data_lock: ++ if pid in process_network_io: ++ current_data["ETHERNET_DEVICE_IO - ethernet_device_io_write(wkB/s)"] = process_network_io[pid]["tx"] ++ current_data["ETHERNET_DEVICE_IO - ethernet_device_io_read(rkB/s)"] = process_network_io[pid]["rx"] ++ else: ++ current_data["ETHERNET_DEVICE_IO - ethernet_device_io_write(wkB/s)"] = 0 ++ current_data["ETHERNET_DEVICE_IO - ethernet_device_io_read(rkB/s)"] = 0 ++ ++ current_data["BASIC - gpu_memory(MB)"] = gpu_mem / 1024 ++ ++ with data_lock: ++ if process_name not in data_history["data"]: ++ data_history["data"][process_name] = {} ++ data_history["data"][process_name]["time"] = Queue(maxsize = 20) ++ ++ for key in current_data: ++ if key not in data_history["data"][process_name]: ++ data_history["data"][process_name][key] = Queue(maxsize = 20) ++ ++ time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") ++ if data_history["data"][process_name]["time"].full(): ++ data_history["data"][process_name]["time"].get() ++ data_history["data"][process_name]["time"].put(time_format) ++ ++ for key, value in current_data.items(): ++ if data_history["data"][process_name][key].full(): ++ data_history["data"][process_name][key].get() ++ data_history["data"][process_name][key].put(value) ++ ++ ++def sample_task(): ++ global data_history ++ global sample_times ++ global dumps_fio ++ global response ++ global autodrive ++ ++ p = subprocess.run( ++ "which tegrastats", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ ++ tegrastats = None ++ if p.returncode == 0: ++ tegrastats = p.stdout.decode("utf-8").strip() ++ ++ system_info = { ++ "system-cpu": Queue(maxsize = 20), ++ "system-memory": Queue(maxsize = 20), ++ "system-gpu": Queue(maxsize = 20), ++ "time": Queue(maxsize = 20), ++ "system-io-usage": Queue(maxsize = 20), ++ "autodrive": Queue(maxsize = 20), ++ "block-device-io" : {}, ++ "ethernet-device-io": {} ++ } ++ ++ while True: ++ sample_times = sample_times + 1 ++ system_cpu = None ++ system_memory = None ++ system_gpu = None ++ system_io_usage = None ++ if tegrastats is not None: ++ time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") ++ p = subprocess.run( ++ " ".join(["timeout", "2", tegrastats]), shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip() ++ ++ cpu_usage_pattern = re.compile(r'\bCPU \[(.*?)\]') ++ match_result = cpu_usage_pattern.findall(stdout) ++ if len(match_result) > 0: ++ usages = re.findall(r'(\d+)%@', match_result[0]) ++ system_cpu = 0 ++ for usage in usages: ++ system_cpu += float(usage) ++ system_cpu = system_cpu / len(usages) ++ ++ gpu_usage_pattern = re.compile(r'GR3D_FREQ (\d+)%') ++ match_result = gpu_usage_pattern.findall(stdout) ++ if len(match_result) > 0: ++ system_gpu = float(match_result[0]) ++ ++ p = subprocess.run( ++ "vmstat 1 2 | awk '{print $16}' | tail -n 1", shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip() ++ system_io_usage = float(stdout) ++ else: ++ p = subprocess.run( ++ "top -bn2 | grep Cpu | awk '{print $8}' | tail -n 1", shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip() ++ time_format = datetime.now().strftime("%m/%d/%Y, %H:%M:%S") ++ system_cpu = 100 - float(stdout) ++ ++ system_gpu = 0 ++ ++ p = subprocess.run( ++ "vmstat | awk '{print $16}' | tail -n 1", shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip() ++ system_io_usage = float(stdout) ++ p = subprocess.run("cat /proc/meminfo", ++ shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip().splitlines() ++ meminfo = {} ++ for i in stdout: ++ k, v = i.split(":")[0].strip().lower(), i.split(":")[1].strip() ++ value = round(int(v.strip().split(' ')[0]) / 1024, 2) ++ meminfo[k] = value ++ ++ total = meminfo["memtotal"] ++ buffers = meminfo["buffers"] ++ cached = meminfo["cached"] ++ sreclaimable = meminfo["sreclaimable"] ++ free = meminfo["memfree"] ++ shm = meminfo["shmem"] ++ if "memavailable" not in meminfo: ++ used_without_shm = total - buffers - cached - sreclaimable ++ used = used_without_shm + shm ++ else: ++ available = meminfo["memavailable"] ++ used = total - available ++ system_memory = used ++ ++ if system_cpu is not None \ ++ and system_gpu is not None \ ++ and system_memory is not None \ ++ and system_io_usage is not None: ++ if system_info["time"].full(): ++ system_info["time"].get() ++ system_info["time"].put(time_format) ++ if system_info["system-cpu"].full(): ++ system_info["system-cpu"].get() ++ system_info["system-cpu"].put(system_cpu) ++ if system_info["system-gpu"].full(): ++ system_info["system-gpu"].get() ++ system_info["system-gpu"].put(system_gpu) ++ if system_info["system-memory"].full(): ++ system_info["system-memory"].get() ++ system_info["system-memory"].put(system_memory) ++ if system_info["system-io-usage"].full(): ++ system_info["system-io-usage"].get() ++ system_info["system-io-usage"].put(system_io_usage) ++ if system_info["autodrive"].full(): ++ system_info["autodrive"].get() ++ system_info["autodrive"].put(autodrive) ++ ++ p = subprocess.run( ++ "lsblk -o NAME,TYPE,SIZE,TRAN --json", shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip() ++ blk_devices = json.loads(stdout) ++ blk_monitor_devices = [] ++ try: ++ for dev in blk_devices["blockdevices"]: ++ if dev["type"] != "disk": ++ continue ++ ++ if dev["tran"] == "nvme" or dev["tran"] == "sata": ++ blk_monitor_devices.append(dev["name"]) ++ elif dev["tran"] == "null" and "children" in dev: ++ blk_monitor_devices.append(dev["name"]) ++ blk_monitor_devices = list(filter( ++ lambda x: os.path.exists(f"/dev/{x}"), blk_monitor_devices)) ++ except Exception as ex: ++ blk_monitor_devices = [] ++ ++ if len(blk_monitor_devices) > 0: ++ for dev in blk_monitor_devices: ++ if dev not in system_info["block-device-io"]: ++ system_info["block-device-io"][dev] = { ++ "rkB/s": Queue(maxsize = 20), ++ "wkB/s": Queue(maxsize = 20), ++ "r/s": Queue(maxsize = 20), ++ "w/s": Queue(maxsize = 20), ++ "r_await": Queue(maxsize = 20), ++ "w_await": Queue(maxsize = 20), ++ "aqu-sz": Queue(maxsize = 20) ++ } ++ ++ query_devices = " ".join(blk_monitor_devices) ++ stat_length = len(blk_monitor_devices) + 1 ++ query_cmd = f"iostat -xk 1 2 {query_devices} | grep -v '^$' | tail -n {stat_length}" ++ ++ p = subprocess.run(query_cmd, shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip().splitlines() ++ ++ monitor_items = list(filter(lambda x: x != "", stdout[0].split(" "))) ++ for i in range(1, len(stdout)): ++ dev_res = list(filter(lambda x: x != "", stdout[i].split(" "))) ++ dev_name = dev_res[0] ++ for j in range(1, len(monitor_items)): ++ if monitor_items[j] not in system_info["block-device-io"][dev_name]: ++ continue ++ monitor_item = monitor_items[j] ++ if system_info["block-device-io"][dev_name][monitor_item].full(): ++ system_info["block-device-io"][dev_name][monitor_item].get() ++ system_info["block-device-io"][dev_name][monitor_item].put(dev_res[j]) ++ ++ eth_devices = [] ++ for i in os.listdir(iface_path): ++ if os.path.exists(os.path.join(iface_path, i, "device", "driver")): ++ eth_devices.append(i) ++ if len(eth_devices) > 0: ++ for dev in eth_devices: ++ if dev not in system_info["ethernet-device-io"]: ++ system_info["ethernet-device-io"][dev] = { ++ "rxkB/s": Queue(maxsize = 20), ++ "txkB/s": Queue(maxsize = 20), ++ "%ifutil": Queue(maxsize = 20) ++ } ++ query_cmd = "sar -n DEV 1 1 | grep --color=never Average" ++ p = subprocess.run(query_cmd, shell=True, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ stdout = p.stdout.decode("utf-8").strip().splitlines() ++ ++ monitor_items = list(filter(lambda x: x != "", stdout[0].split(" "))) ++ for i in range(1, len(stdout)): ++ dev_res = list(filter(lambda x: x != "", stdout[i].split(" "))) ++ dev_name = dev_res[1] ++ if dev_name not in system_info["ethernet-device-io"]: ++ continue ++ for j in range(2, len(monitor_items)): ++ if monitor_items[j] not in system_info["ethernet-device-io"][dev_name]: ++ continue ++ monitor_item = monitor_items[j] ++ if system_info["ethernet-device-io"][dev_name][monitor_item].full(): ++ system_info["ethernet-device-io"][dev_name][monitor_item].get() ++ system_info["ethernet-device-io"][dev_name][monitor_item].put(dev_res[j]) ++ ++ # system metrics ++ response = { ++ "data": {"system": {}} ++ } ++ ++ # status ++ response["data"]["system"]["time"] = list(system_info["time"].queue) ++ response["data"]["system"]["autodrive"] = list(system_info["autodrive"].queue) ++ ++ # basic performance metrics ++ response["data"]["system"]["BASIC - system - cpu_usage(%, all-core)"] = list(system_info["system-cpu"].queue) ++ response["data"]["system"]["BASIC - system - gpu_usage(%)"] = list(system_info["system-gpu"].queue) ++ response["data"]["system"]["BASIC - system - memory(MB)"] = list(system_info["system-memory"].queue) ++ ++ # io metrics ++ response["data"]["system"]["BLOCK_DEVICE_IO - system - io_wait_usage(%)"] = list(system_info["system-io-usage"].queue) ++ for dev in system_info["block-device-io"]: ++ for io_metric in system_info["block-device-io"][dev]: ++ response["data"]["system"][f"BLOCK_DEVICE_IO - {dev} - {io_metric}"] = \ ++ list(system_info["block-device-io"][dev][io_metric].queue) ++ for dev in system_info["ethernet-device-io"]: ++ for io_metric in system_info["ethernet-device-io"][dev]: ++ response["data"]["system"][f"ETHERNET_DEVICE_IO - {dev} - {io_metric}"] = \ ++ list(system_info["ethernet-device-io"][dev][io_metric].queue) ++ ++ # process metrics ++ for p in data_history["data"]: ++ response["data"][p] = {} ++ for monitor_instance in data_history["data"][p]: ++ response["data"][p][monitor_instance] = list( ++ data_history["data"][p][monitor_instance].queue) ++ ++ if sample_times >= 20: ++ dumps_fio.write(json.dumps(response)) ++ dumps_fio.write('\n') ++ dumps_fio.flush() ++ sample_times = 0 ++ ++ time.sleep(update_time / 1000) ++@app.route('/get_data', methods=['GET']) ++def get_data(): ++ global response ++ ++ return jsonify(response) ++ ++@app.route('/') ++def index(): ++ return render_template_string(''' ++ ++ ++ ++ ++ ++ cyber_performance ++ ++ ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ''') ++ ++if __name__ == '__main__': ++ system_sample_thread = threading.Thread(target=sample_task) ++ system_sample_thread.daemon = True ++ system_sample_thread.start() ++ ++ watchdog_thread = threading.Thread(target=watcher_run) ++ watchdog_thread.daemon = True ++ watchdog_thread.start() ++ ++ if sudo_prv: ++ nethogs_process = subprocess.Popen( ++ ['sudo', 'nethogs', '-t'], stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE, bufsize=1, universal_newlines=True) ++ ++ def parse_nethogs_output(): ++ global nethogs_buf, process_network_io, network_data_lock ++ for line in iter(nethogs_process.stdout.readline, ''): ++ if line.startswith("Refreshing:"): ++ with network_data_lock: ++ process_network_io = {} ++ nethogs_buf_list = list(filter(lambda x: x!= "", nethogs_buf.split("\n"))) ++ for i in nethogs_buf_list: ++ raw_line = list(filter(lambda x: x != "", i.split(" "))) ++ raw_process_info = raw_line[0].split("\t") ++ process_info = raw_process_info[0].split("/") ++ if len(process_info) < 3 or int(process_info[-2]) == 0: ++ continue ++ process_network_io[int(process_info[-2])] = {} ++ process_network_io[int(process_info[-2])]["rx"] = float(raw_process_info[2]) ++ process_network_io[int(process_info[-2])]["tx"] = float(raw_process_info[1]) ++ nethogs_buf = "" ++ else: ++ nethogs_buf = nethogs_buf + line ++ ++ network_sample_thread = threading.Thread(target=parse_nethogs_output) ++ network_sample_thread.daemon = True ++ network_sample_thread.start() ++ ++ cyber_task() ++ ++ app.run(host="0.0.0.0", threaded=True) ++ +diff --git a/cyber/tools/cyber_recorder/BUILD b/cyber/tools/cyber_recorder/BUILD +index a53af19..14c1e0f 100644 +--- a/cyber/tools/cyber_recorder/BUILD ++++ b/cyber/tools/cyber_recorder/BUILD +@@ -8,7 +8,11 @@ apollo_cc_binary( + srcs = [ + "main.cc", + ], +- linkopts = ["-pthread"], ++ linkopts = [ ++ "-pthread", ++ "-lprofiler", ++ "-ltcmalloc", ++ ], + deps = [ + ":recorder", + "//cyber", +@@ -34,7 +38,7 @@ apollo_cc_library( + "//cyber", + "//cyber/common:cyber_common", + "//cyber/proto:record_cc_proto", +- "@fastrtps", ++ "@fastdds", + ], + ) + +diff --git a/cyber/tools/cyber_recorder/main.cc b/cyber/tools/cyber_recorder/main.cc +index b43396b..1136b98 100644 +--- a/cyber/tools/cyber_recorder/main.cc ++++ b/cyber/tools/cyber_recorder/main.cc +@@ -15,12 +15,15 @@ + *****************************************************************************/ + + #include ++#include + #include ++#include + #include + #include + #include + #include + ++#include "cyber/common/environment.h" + #include "cyber/common/file.h" + #include "cyber/common/time_conversion.h" + #include "cyber/init.h" +@@ -30,6 +33,11 @@ + #include "cyber/tools/cyber_recorder/recoverer.h" + #include "cyber/tools/cyber_recorder/spliter.h" + ++#include "gflags/gflags.h" ++#include "gperftools/heap-profiler.h" ++#include "gperftools/malloc_extension.h" ++#include "gperftools/profiler.h" ++ + using apollo::cyber::common::GetFileName; + using apollo::cyber::common::StringToUnixSeconds; + using apollo::cyber::common::UnixSecondsToString; +@@ -42,7 +50,7 @@ using apollo::cyber::record::Recoverer; + using apollo::cyber::record::Spliter; + + const char INFO_OPTIONS[] = "h"; +-const char RECORD_OPTIONS[] = "o:ac:k:i:m:h"; ++const char RECORD_OPTIONS[] = "o:ac:k:i:m:hCH"; + const char PLAY_OPTIONS[] = "f:ac:k:lr:b:e:s:d:p:h"; + const char SPLIT_OPTIONS[] = "f:o:c:k:b:e:h"; + const char RECOVER_OPTIONS[] = "f:o:h"; +@@ -148,6 +156,13 @@ void DisplayUsage(const std::string& binary, const std::string& command, + case 'h': + std::cout << "\t-h, --help\t\t\t\tshow help message" << std::endl; + break; ++ case 'H': ++ std::cout << "\t-H, --heap-profule\t\t\t\tprofile heap info" ++ << std::endl; ++ break; ++ case 'C': ++ std::cout << "\t-C, --cpu-profule\t\t\t\tprofile cpu info" << std::endl; ++ break; + case ':': + break; + default: +@@ -170,7 +185,7 @@ int main(int argc, char** argv) { + } + + int long_index = 0; +- const std::string short_opts = "f:c:k:o:alr:b:e:s:d:p:i:m:h"; ++ const std::string short_opts = "f:c:k:o:alr:b:e:s:d:p:i:m:hCH"; + static const struct option long_opts[] = { + {"files", required_argument, nullptr, 'f'}, + {"white-channel", required_argument, nullptr, 'c'}, +@@ -186,12 +201,16 @@ int main(int argc, char** argv) { + {"preload", required_argument, nullptr, 'p'}, + {"segment-interval", required_argument, nullptr, 'i'}, + {"segment-size", required_argument, nullptr, 'm'}, +- {"help", no_argument, nullptr, 'h'}}; ++ {"help", no_argument, nullptr, 'h'}, ++ {"cpu-profile", no_argument, nullptr, 'C'}, ++ {"heap-profule", no_argument, nullptr, 'H'}}; + + std::vector opt_file_vec; + std::vector opt_output_vec; + std::vector opt_white_channels; + std::vector opt_black_channels; ++ static bool enable_cpu_profile = false; ++ static bool enable_heap_profile = false; + bool opt_all = false; + bool opt_loop = false; + float opt_rate = 1.0f; +@@ -209,11 +228,37 @@ int main(int argc, char** argv) { + break; + } + switch (opt) { ++ case 'C': ++ enable_cpu_profile = true; ++ break; ++ case 'H': ++ enable_heap_profile = true; ++ break; + case 'f': +- opt_file_vec.emplace_back(std::string(optarg)); ++ if (!apollo::cyber::common::PathIsAbsolute(std::string(optarg))) { ++ auto opt_file_abs_path = ++ apollo::cyber::common::GetEnv("PWD") + "/" + std::string(optarg); ++ if (apollo::cyber::common::PathExists(opt_file_abs_path)) { ++ opt_file_vec.emplace_back(opt_file_abs_path); ++ } else { ++ opt_file_vec.emplace_back(std::string(optarg)); ++ } ++ } else { ++ opt_file_vec.emplace_back(std::string(optarg)); ++ } + for (int i = optind; i < argc; i++) { + if (*argv[i] != '-') { +- opt_file_vec.emplace_back(std::string(argv[i])); ++ if (!apollo::cyber::common::PathIsAbsolute(std::string(argv[i]))) { ++ auto opt_file_abs_path = apollo::cyber::common::GetEnv("PWD") + ++ "/" + std::string(argv[i]); ++ if (apollo::cyber::common::PathExists(opt_file_abs_path)) { ++ opt_file_vec.emplace_back(opt_file_abs_path); ++ } else { ++ opt_file_vec.emplace_back(std::string(argv[i])); ++ } ++ } else { ++ opt_file_vec.emplace_back(std::string(argv[i])); ++ } + } else { + break; + } +@@ -240,7 +285,13 @@ int main(int argc, char** argv) { + } + break; + case 'o': +- opt_output_vec.push_back(std::string(optarg)); ++ if (!apollo::cyber::common::PathIsAbsolute(std::string(optarg))) { ++ auto opt_output_file_abs_path = ++ apollo::cyber::common::GetEnv("PWD") + "/" + std::string(optarg); ++ opt_output_vec.push_back(opt_output_file_abs_path); ++ } else { ++ opt_output_vec.push_back(std::string(optarg)); ++ } + break; + case 'a': + opt_all = true; +@@ -360,6 +411,13 @@ int main(int argc, char** argv) { + std::cout << "usage: cyber_recorder info file" << std::endl; + return -1; + } ++ if (!apollo::cyber::common::PathIsAbsolute(file_path)) { ++ auto file_path_abs = ++ apollo::cyber::common::GetEnv("PWD") + "/" + std::string(file_path); ++ if (std::filesystem::exists(file_path_abs)) { ++ file_path = file_path_abs; ++ } ++ } + ::apollo::cyber::Init(argv[0]); + Info info; + bool info_result = info.Display(file_path); +@@ -388,7 +446,7 @@ int main(int argc, char** argv) { + std::cout << "MUST specify file option (-f)." << std::endl; + return -1; + } +- ::apollo::cyber::Init(argv[0]); ++ ::apollo::cyber::Init(argv[0], "cyber_recorder"); + PlayParam play_param; + play_param.is_play_all_channels = opt_all || opt_white_channels.empty(); + play_param.is_loop_playback = opt_loop; +@@ -419,6 +477,7 @@ int main(int argc, char** argv) { + } + if (opt_output_vec.empty()) { + std::string default_output_file = ++ apollo::cyber::common::GetEnv("PWD") + "/" + + UnixSecondsToString(time(nullptr), "%Y%m%d%H%M%S") + ".record"; + opt_output_vec.push_back(default_output_file); + } +@@ -426,6 +485,35 @@ int main(int argc, char** argv) { + auto recorder = std::make_shared(opt_output_vec[0], opt_all, + opt_white_channels, + opt_black_channels, opt_header); ++ std::signal(SIGTERM, [](int sig) { ++ apollo::cyber::OnShutdown(sig); ++ if (enable_cpu_profile) { ++ ProfilerStop(); ++ } ++ if (enable_heap_profile) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++ }); ++ ++ std::signal(SIGINT, [](int sig) { ++ apollo::cyber::OnShutdown(sig); ++ if (enable_cpu_profile) { ++ ProfilerStop(); ++ } ++ if (enable_heap_profile) { ++ HeapProfilerDump("Befor shutdown"); ++ HeapProfilerStop(); ++ } ++ }); ++ ++ auto base_name = std::string(argv[0]) + std::string(".prof"); ++ if (enable_cpu_profile) { ++ ProfilerStart(base_name.c_str()); ++ } ++ if (enable_heap_profile) { ++ HeapProfilerStart(base_name.c_str()); ++ } + bool record_result = recorder->Start(); + if (record_result) { + while (!::apollo::cyber::IsShutdown()) { +diff --git a/cyber/transport/BUILD b/cyber/transport/BUILD +index eb81b20..1e920a0 100644 +--- a/cyber/transport/BUILD ++++ b/cyber/transport/BUILD +@@ -1,53 +1,105 @@ + load("//tools:cpplint.bzl", "cpplint") +-load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_package", "apollo_cc_test") ++load("//tools:apollo_package.bzl", "apollo_cc_library", "apollo_cc_test", "apollo_package") + + package(default_visibility = ["//visibility:public"]) + + apollo_cc_library( + name = "cyber_transport", + srcs = [ +- 'transport.cc', 'shm/segment.cc', 'shm/condition_notifier.cc', +- 'shm/segment_factory.cc', 'shm/posix_segment.cc', 'shm/state.cc', +- 'shm/multicast_notifier.cc', 'shm/block.cc', 'shm/shm_conf.cc', +- 'shm/xsi_segment.cc', 'shm/readable_info.cc', 'shm/notifier_factory.cc', +- 'qos/qos_profile_conf.cc', 'common/identity.cc', 'common/endpoint.cc', +- 'dispatcher/intra_dispatcher.cc', 'dispatcher/shm_dispatcher.cc', +- 'dispatcher/rtps_dispatcher.cc', 'dispatcher/dispatcher.cc', +- 'message/message_info.cc', 'rtps/participant.cc', 'rtps/attributes_filler.cc', +- 'rtps/sub_listener.cc', 'rtps/underlay_message_type.cc', +- 'rtps/underlay_message.cc' ++ "common/endpoint.cc", ++ "common/identity.cc", ++ "dispatcher/dispatcher.cc", ++ "dispatcher/intra_dispatcher.cc", ++ "dispatcher/rtps_dispatcher.cc", ++ "dispatcher/subscriber_listener.cc", ++ "dispatcher/shm_dispatcher.cc", ++ "message/message_info.cc", ++ "qos/qos_profile_conf.cc", ++ "qos/qos_filler.cc", ++ "rtps/attributes_filler.cc", ++ "rtps/participant.cc", ++ "rtps/publisher.cc", ++ "rtps/subscriber.cc", ++ "rtps/underlay_message.cc", ++ "rtps/underlay_message_type.cc", ++ "shm/arena_address_allocator.cc", ++ "shm/block.cc", ++ "shm/condition_notifier.cc", ++ "shm/multicast_notifier.cc", ++ "shm/notifier_factory.cc", ++ "shm/posix_segment.cc", ++ "shm/protobuf_arena_manager.cc", ++ "shm/readable_info.cc", ++ "shm/segment.cc", ++ "shm/segment_factory.cc", ++ "shm/shm_conf.cc", ++ "shm/state.cc", ++ "shm/xsi_segment.cc", ++ "transport.cc", + ], + hdrs = [ +- 'transport.h', 'shm/state.h', 'shm/xsi_segment.h', +- 'shm/notifier_factory.h', 'shm/block.h', 'shm/shm_conf.h', +- 'shm/readable_info.h', 'shm/posix_segment.h', 'shm/segment_factory.h', +- 'shm/multicast_notifier.h', 'shm/segment.h', 'shm/notifier_base.h', +- 'shm/condition_notifier.h', 'qos/qos_profile_conf.h', 'common/identity.h', +- 'common/endpoint.h', 'receiver/hybrid_receiver.h', 'receiver/shm_receiver.h', +- 'receiver/receiver.h', 'receiver/intra_receiver.h', 'receiver/rtps_receiver.h', +- 'transmitter/rtps_transmitter.h', 'transmitter/transmitter.h', +- 'transmitter/shm_transmitter.h', 'transmitter/hybrid_transmitter.h', +- 'transmitter/intra_transmitter.h', 'dispatcher/dispatcher.h', +- 'dispatcher/intra_dispatcher.h', 'dispatcher/rtps_dispatcher.h', +- 'dispatcher/shm_dispatcher.h', 'message/history.h', 'message/listener_handler.h', +- 'message/history_attributes.h', 'message/message_info.h', +- 'rtps/attributes_filler.h', 'rtps/underlay_message.h', 'rtps/participant.h', +- 'rtps/sub_listener.h', 'rtps/underlay_message_type.h' ++ "common/endpoint.h", ++ "common/identity.h", ++ "common/common_type.h", ++ "dispatcher/dispatcher.h", ++ "dispatcher/intra_dispatcher.h", ++ "dispatcher/rtps_dispatcher.h", ++ "dispatcher/shm_dispatcher.h", ++ "dispatcher/subscriber_listener.h", ++ "message/history.h", ++ "message/history_attributes.h", ++ "message/listener_handler.h", ++ "message/message_info.h", ++ "qos/qos_profile_conf.h", ++ "qos/qos_filler.h", ++ "receiver/hybrid_receiver.h", ++ "receiver/intra_receiver.h", ++ "receiver/receiver.h", ++ "receiver/rtps_receiver.h", ++ "receiver/shm_receiver.h", ++ "rtps/attributes_filler.h", ++ "rtps/participant.h", ++ "rtps/subscriber.h", ++ "rtps/publisher.h", ++ "rtps/underlay_message.h", ++ "rtps/underlay_message_type.h", ++ "shm/arena_address_allocator.h", ++ "shm/block.h", ++ "shm/condition_notifier.h", ++ "shm/multicast_notifier.h", ++ "shm/notifier_base.h", ++ "shm/notifier_factory.h", ++ "shm/posix_segment.h", ++ "shm/protobuf_arena_manager.h", ++ "shm/readable_info.h", ++ "shm/segment.h", ++ "shm/segment_factory.h", ++ "shm/shm_conf.h", ++ "shm/state.h", ++ "shm/xsi_segment.h", ++ "transmitter/hybrid_transmitter.h", ++ "transmitter/intra_transmitter.h", ++ "transmitter/rtps_transmitter.h", ++ "transmitter/shm_transmitter.h", ++ "transmitter/transmitter.h", ++ "transport.h", + ], + linkopts = ["-lrt"], + deps = [ +- "@fastrtps", +- "@uuid", +- "//cyber/service_discovery:cyber_service_discovery_role", +- "//cyber/task:cyber_task", ++ "//cyber/base:cyber_base", + "//cyber/common:cyber_common", +- "//cyber/proto:role_attributes_cc_proto", ++ "//cyber/event:cyber_event", + "//cyber/message:cyber_message", + "//cyber/proto:proto_desc_cc_proto", +- "//cyber/scheduler:cyber_scheduler", + "//cyber/proto:qos_profile_cc_proto", +- "//cyber/base:cyber_base", +- "//cyber/event:cyber_event", ++ "//cyber/proto:role_attributes_cc_proto", ++ "//cyber/scheduler:cyber_scheduler", ++ "//cyber/service_discovery:cyber_service_discovery_role", ++ "//cyber/service_discovery:subscriber_listener", ++ "//cyber/statistics:apollo_statistics", ++ "//cyber/task:cyber_task", ++ "@fastdds", ++ "@uuid", + ], + ) + +@@ -55,12 +107,12 @@ apollo_cc_test( + name = "condition_notifier_test", + size = "small", + srcs = ["shm/condition_notifier_test.cc"], ++ linkstatic = True, + tags = ["exclusive"], + deps = [ + "//cyber", + "@com_google_googletest//:gtest_main", + ], +- linkstatic = True, + ) + + apollo_cc_test( +@@ -70,7 +122,7 @@ apollo_cc_test( + deps = [ + "//cyber", + "@com_google_googletest//:gtest_main", +- "@fastrtps", ++ "@fastdds", + ], + ) + +@@ -78,22 +130,22 @@ apollo_cc_test( + name = "message_info_test", + size = "small", + srcs = ["message/message_info_test.cc"], ++ linkstatic = True, + deps = [ + "//cyber", + "@com_google_googletest//:gtest_main", + ], +- linkstatic = True, + ) + + apollo_cc_test( + name = "message_test", + size = "small", + srcs = ["message/message_test.cc"], ++ linkstatic = True, + deps = [ + "//cyber", + "@com_google_googletest//:gtest_main", + ], +- linkstatic = True, + ) + + apollo_cc_test( +@@ -172,4 +224,5 @@ apollo_cc_test( + ) + + apollo_package() ++ + cpplint() +diff --git a/cyber/transport/common/common_type.h b/cyber/transport/common/common_type.h +new file mode 100644 +index 0000000..b60365c +--- /dev/null ++++ b/cyber/transport/common/common_type.h +@@ -0,0 +1,36 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_TRANSPORT_RTPS_COMMON_TYPE_H ++#define CYBER_TRANSPORT_RTPS_COMMON_TYPE_H ++ ++#include ++#include ++#include ++ ++#include "cyber/transport/message/message_info.h" ++namespace apollo { ++namespace cyber { ++namespace transport { ++namespace rtps { ++using subsciber_callback = ++ std::function& msg_str, ++ uint64_t channel_id, const MessageInfo& msg_info)>; ++} // namespace rtps ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_TRANSPORT_RTPS_COMMON_TYPE_H +diff --git a/cyber/transport/dispatcher/dispatcher.h b/cyber/transport/dispatcher/dispatcher.h +index e37c366..0ea54ef 100644 +--- a/cyber/transport/dispatcher/dispatcher.h ++++ b/cyber/transport/dispatcher/dispatcher.h +@@ -25,11 +25,12 @@ + #include + #include + ++#include "cyber/proto/role_attributes.pb.h" ++ + #include "cyber/base/atomic_hash_map.h" + #include "cyber/base/atomic_rw_lock.h" + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" +-#include "cyber/proto/role_attributes.pb.h" + #include "cyber/transport/message/listener_handler.h" + #include "cyber/transport/message/message_info.h" + +diff --git a/cyber/transport/dispatcher/intra_dispatcher.h b/cyber/transport/dispatcher/intra_dispatcher.h +index 37bc046..82a40b0 100644 +--- a/cyber/transport/dispatcher/intra_dispatcher.h ++++ b/cyber/transport/dispatcher/intra_dispatcher.h +@@ -29,6 +29,8 @@ + #include "cyber/common/macros.h" + #include "cyber/message/message_traits.h" + #include "cyber/message/raw_message.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/time/time.h" + #include "cyber/transport/dispatcher/dispatcher.h" + + namespace apollo { +@@ -357,9 +359,12 @@ void IntraDispatcher::AddListener(const RoleAttributes& self_attr, + + auto handler = GetHandler(self_attr.channel_id()); + if (handler && created) { +- auto listener_wrapper = [this, self_id, channel_id, message_type]( ++ auto listener_wrapper = ++ [this, self_id, channel_id, message_type, self_attr]( + const std::shared_ptr& message, + const MessageInfo& message_info) { ++ auto recv_time = Time::Now().ToMicrosecond(); ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); + this->chain_->Run(self_id, channel_id, message_type, message, + message_info); + }; +@@ -385,9 +390,12 @@ void IntraDispatcher::AddListener(const RoleAttributes& self_attr, + + auto handler = GetHandler(self_attr.channel_id()); + if (handler && created) { +- auto listener_wrapper = [this, self_id, oppo_id, channel_id, message_type]( ++ auto listener_wrapper = ++ [this, self_id, oppo_id, channel_id, message_type, self_attr]( + const std::shared_ptr& message, + const MessageInfo& message_info) { ++ auto recv_time = Time::Now().ToMicrosecond(); ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); + this->chain_->Run(self_id, oppo_id, channel_id, message_type, + message, message_info); + }; +diff --git a/cyber/transport/dispatcher/rtps_dispatcher.cc b/cyber/transport/dispatcher/rtps_dispatcher.cc +index 7e7da27..f2f494e 100644 +--- a/cyber/transport/dispatcher/rtps_dispatcher.cc ++++ b/cyber/transport/dispatcher/rtps_dispatcher.cc +@@ -16,6 +16,11 @@ + + #include "cyber/transport/dispatcher/rtps_dispatcher.h" + ++#include "cyber/common/log.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/transport/common/endpoint.h" ++#include "cyber/transport/dispatcher/dispatcher.h" ++ + namespace apollo { + namespace cyber { + namespace transport { +@@ -32,7 +37,7 @@ void RtpsDispatcher::Shutdown() { + { + std::lock_guard lock(subs_mutex_); + for (auto& item : subs_) { +- item.second.sub = nullptr; ++ item.second = nullptr; + } + } + +@@ -47,25 +52,27 @@ void RtpsDispatcher::AddSubscriber(const RoleAttributes& self_attr) { + + uint64_t channel_id = self_attr.channel_id(); + std::lock_guard lock(subs_mutex_); ++ // subscriber exsit + if (subs_.count(channel_id) > 0) { + return; + } + +- Subscriber new_sub; +- eprosima::fastrtps::SubscriberAttributes sub_attr; ++ auto listener_adapter = ++ [this, self_attr](const std::shared_ptr& msg_str, ++ uint64_t channel_id, const MessageInfo& msg_info) { ++ statistics::Statistics::Instance()->AddRecvCount(self_attr, ++ msg_info.seq_num()); ++ statistics::Statistics::Instance()->SetTotalMsgsStatus( ++ self_attr, msg_info.seq_num()); ++ this->OnMessage(channel_id, msg_str, msg_info); ++ }; ++ + auto& qos = self_attr.qos_profile(); +- RETURN_IF(!AttributesFiller::FillInSubAttr(self_attr.channel_name(), qos, +- &sub_attr)); +- +- new_sub.sub_listener = std::make_shared( +- std::bind(&RtpsDispatcher::OnMessage, this, std::placeholders::_1, +- std::placeholders::_2, std::placeholders::_3)); +- +- new_sub.sub = eprosima::fastrtps::Domain::createSubscriber( +- participant_->fastrtps_participant(), sub_attr, +- new_sub.sub_listener.get()); +- RETURN_IF_NULL(new_sub.sub); +- subs_[channel_id] = new_sub; ++ auto subscriber_ptr = participant_->CreateSubscriber(self_attr.channel_name(), ++ qos, listener_adapter); ++ RETURN_IF_NULL(subscriber_ptr); ++ ++ subs_[channel_id] = subscriber_ptr; + } + + void RtpsDispatcher::OnMessage(uint64_t channel_id, +diff --git a/cyber/transport/dispatcher/rtps_dispatcher.h b/cyber/transport/dispatcher/rtps_dispatcher.h +index 656fea2..e73d571 100644 +--- a/cyber/transport/dispatcher/rtps_dispatcher.h ++++ b/cyber/transport/dispatcher/rtps_dispatcher.h +@@ -17,6 +17,7 @@ + #ifndef CYBER_TRANSPORT_DISPATCHER_RTPS_DISPATCHER_H_ + #define CYBER_TRANSPORT_DISPATCHER_RTPS_DISPATCHER_H_ + ++#include + #include + #include + #include +@@ -26,25 +27,25 @@ + #include "cyber/common/log.h" + #include "cyber/common/macros.h" + #include "cyber/message/message_traits.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/time/time.h" + #include "cyber/transport/dispatcher/dispatcher.h" ++#include "cyber/transport/dispatcher/subscriber_listener.h" ++#include "cyber/transport/qos/qos_filler.h" + #include "cyber/transport/rtps/attributes_filler.h" + #include "cyber/transport/rtps/participant.h" +-#include "cyber/transport/rtps/sub_listener.h" ++#include "cyber/transport/rtps/subscriber.h" + + namespace apollo { + namespace cyber { + namespace transport { + +-struct Subscriber { +- Subscriber() : sub(nullptr), sub_listener(nullptr) {} +- +- eprosima::fastrtps::Subscriber* sub; +- SubListenerPtr sub_listener; +-}; +- + class RtpsDispatcher; + using RtpsDispatcherPtr = RtpsDispatcher*; + ++using ParticipantPtr = ++ std::shared_ptr; ++ + class RtpsDispatcher : public Dispatcher { + public: + virtual ~RtpsDispatcher(); +@@ -60,7 +61,7 @@ class RtpsDispatcher : public Dispatcher { + const RoleAttributes& opposite_attr, + const MessageListener& listener); + +- void set_participant(const ParticipantPtr& participant) { ++ void SetParticipant(const ParticipantPtr& participant) { + participant_ = participant; + } + +@@ -70,7 +71,9 @@ class RtpsDispatcher : public Dispatcher { + const MessageInfo& msg_info); + void AddSubscriber(const RoleAttributes& self_attr); + // key: channel_id +- std::unordered_map subs_; ++ std::unordered_map> ++ subs_; + std::mutex subs_mutex_; + + ParticipantPtr participant_; +@@ -81,11 +84,23 @@ class RtpsDispatcher : public Dispatcher { + template + void RtpsDispatcher::AddListener(const RoleAttributes& self_attr, + const MessageListener& listener) { +- auto listener_adapter = [listener]( ++ auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& msg_str, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + RETURN_IF(!message::ParseFromString(*msg_str, msg.get())); ++ uint64_t recv_time = Time::Now().ToNanosecond(); ++ uint64_t send_time = msg_info.send_time(); ++ if (send_time > recv_time) { ++ AWARN << "The message is received (" << recv_time ++ << ") earlier than the message is sent (" << send_time << ")"; ++ } else { ++ uint64_t diff = recv_time - send_time; ++ // sample transport latency in microsecond ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); + listener(msg, msg_info); + }; + +@@ -97,11 +112,23 @@ template + void RtpsDispatcher::AddListener(const RoleAttributes& self_attr, + const RoleAttributes& opposite_attr, + const MessageListener& listener) { +- auto listener_adapter = [listener]( ++ auto listener_adapter = [listener, self_attr]( + const std::shared_ptr& msg_str, + const MessageInfo& msg_info) { + auto msg = std::make_shared(); + RETURN_IF(!message::ParseFromString(*msg_str, msg.get())); ++ uint64_t recv_time = Time::Now().ToNanosecond(); ++ uint64_t send_time = msg_info.send_time(); ++ if (send_time > recv_time) { ++ AWARN << "The message is received (" << recv_time ++ << ") earlier than the message is sent (" << send_time << ")"; ++ } else { ++ uint64_t diff = recv_time - send_time; ++ // sample transport latency in microsecond ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, recv_time); + listener(msg, msg_info); + }; + +diff --git a/cyber/transport/dispatcher/shm_dispatcher.cc b/cyber/transport/dispatcher/shm_dispatcher.cc +index 9032870..383091f 100644 +--- a/cyber/transport/dispatcher/shm_dispatcher.cc ++++ b/cyber/transport/dispatcher/shm_dispatcher.cc +@@ -15,6 +15,7 @@ + *****************************************************************************/ + + #include "cyber/transport/dispatcher/shm_dispatcher.h" ++ + #include "cyber/common/global_data.h" + #include "cyber/common/util.h" + #include "cyber/scheduler/scheduler_factory.h" +@@ -54,6 +55,7 @@ void ShmDispatcher::AddSegment(const RoleAttributes& self_attr) { + auto segment = SegmentFactory::CreateSegment(channel_id); + segments_[channel_id] = segment; + previous_indexes_[channel_id] = UINT32_MAX; ++ arena_previous_indexes_[channel_id] = UINT32_MAX; + } + + void ShmDispatcher::ReadMessage(uint64_t channel_id, uint32_t block_index) { +@@ -82,6 +84,32 @@ void ShmDispatcher::ReadMessage(uint64_t channel_id, uint32_t block_index) { + segments_[channel_id]->ReleaseReadBlock(*rb); + } + ++void ShmDispatcher::ReadArenaMessage(uint64_t channel_id, ++ uint32_t arena_block_index) { ++ ADEBUG << "Reading sharedmem arena message: " ++ << GlobalData::GetChannelById(channel_id) ++ << " from block: " << arena_block_index; ++ auto rb = std::make_shared(); ++ rb->index = arena_block_index; ++ if (!segments_[channel_id]->AcquireArenaBlockToRead(rb.get())) { ++ AWARN << "fail to acquire block, channel: " ++ << GlobalData::GetChannelById(channel_id) ++ << " index: " << arena_block_index; ++ return; ++ } ++ ++ MessageInfo msg_info; ++ const char* msg_info_addr = ++ reinterpret_cast(rb->buf) + rb->block->msg_size(); ++ if (msg_info.DeserializeFrom(msg_info_addr, rb->block->msg_info_size())) { ++ OnArenaMessage(channel_id, rb, msg_info); ++ } else { ++ AERROR << "error msg info of channel:" ++ << GlobalData::GetChannelById(channel_id); ++ } ++ segments_[channel_id]->ReleaseArenaReadBlock(*rb); ++} ++ + void ShmDispatcher::OnMessage(uint64_t channel_id, + const std::shared_ptr& rb, + const MessageInfo& msg_info) { +@@ -94,8 +122,29 @@ void ShmDispatcher::OnMessage(uint64_t channel_id, + *handler_base); + handler->Run(rb, msg_info); + } else { +- AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) +- << "'s handler."; ++ if (!arena_msg_listeners_.Get(channel_id, &handler_base)) { ++ AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) ++ << "'s handler."; ++ } ++ } ++} ++ ++void ShmDispatcher::OnArenaMessage(uint64_t channel_id, ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info) { ++ if (is_shutdown_.load()) { ++ return; ++ } ++ ListenerHandlerBasePtr* handler_base = nullptr; ++ if (arena_msg_listeners_.Get(channel_id, &handler_base)) { ++ auto handler = std::dynamic_pointer_cast>( ++ *handler_base); ++ handler->Run(rb, msg_info); ++ } else { ++ if (!msg_listeners_.Get(channel_id, &handler_base)) { ++ AERROR << "Cannot find " << GlobalData::GetChannelById(channel_id) ++ << "'s handler."; ++ } + } + } + +@@ -113,33 +162,57 @@ void ShmDispatcher::ThreadFunc() { + } + + uint64_t channel_id = readable_info.channel_id(); +- uint32_t block_index = readable_info.block_index(); ++ int32_t block_index = readable_info.block_index(); ++ int32_t arena_block_index = readable_info.arena_block_index(); + + { + ReadLockGuard lock(segments_lock_); + if (segments_.count(channel_id) == 0) { + continue; + } +- // check block index +- if (previous_indexes_.count(channel_id) == 0) { +- previous_indexes_[channel_id] = UINT32_MAX; +- } +- uint32_t& previous_index = previous_indexes_[channel_id]; +- if (block_index != 0 && previous_index != UINT32_MAX) { +- if (block_index == previous_index) { +- ADEBUG << "Receive SAME index " << block_index << " of channel " +- << channel_id; +- } else if (block_index < previous_index) { +- ADEBUG << "Receive PREVIOUS message. last: " << previous_index +- << ", now: " << block_index; +- } else if (block_index - previous_index > 1) { +- ADEBUG << "Receive JUMP message. last: " << previous_index +- << ", now: " << block_index; ++ ++ if (block_index != -1) { ++ // check block index ++ if (previous_indexes_.count(channel_id) == 0) { ++ previous_indexes_[channel_id] = UINT32_MAX; + } ++ uint32_t& previous_index = previous_indexes_[channel_id]; ++ if (block_index != 0 && previous_index != UINT32_MAX) { ++ if (block_index == previous_index) { ++ ADEBUG << "Receive SAME index " << block_index << " of channel " ++ << channel_id; ++ } else if (block_index < previous_index) { ++ ADEBUG << "Receive PREVIOUS message. last: " << previous_index ++ << ", now: " << block_index; ++ } else if (block_index - previous_index > 1) { ++ ADEBUG << "Receive JUMP message. last: " << previous_index ++ << ", now: " << block_index; ++ } ++ } ++ previous_index = block_index; ++ ReadMessage(channel_id, block_index); + } +- previous_index = block_index; + +- ReadMessage(channel_id, block_index); ++ if (arena_block_index != -1) { ++ if (arena_previous_indexes_.count(channel_id) == 0) { ++ arena_previous_indexes_[channel_id] = UINT32_MAX; ++ } ++ uint32_t& arena_previous_index = arena_previous_indexes_[channel_id]; ++ if (arena_block_index != 0 && arena_previous_index != UINT32_MAX) { ++ if (arena_block_index == arena_previous_index) { ++ ADEBUG << "Receive SAME index " << arena_block_index ++ << " of channel " << channel_id; ++ } else if (arena_block_index < arena_previous_index) { ++ ADEBUG << "Receive PREVIOUS message. last: " << arena_previous_index ++ << ", now: " << arena_block_index; ++ } else if (arena_block_index - arena_previous_index > 1) { ++ ADEBUG << "Receive JUMP message. last: " << arena_previous_index ++ << ", now: " << arena_block_index; ++ } ++ } ++ arena_previous_index = arena_block_index; ++ ReadArenaMessage(channel_id, arena_block_index); ++ } + } + } + } +@@ -149,6 +222,7 @@ bool ShmDispatcher::Init() { + notifier_ = NotifierFactory::CreateNotifier(); + thread_ = std::thread(&ShmDispatcher::ThreadFunc, this); + scheduler::Instance()->SetInnerThreadAttr("shm_disp", &thread_); ++ // statistics::Statistics::Instance()->CreateSpan("protobuf_parse_time"); + return true; + } + +diff --git a/cyber/transport/dispatcher/shm_dispatcher.h b/cyber/transport/dispatcher/shm_dispatcher.h +index 35d8f03..da29289 100644 +--- a/cyber/transport/dispatcher/shm_dispatcher.h ++++ b/cyber/transport/dispatcher/shm_dispatcher.h +@@ -27,9 +27,14 @@ + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/common/macros.h" ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/message_traits.h" ++#include "cyber/message/raw_message.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/time/time.h" + #include "cyber/transport/dispatcher/dispatcher.h" + #include "cyber/transport/shm/notifier_factory.h" ++#include "cyber/transport/shm/protobuf_arena_manager.h" + #include "cyber/transport/shm/segment_factory.h" + + namespace apollo { +@@ -60,17 +65,32 @@ class ShmDispatcher : public Dispatcher { + const RoleAttributes& opposite_attr, + const MessageListener& listener); + ++ template ++ void AddArenaListener(const RoleAttributes& self_attr, ++ const MessageListener& listener); ++ ++ template ++ void AddArenaListener(const RoleAttributes& self_attr, ++ const RoleAttributes& opposite_attr, ++ const MessageListener& listener); ++ + private: + void AddSegment(const RoleAttributes& self_attr); + void ReadMessage(uint64_t channel_id, uint32_t block_index); + void OnMessage(uint64_t channel_id, const std::shared_ptr& rb, + const MessageInfo& msg_info); ++ void ReadArenaMessage(uint64_t channel_id, uint32_t arena_block_index); ++ void OnArenaMessage(uint64_t channel_id, ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info); + void ThreadFunc(); + bool Init(); + + uint64_t host_id_; + SegmentContainer segments_; + std::unordered_map previous_indexes_; ++ std::unordered_map arena_previous_indexes_; ++ AtomicHashMap arena_msg_listeners_; + AtomicRWLock segments_lock_; + std::thread thread_; + NotifierPtr notifier_; +@@ -78,19 +98,174 @@ class ShmDispatcher : public Dispatcher { + DECLARE_SINGLETON(ShmDispatcher) + }; + ++template ++void ShmDispatcher::AddArenaListener( ++ const RoleAttributes& self_attr, ++ const MessageListener& listener) { ++ if (is_shutdown_.load()) { ++ return; ++ } ++ uint64_t channel_id = self_attr.channel_id(); ++ ++ std::shared_ptr> handler; ++ ListenerHandlerBasePtr* handler_base = nullptr; ++ if (arena_msg_listeners_.Get(channel_id, &handler_base)) { ++ handler = ++ std::dynamic_pointer_cast>(*handler_base); ++ if (handler == nullptr) { ++ AERROR << "please ensure that readers with the same channel[" ++ << self_attr.channel_name() ++ << "] in the same process have the same message type"; ++ return; ++ } ++ } else { ++ ADEBUG << "new reader for channel:" ++ << GlobalData::GetChannelById(channel_id); ++ handler.reset(new ListenerHandler()); ++ arena_msg_listeners_.Set(channel_id, handler); ++ } ++ handler->Connect(self_attr.id(), listener); ++} ++ ++template ++void ShmDispatcher::AddArenaListener( ++ const RoleAttributes& self_attr, const RoleAttributes& opposite_attr, ++ const MessageListener& listener) { ++ if (is_shutdown_.load()) { ++ return; ++ } ++ uint64_t channel_id = self_attr.channel_id(); ++ std::shared_ptr> handler; ++ ListenerHandlerBasePtr* handler_base = nullptr; ++ if (arena_msg_listeners_.Get(channel_id, &handler_base)) { ++ handler = ++ std::dynamic_pointer_cast>(*handler_base); ++ if (handler == nullptr) { ++ AERROR << "please ensuore that readers with the same channel[" ++ << self_attr.channel_name() ++ << "] in the same process have the same message type"; ++ return; ++ } ++ } else { ++ ADEBUG << "new reader for channel:" ++ << GlobalData::GetChannelById(channel_id); ++ handler.reset(new ListenerHandler()); ++ arena_msg_listeners_.Set(channel_id, handler); ++ } ++ handler->Connect(self_attr.id(), listener); ++} ++ + template + void ShmDispatcher::AddListener(const RoleAttributes& self_attr, + const MessageListener& listener) { + // FIXME: make it more clean +- auto listener_adapter = [listener](const std::shared_ptr& rb, +- const MessageInfo& msg_info) { +- auto msg = std::make_shared(); +- RETURN_IF(!message::ParseFromArray( +- rb->buf, static_cast(rb->block->msg_size()), msg.get())); +- listener(msg, msg_info); +- }; +- +- Dispatcher::AddListener(self_attr, listener_adapter); ++ if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ self_attr.channel_id()) && ++ self_attr.message_type() != message::MessageType() && ++ self_attr.message_type() != ++ message::MessageType()) { ++ auto listener_adapter = [listener, self_attr]( ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info) { ++ auto msg = std::make_shared(); ++ // TODO(ALL): read config from msg_info ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ auto msg_wrapper = arena_manager->CreateMessageWrapper(); ++ memcpy(msg_wrapper->GetData(), rb->buf, 1024); ++ MessageT* msg_p; ++ if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(), ++ &msg_p)) { ++ AERROR << "ParseFromArenaMessageWrapper failed"; ++ } ++ // msg->CopyFrom(*msg_p); ++ // msg = arena_manager->LoadMessage(msg_wrapper.get()) ++ auto segment = arena_manager->GetSegment(self_attr.channel_id()); ++ auto msg_addr = reinterpret_cast(msg_p); ++ msg.reset(reinterpret_cast(msg_addr), ++ [arena_manager, segment, msg_wrapper](MessageT* p) { ++ // fprintf(stderr, "msg deleter invoked\n"); ++ // auto related_blocks = ++ // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ // for (auto block_index : related_blocks) { ++ // // segment->ReleaseBlockForReadByIndex(block_index); ++ // segment->RemoveBlockReadLock(block_index); ++ // } ++ }); ++ auto related_blocks_for_lock = ++ arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ for (int i = 0; i < related_blocks_for_lock.size(); ++i) { ++ auto block_index = related_blocks_for_lock[i]; ++ if (!segment->AddBlockReadLock(block_index)) { ++ AWARN << "failed to acquire block for read, channel: " ++ << self_attr.channel_id() << " index: " << block_index; ++ for (int j = 0; j < i; ++j) { ++ // restore the lock ++ segment->RemoveBlockReadLock(related_blocks_for_lock[j]); ++ } ++ return; ++ } ++ } ++ ++ auto send_time = msg_info.send_time(); ++ ++ statistics::Statistics::Instance()->AddRecvCount(self_attr, ++ msg_info.seq_num()); ++ statistics::Statistics::Instance()->SetTotalMsgsStatus( ++ self_attr, msg_info.seq_num()); ++ ++ auto recv_time = Time::Now().ToNanosecond(); ++ ++ // sampling in microsecond ++ auto tran_diff = (recv_time - send_time) / 1000; ++ if (tran_diff > 0) { ++ // sample transport latency in microsecond ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, tran_diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, ++ recv_time / 1000); ++ listener(msg, msg_info); ++ auto related_blocks = ++ arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ for (auto block_index : related_blocks) { ++ // segment->ReleaseBlockForReadByIndex(block_index); ++ segment->RemoveBlockReadLock(block_index); ++ } ++ }; ++ ++ AddArenaListener(self_attr, listener_adapter); ++ } else { ++ auto listener_adapter = [listener, self_attr]( ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info) { ++ auto msg = std::make_shared(); ++ // TODO(ALL): read config from msg_info ++ RETURN_IF(!message::ParseFromArray( ++ rb->buf, static_cast(rb->block->msg_size()), msg.get())); ++ ++ auto send_time = msg_info.send_time(); ++ ++ statistics::Statistics::Instance()->AddRecvCount(self_attr, ++ msg_info.seq_num()); ++ statistics::Statistics::Instance()->SetTotalMsgsStatus( ++ self_attr, msg_info.seq_num()); ++ ++ auto recv_time = Time::Now().ToNanosecond(); ++ ++ // sampling in microsecond ++ auto tran_diff = (recv_time - send_time) / 1000; ++ if (tran_diff > 0) { ++ // sample transport latency in microsecond ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, tran_diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, ++ recv_time / 1000); ++ listener(msg, msg_info); ++ }; ++ ++ Dispatcher::AddListener(self_attr, listener_adapter); ++ } + AddSegment(self_attr); + } + +@@ -99,16 +274,112 @@ void ShmDispatcher::AddListener(const RoleAttributes& self_attr, + const RoleAttributes& opposite_attr, + const MessageListener& listener) { + // FIXME: make it more clean +- auto listener_adapter = [listener](const std::shared_ptr& rb, +- const MessageInfo& msg_info) { +- auto msg = std::make_shared(); +- RETURN_IF(!message::ParseFromArray( +- rb->buf, static_cast(rb->block->msg_size()), msg.get())); +- listener(msg, msg_info); +- }; +- +- Dispatcher::AddListener(self_attr, opposite_attr, +- listener_adapter); ++ if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ self_attr.channel_id()) && ++ self_attr.message_type() != message::MessageType() && ++ self_attr.message_type() != ++ message::MessageType()) { ++ auto listener_adapter = [listener, self_attr]( ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info) { ++ auto msg = std::make_shared(); ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ auto msg_wrapper = arena_manager->CreateMessageWrapper(); ++ memcpy(msg_wrapper->GetData(), rb->buf, 1024); ++ MessageT* msg_p; ++ if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(), ++ &msg_p)) { ++ AERROR << "ParseFromArenaMessageWrapper failed"; ++ } ++ // msg->CopyFrom(*msg_p); ++ // msg = arena_manager->LoadMessage(msg_wrapper.get()) ++ auto segment = arena_manager->GetSegment(self_attr.channel_id()); ++ auto msg_addr = reinterpret_cast(msg_p); ++ msg.reset(reinterpret_cast(msg_addr), ++ [arena_manager, segment, msg_wrapper](MessageT* p) { ++ // fprintf(stderr, "msg deleter invoked\n"); ++ // auto related_blocks = ++ // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ // for (auto block_index : related_blocks) { ++ // // segment->ReleaseBlockForReadByIndex(block_index); ++ // segment->RemoveBlockReadLock(block_index); ++ // } ++ }); ++ auto related_blocks_for_lock = ++ arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ for (int i = 0; i < related_blocks_for_lock.size(); ++i) { ++ auto block_index = related_blocks_for_lock[i]; ++ if (!segment->AddBlockReadLock(block_index)) { ++ AWARN << "failed to acquire block for read, channel: " ++ << self_attr.channel_id() << " index: " << block_index; ++ for (int j = 0; j < i; ++j) { ++ // restore the lock ++ segment->RemoveBlockReadLock(related_blocks_for_lock[j]); ++ } ++ return; ++ } ++ } ++ ++ auto send_time = msg_info.send_time(); ++ ++ statistics::Statistics::Instance()->AddRecvCount(self_attr, ++ msg_info.seq_num()); ++ statistics::Statistics::Instance()->SetTotalMsgsStatus( ++ self_attr, msg_info.seq_num()); ++ ++ auto recv_time = Time::Now().ToNanosecond(); ++ ++ // sampling in microsecond ++ auto tran_diff = (recv_time - send_time) / 1000; ++ if (tran_diff > 0) { ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, tran_diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, ++ recv_time / 1000); ++ ++ listener(msg, msg_info); ++ auto related_blocks = ++ arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ for (auto block_index : related_blocks) { ++ // segment->ReleaseBlockForReadByIndex(block_index); ++ segment->RemoveBlockReadLock(block_index); ++ } ++ }; ++ ++ AddArenaListener(self_attr, opposite_attr, listener_adapter); ++ } else { ++ auto listener_adapter = [listener, self_attr]( ++ const std::shared_ptr& rb, ++ const MessageInfo& msg_info) { ++ auto msg = std::make_shared(); ++ RETURN_IF(!message::ParseFromArray( ++ rb->buf, static_cast(rb->block->msg_size()), msg.get())); ++ ++ auto send_time = msg_info.send_time(); ++ auto msg_seq_num = msg_info.seq_num(); ++ ++ statistics::Statistics::Instance()->AddRecvCount(self_attr, msg_seq_num); ++ statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr, ++ msg_seq_num); ++ ++ auto recv_time = Time::Now().ToNanosecond(); ++ ++ // sampling in microsecond ++ auto tran_diff = (recv_time - send_time) / 1000; ++ if (tran_diff > 0) { ++ statistics::Statistics::Instance()->SamplingTranLatency( ++ self_attr, tran_diff); ++ } ++ statistics::Statistics::Instance()->SetProcStatus(self_attr, ++ recv_time / 1000); ++ ++ listener(msg, msg_info); ++ }; ++ ++ Dispatcher::AddListener(self_attr, opposite_attr, ++ listener_adapter); ++ } + AddSegment(self_attr); + } + +diff --git a/cyber/transport/dispatcher/shm_dispatcher_test.cc b/cyber/transport/dispatcher/shm_dispatcher_test.cc +index 2c7cee5..fa5f6e5 100644 +--- a/cyber/transport/dispatcher/shm_dispatcher_test.cc ++++ b/cyber/transport/dispatcher/shm_dispatcher_test.cc +@@ -20,7 +20,6 @@ + #include "gtest/gtest.h" + + #include "cyber/common/global_data.h" +-#include "cyber/common/log.h" + #include "cyber/common/util.h" + #include "cyber/init.h" + #include "cyber/message/raw_message.h" +diff --git a/cyber/transport/dispatcher/subscriber_listener.cc b/cyber/transport/dispatcher/subscriber_listener.cc +new file mode 100644 +index 0000000..6254ed1 +--- /dev/null ++++ b/cyber/transport/dispatcher/subscriber_listener.cc +@@ -0,0 +1,76 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/transport/dispatcher/subscriber_listener.h" ++ ++#include "cyber/common/log.h" ++#include "cyber/transport/message/message_info.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++namespace dispatcher { ++ ++SubscriberListener::SubscriberListener(const rtps::subsciber_callback& callback) ++ : callback_(callback) {} ++ ++SubscriberListener::~SubscriberListener() {} ++ ++void SubscriberListener::on_data_available( ++ eprosima::fastdds::dds::DataReader* reader) { ++ RETURN_IF_NULL(reader); ++ RETURN_IF_NULL(callback_); ++ ++ // fetch channel name ++ auto channel_id = common::Hash(reader->get_topicdescription()->get_name()); ++ eprosima::fastdds::dds::SampleInfo m_info; ++ UnderlayMessage m; ++ ++ while (reader->take_next_sample(reinterpret_cast(&m), &m_info) == ++ eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { ++ if (m_info.valid_data) { ++ char* ptr = reinterpret_cast( ++ &m_info.related_sample_identity.writer_guid()); ++ Identity sender_id(false); ++ sender_id.set_data(ptr); ++ msg_info_.set_sender_id(sender_id); ++ ++ Identity spare_id(false); ++ spare_id.set_data(ptr + ID_SIZE); ++ msg_info_.set_spare_id(spare_id); ++ ++ msg_info_.set_seq_num(m.seq()); ++ msg_info_.set_send_time(m.timestamp()); ++ // callback ++ callback_(std::make_shared(m.data()), channel_id, msg_info_); ++ } else { ++ AERROR << "Remote writer for topic " ++ << reader->get_topicdescription()->get_name() << " is dead"; ++ } ++ } ++} ++ ++void SubscriberListener::on_subscription_matched( ++ eprosima::fastdds::dds::DataReader* reader, ++ const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) { ++ (void)reader; ++ (void)info; ++} ++ ++} // namespace dispatcher ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/rtps/sub_listener.h b/cyber/transport/dispatcher/subscriber_listener.h +similarity index 54% +rename from cyber/transport/rtps/sub_listener.h +rename to cyber/transport/dispatcher/subscriber_listener.h +index fc16abf..f379fa9 100644 +--- a/cyber/transport/rtps/sub_listener.h ++++ b/cyber/transport/dispatcher/subscriber_listener.h +@@ -14,8 +14,8 @@ + * limitations under the License. + *****************************************************************************/ + +-#ifndef CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ +-#define CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ ++#ifndef CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ ++#define CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ + + #include + #include +@@ -23,42 +23,43 @@ + #include + #include + ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/subscriber/DataReader.hpp" ++#include "fastdds/dds/subscriber/SampleInfo.hpp" ++#include "fastdds/dds/subscriber/SubscriberListener.hpp" ++#include "fastdds/dds/topic/TopicDescription.hpp" ++ ++#include "cyber/common/util.h" + #include "cyber/transport/message/message_info.h" ++#include "cyber/transport/common/common_type.h" + #include "cyber/transport/rtps/underlay_message.h" + #include "cyber/transport/rtps/underlay_message_type.h" +-#include "fastrtps/Domain.h" +-#include "fastrtps/subscriber/SampleInfo.h" +-#include "fastrtps/subscriber/Subscriber.h" +-#include "fastrtps/subscriber/SubscriberListener.h" + + namespace apollo { + namespace cyber { + namespace transport { +- +-class SubListener; +-using SubListenerPtr = std::shared_ptr; +- +-class SubListener : public eprosima::fastrtps::SubscriberListener { ++namespace dispatcher { ++class SubscriberListener : public eprosima::fastdds::dds::SubscriberListener { + public: +- using NewMsgCallback = std::function& msg_str, +- const MessageInfo& msg_info)>; +- +- explicit SubListener(const NewMsgCallback& callback); +- virtual ~SubListener(); ++ explicit SubscriberListener(const rtps::subsciber_callback& callback); ++ virtual ~SubscriberListener(); + +- void onNewDataMessage(eprosima::fastrtps::Subscriber* sub); +- void onSubscriptionMatched(eprosima::fastrtps::Subscriber* sub, +- eprosima::fastrtps::MatchingInfo& info); // NOLINT ++ void on_data_available(eprosima::fastdds::dds::DataReader* reader) override; ++ void on_subscription_matched( ++ eprosima::fastdds::dds::DataReader* reader, ++ const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) ++ override; // NOLINT + + private: +- NewMsgCallback callback_; ++ rtps::subsciber_callback callback_; + MessageInfo msg_info_; + std::mutex mutex_; + }; + ++} // namespace dispatcher + } // namespace transport + } // namespace cyber + } // namespace apollo + +-#endif // CYBER_TRANSPORT_RTPS_SUB_LISTENER_H_ ++#endif // CYBER_TRANSPORT_DISPATCHER_SUBSCRIBER_LISTENER_H_ +diff --git a/cyber/transport/message/listener_handler.h b/cyber/transport/message/listener_handler.h +index b4b662a..a99051d 100644 +--- a/cyber/transport/message/listener_handler.h ++++ b/cyber/transport/message/listener_handler.h +@@ -25,6 +25,7 @@ + #include "cyber/base/atomic_rw_lock.h" + #include "cyber/base/signal.h" + #include "cyber/common/log.h" ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/message_traits.h" + #include "cyber/message/raw_message.h" + #include "cyber/transport/message/message_info.h" +diff --git a/cyber/transport/message/message_info.cc b/cyber/transport/message/message_info.cc +index 185375e..00fe0ae 100644 +--- a/cyber/transport/message/message_info.cc ++++ b/cyber/transport/message/message_info.cc +@@ -24,7 +24,9 @@ namespace apollo { + namespace cyber { + namespace transport { + +-const std::size_t MessageInfo::kSize = 2 * ID_SIZE + sizeof(uint64_t); ++const std::size_t MessageInfo::kSize = 2 * ID_SIZE + sizeof(uint64_t) + \ ++ sizeof(uint64_t) + sizeof(int32_t) + \ ++ sizeof(uint64_t); + + MessageInfo::MessageInfo() : sender_id_(false), spare_id_(false) {} + +@@ -67,9 +69,13 @@ bool MessageInfo::SerializeTo(std::string* dst) const { + RETURN_VAL_IF_NULL(dst, false); + + dst->assign(sender_id_.data(), ID_SIZE); +- dst->append(reinterpret_cast(&seq_num_), sizeof(seq_num_)); ++ dst->append( ++ reinterpret_cast(&channel_id_), sizeof(channel_id_)); ++ dst->append( ++ reinterpret_cast(&seq_num_), sizeof(seq_num_)); + dst->append(spare_id_.data(), ID_SIZE); +- ++ dst->append(reinterpret_cast( ++ &send_time_), sizeof(send_time_)); + return true; + } + +@@ -81,10 +87,16 @@ bool MessageInfo::SerializeTo(char* dst, std::size_t len) const { + char* ptr = dst; + std::memcpy(ptr, sender_id_.data(), ID_SIZE); + ptr += ID_SIZE; +- std::memcpy(ptr, reinterpret_cast(&seq_num_), sizeof(seq_num_)); ++ std::memcpy(ptr, ++ reinterpret_cast(&channel_id_), sizeof(channel_id_)); ++ ptr += sizeof(channel_id_); ++ std::memcpy(ptr, ++ reinterpret_cast(&seq_num_), sizeof(seq_num_)); + ptr += sizeof(seq_num_); + std::memcpy(ptr, spare_id_.data(), ID_SIZE); +- ++ ptr += ID_SIZE; ++ std::memcpy(ptr, ++ reinterpret_cast(&send_time_), sizeof(send_time_)); + return true; + } + +@@ -102,10 +114,16 @@ bool MessageInfo::DeserializeFrom(const char* src, std::size_t len) { + char* ptr = const_cast(src); + sender_id_.set_data(ptr); + ptr += ID_SIZE; +- std::memcpy(reinterpret_cast(&seq_num_), ptr, sizeof(seq_num_)); ++ std::memcpy( ++ reinterpret_cast(&channel_id_), ptr, sizeof(channel_id_)); ++ ptr += sizeof(channel_id_); ++ std::memcpy( ++ reinterpret_cast(&seq_num_), ptr, sizeof(seq_num_)); + ptr += sizeof(seq_num_); + spare_id_.set_data(ptr); +- ++ ptr += ID_SIZE; ++ std::memcpy( ++ reinterpret_cast(&send_time_), ptr, sizeof(send_time_)); + return true; + } + +diff --git a/cyber/transport/message/message_info.h b/cyber/transport/message/message_info.h +index 3e869fb..0ef633c 100644 +--- a/cyber/transport/message/message_info.h ++++ b/cyber/transport/message/message_info.h +@@ -60,11 +60,15 @@ class MessageInfo { + + static const std::size_t kSize; + ++ uint64_t send_time() const { return send_time_; } ++ void set_send_time(uint64_t send_time) { send_time_ = send_time; } ++ + private: + Identity sender_id_; + uint64_t channel_id_ = 0; + uint64_t seq_num_ = 0; + Identity spare_id_; ++ uint64_t send_time_; + }; + + } // namespace transport +diff --git a/cyber/transport/qos/qos_filler.cc b/cyber/transport/qos/qos_filler.cc +new file mode 100644 +index 0000000..5a11d1b +--- /dev/null ++++ b/cyber/transport/qos/qos_filler.cc +@@ -0,0 +1,339 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/transport/qos/qos_filler.h" ++ ++#include "cyber/common/log.h" ++#include "cyber/transport/qos/qos_profile_conf.h" ++ ++#include "fastrtps/attributes/PublisherAttributes.h" ++#include "fastrtps/attributes/SubscriberAttributes.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++using proto::QosDurabilityPolicy; ++using proto::QosHistoryPolicy; ++using proto::QosProfile; ++using proto::QosReliabilityPolicy; ++using transport::QosProfileConf; ++ ++bool GetDefaultPubAttributes( ++ const std::string& channel_name, const QosProfile& qos, ++ eprosima::fastrtps::PublisherAttributes* pub_attr) { ++ RETURN_VAL_IF_NULL2(pub_attr, false); ++ pub_attr->topic.topicName = channel_name; ++ pub_attr->topic.topicDataType = "UnderlayMessage"; ++ pub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; ++ switch (qos.history()) { ++ case QosHistoryPolicy::HISTORY_KEEP_LAST: ++ pub_attr->topic.historyQos.kind = ++ eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; ++ break; ++ case QosHistoryPolicy::HISTORY_KEEP_ALL: ++ pub_attr->topic.historyQos.kind = ++ eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; ++ break; ++ default: ++ break; ++ } ++ switch (qos.durability()) { ++ case QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL: ++ pub_attr->qos.m_durability.kind = ++ eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS; ++ break; ++ case QosDurabilityPolicy::DURABILITY_VOLATILE: ++ pub_attr->qos.m_durability.kind = ++ eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; ++ break; ++ default: ++ break; ++ } ++ ++ switch (qos.reliability()) { ++ case QosReliabilityPolicy::RELIABILITY_BEST_EFFORT: ++ pub_attr->qos.m_reliability.kind = ++ eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS; ++ break; ++ case QosReliabilityPolicy::RELIABILITY_RELIABLE: ++ pub_attr->qos.m_reliability.kind = ++ eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS; ++ break; ++ default: ++ break; ++ } ++ if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { ++ pub_attr->topic.historyQos.depth = static_cast(qos.depth()); ++ } ++ ++ // ensure the history depth is at least the requested queue size ++ RETURN_VAL_IF2(pub_attr->topic.historyQos.depth < 0, false); ++ ++ // tranform messages per second to rtps heartbeat ++ // set default heartbeat period ++ pub_attr->times.heartbeatPeriod.seconds = 0; ++ pub_attr->times.heartbeatPeriod.fraction(300 * 4294967); // 300ms ++ if (qos.mps() != 0) { ++ uint64_t mps = qos.mps(); ++ ++ // adapt heartbeat period ++ if (mps > 1024) { ++ mps = 1024; ++ } else if (mps < 64) { ++ mps = 64; ++ } ++ ++ uint64_t fractions = (256ull << 32) / mps; ++ uint32_t fraction = fractions & 0xffffffff; ++ int32_t seconds = static_cast(fractions >> 32); ++ ++ pub_attr->times.heartbeatPeriod.seconds = seconds; ++ pub_attr->times.heartbeatPeriod.fraction(fraction); ++ } ++ ++ pub_attr->qos.m_publishMode.kind = ++ eprosima::fastdds::dds::ASYNCHRONOUS_PUBLISH_MODE; ++ pub_attr->historyMemoryPolicy = ++ eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; ++ AINFO << channel_name << "qos: [history: " << pub_attr->topic.historyQos.kind ++ << "] [durability: " << pub_attr->qos.m_durability.kind ++ << "] [reliability: " << pub_attr->qos.m_reliability.kind ++ << "] [depth: " << pub_attr->topic.historyQos.depth ++ << "] [samples: " << pub_attr->topic.resourceLimitsQos.max_samples ++ << "]"; ++ ++ return true; ++} ++ ++bool GetDefaultSubAttributes( ++ const std::string& channel_name, const QosProfile& qos, ++ eprosima::fastrtps::SubscriberAttributes* sub_attr) { ++ RETURN_VAL_IF_NULL2(sub_attr, false); ++ sub_attr->topic.topicName = channel_name; ++ sub_attr->topic.topicDataType = "UnderlayMessage"; ++ sub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; ++ ++ switch (qos.history()) { ++ case QosHistoryPolicy::HISTORY_KEEP_LAST: ++ sub_attr->topic.historyQos.kind = ++ eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; ++ break; ++ case QosHistoryPolicy::HISTORY_KEEP_ALL: ++ sub_attr->topic.historyQos.kind = ++ eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; ++ break; ++ default: ++ break; ++ } ++ switch (qos.durability()) { ++ case QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL: ++ sub_attr->qos.m_durability.kind = ++ eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS; ++ break; ++ case QosDurabilityPolicy::DURABILITY_VOLATILE: ++ sub_attr->qos.m_durability.kind = ++ eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS; ++ break; ++ default: ++ break; ++ } ++ ++ switch (qos.reliability()) { ++ case QosReliabilityPolicy::RELIABILITY_BEST_EFFORT: ++ sub_attr->qos.m_reliability.kind = ++ eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS; ++ break; ++ case QosReliabilityPolicy::RELIABILITY_RELIABLE: ++ sub_attr->qos.m_reliability.kind = ++ eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS; ++ break; ++ default: ++ break; ++ } ++ if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { ++ sub_attr->topic.historyQos.depth = static_cast(qos.depth()); ++ } ++ ++ // ensure the history depth is at least the requested queue size ++ RETURN_VAL_IF2(sub_attr->topic.historyQos.depth < 0, false); ++ ++ sub_attr->historyMemoryPolicy = ++ eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; ++ AINFO << channel_name << "qos: [history: " << sub_attr->topic.historyQos.kind ++ << "] [durability: " << sub_attr->qos.m_durability.kind ++ << "] [reliability: " << sub_attr->qos.m_reliability.kind ++ << "] [depth: " << sub_attr->topic.historyQos.depth ++ << "] [samples: " << sub_attr->topic.resourceLimitsQos.max_samples ++ << "]"; ++ ++ return true; ++} ++ ++bool GetDefaultTopicAttributes( ++ const std::string& channel_name, const QosProfile& qos, ++ eprosima::fastrtps::TopicAttributes* topic_attr) { ++ RETURN_VAL_IF_NULL2(topic_attr, false); ++ topic_attr->topicName = channel_name; ++ topic_attr->topicDataType = "UnderlayMessage"; ++ topic_attr->topicKind = eprosima::fastrtps::rtps::NO_KEY; ++ ++ switch (qos.history()) { ++ case QosHistoryPolicy::HISTORY_KEEP_LAST: ++ topic_attr->historyQos.kind = ++ eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS; ++ break; ++ case QosHistoryPolicy::HISTORY_KEEP_ALL: ++ topic_attr->historyQos.kind = ++ eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS; ++ break; ++ default: ++ break; ++ } ++ ++ if (qos.depth() != QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT) { ++ topic_attr->historyQos.depth = static_cast(qos.depth()); ++ } ++ ++ // ensure the history depth is at least the requested queue size ++ RETURN_VAL_IF2(topic_attr->historyQos.depth < 0, false); ++ ++ return true; ++} ++ ++/////////////////////////////////////////////////////////////////////////// ++bool QosFiller::FillInPubQos(const std::string& channel_name, ++ const QosProfile& qos, ++ eprosima::fastdds::dds::PublisherQos* pub_qos) { ++ RETURN_VAL_IF_NULL2(pub_qos, false); ++ eprosima::fastrtps::PublisherAttributes pub_attr; ++ if (!GetDefaultPubAttributes(channel_name, qos, &pub_attr)) { ++ return false; ++ } ++ pub_qos->group_data().setValue(pub_attr.qos.m_groupData); ++ pub_qos->partition() = pub_attr.qos.m_partition; ++ pub_qos->presentation() = pub_attr.qos.m_presentation; ++ return true; ++} ++ ++bool QosFiller::FillInWriterQos( ++ const std::string& channel_name, const QosProfile& qos, ++ eprosima::fastdds::dds::DataWriterQos* writer_qos) { ++ RETURN_VAL_IF_NULL2(writer_qos, false); ++ eprosima::fastrtps::PublisherAttributes pub_attr; ++ if (!GetDefaultPubAttributes(channel_name, qos, &pub_attr)) { ++ return false; ++ } ++ writer_qos->writer_resource_limits().matched_subscriber_allocation = ++ pub_attr.matched_subscriber_allocation; ++ writer_qos->properties() = pub_attr.properties; ++ writer_qos->throughput_controller() = pub_attr.throughputController; ++ writer_qos->endpoint().unicast_locator_list = pub_attr.unicastLocatorList; ++ writer_qos->endpoint().multicast_locator_list = pub_attr.multicastLocatorList; ++ writer_qos->endpoint().remote_locator_list = pub_attr.remoteLocatorList; ++ writer_qos->endpoint().history_memory_policy = pub_attr.historyMemoryPolicy; ++ writer_qos->endpoint().user_defined_id = pub_attr.getUserDefinedID(); ++ writer_qos->endpoint().entity_id = pub_attr.getEntityID(); ++ writer_qos->reliable_writer_qos().times = pub_attr.times; ++ writer_qos->reliable_writer_qos().disable_positive_acks = ++ pub_attr.qos.m_disablePositiveACKs; ++ writer_qos->durability() = pub_attr.qos.m_durability; ++ writer_qos->durability_service() = pub_attr.qos.m_durabilityService; ++ writer_qos->deadline() = pub_attr.qos.m_deadline; ++ writer_qos->latency_budget() = pub_attr.qos.m_latencyBudget; ++ writer_qos->liveliness() = pub_attr.qos.m_liveliness; ++ writer_qos->reliability() = pub_attr.qos.m_reliability; ++ writer_qos->lifespan() = pub_attr.qos.m_lifespan; ++ writer_qos->user_data().setValue(pub_attr.qos.m_userData); ++ writer_qos->ownership() = pub_attr.qos.m_ownership; ++ writer_qos->ownership_strength() = pub_attr.qos.m_ownershipStrength; ++ writer_qos->destination_order() = pub_attr.qos.m_destinationOrder; ++ writer_qos->representation() = pub_attr.qos.representation; ++ writer_qos->publish_mode() = pub_attr.qos.m_publishMode; ++ writer_qos->history() = pub_attr.topic.historyQos; ++ writer_qos->resource_limits() = pub_attr.topic.resourceLimitsQos; ++ return true; ++} ++ ++bool QosFiller::FillInSubQos(const std::string& channel_name, ++ const QosProfile& qos, ++ eprosima::fastdds::dds::SubscriberQos* sub_qos) { ++ RETURN_VAL_IF_NULL2(sub_qos, false); ++ eprosima::fastrtps::SubscriberAttributes sub_attr; ++ if (!GetDefaultSubAttributes(channel_name, qos, &sub_attr)) { ++ return false; ++ } ++ sub_qos->group_data().setValue(sub_attr.qos.m_groupData); ++ sub_qos->partition() = sub_attr.qos.m_partition; ++ sub_qos->presentation() = sub_attr.qos.m_presentation; ++ return true; ++} ++ ++bool QosFiller::FillInReaderQos( ++ const std::string& channel_name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DataReaderQos* reader_qos) { ++ RETURN_VAL_IF_NULL2(reader_qos, false); ++ eprosima::fastrtps::SubscriberAttributes sub_attr; ++ if (!GetDefaultSubAttributes(channel_name, qos, &sub_attr)) { ++ return false; ++ } ++ reader_qos->reader_resource_limits().matched_publisher_allocation = ++ sub_attr.matched_publisher_allocation; ++ reader_qos->properties() = sub_attr.properties; ++ reader_qos->expects_inline_qos(sub_attr.expectsInlineQos); ++ reader_qos->endpoint().unicast_locator_list = sub_attr.unicastLocatorList; ++ reader_qos->endpoint().multicast_locator_list = sub_attr.multicastLocatorList; ++ reader_qos->endpoint().remote_locator_list = sub_attr.remoteLocatorList; ++ reader_qos->endpoint().history_memory_policy = sub_attr.historyMemoryPolicy; ++ reader_qos->endpoint().user_defined_id = sub_attr.getUserDefinedID(); ++ reader_qos->endpoint().entity_id = sub_attr.getEntityID(); ++ reader_qos->reliable_reader_qos().times = sub_attr.times; ++ reader_qos->reliable_reader_qos().disable_positive_ACKs = ++ sub_attr.qos.m_disablePositiveACKs; ++ reader_qos->durability() = sub_attr.qos.m_durability; ++ reader_qos->durability_service() = sub_attr.qos.m_durabilityService; ++ reader_qos->deadline() = sub_attr.qos.m_deadline; ++ reader_qos->latency_budget() = sub_attr.qos.m_latencyBudget; ++ reader_qos->liveliness() = sub_attr.qos.m_liveliness; ++ reader_qos->reliability() = sub_attr.qos.m_reliability; ++ reader_qos->lifespan() = sub_attr.qos.m_lifespan; ++ reader_qos->user_data().setValue(sub_attr.qos.m_userData); ++ reader_qos->ownership() = sub_attr.qos.m_ownership; ++ reader_qos->destination_order() = sub_attr.qos.m_destinationOrder; ++ reader_qos->type_consistency().type_consistency = ++ sub_attr.qos.type_consistency; ++ reader_qos->type_consistency().representation = sub_attr.qos.representation; ++ reader_qos->time_based_filter() = sub_attr.qos.m_timeBasedFilter; ++ reader_qos->history() = sub_attr.topic.historyQos; ++ reader_qos->resource_limits() = sub_attr.topic.resourceLimitsQos; ++ return true; ++} ++ ++bool QosFiller::FillInTopicQos(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ eprosima::fastdds::dds::TopicQos* topic_qos) { ++ RETURN_VAL_IF_NULL2(topic_qos, false); ++ eprosima::fastrtps::TopicAttributes topic_attr; ++ if (!GetDefaultTopicAttributes(channel_name, qos, &topic_attr)) { ++ return false; ++ } ++ topic_qos->history() = topic_attr.historyQos; ++ topic_qos->resource_limits() = topic_attr.resourceLimitsQos; ++ return true; ++} ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/qos/qos_filler.h b/cyber/transport/qos/qos_filler.h +new file mode 100644 +index 0000000..f7104b8 +--- /dev/null ++++ b/cyber/transport/qos/qos_filler.h +@@ -0,0 +1,62 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#ifndef CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ ++#define CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ ++ ++#include ++ ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/publisher/qos/DataWriterQos.hpp" ++#include "fastdds/dds/publisher/qos/PublisherQos.hpp" ++#include "fastdds/dds/subscriber/qos/DataReaderQos.hpp" ++#include "fastdds/dds/subscriber/qos/SubscriberQos.hpp" ++#include "fastdds/dds/topic/qos/TopicQos.hpp" ++#include "cyber/proto/qos_profile.pb.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++class QosFiller { ++ public: ++ static bool FillInPubQos(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ eprosima::fastdds::dds::PublisherQos* pub_qos); ++ ++ static bool FillInWriterQos( ++ const std::string& channel_name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DataWriterQos* writer_qos); ++ ++ static bool FillInSubQos(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ eprosima::fastdds::dds::SubscriberQos* sub_qos); ++ ++ static bool FillInReaderQos( ++ const std::string& channel_name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DataReaderQos* reader_qos); ++ ++ static bool FillInTopicQos(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ eprosima::fastdds::dds::TopicQos* topic_qos); ++}; ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_DDS_ADAPTER_FASTDDS_QOS_FILLER_H_ +diff --git a/cyber/transport/receiver/shm_receiver.h b/cyber/transport/receiver/shm_receiver.h +index e39890b..ae18ed9 100644 +--- a/cyber/transport/receiver/shm_receiver.h ++++ b/cyber/transport/receiver/shm_receiver.h +@@ -22,6 +22,7 @@ + #include "cyber/common/log.h" + #include "cyber/transport/dispatcher/shm_dispatcher.h" + #include "cyber/transport/receiver/receiver.h" ++#include "cyber/transport/shm/protobuf_arena_manager.h" + + namespace apollo { + namespace cyber { +@@ -63,6 +64,17 @@ void ShmReceiver::Enable() { + return; + } + ++ if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ this->attr_.channel_id()) && message::MessageType() != \ ++ message::MessageType()) { ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ if (!arena_manager->Enable() || ++ !arena_manager->EnableSegment(this->attr_.channel_id())) { ++ AERROR << "arena manager enable failed."; ++ return; ++ } ++ } ++ + dispatcher_->AddListener( + this->attr_, std::bind(&ShmReceiver::OnNewMessage, this, + std::placeholders::_1, std::placeholders::_2)); +@@ -81,6 +93,16 @@ void ShmReceiver::Disable() { + + template + void ShmReceiver::Enable(const RoleAttributes& opposite_attr) { ++ if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ this->attr_.channel_id()) && message::MessageType() != \ ++ message::MessageType()) { ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ if (!arena_manager->Enable() || ++ !arena_manager->EnableSegment(this->attr_.channel_id())) { ++ AERROR << "arena manager enable failed."; ++ return; ++ } ++ } + dispatcher_->AddListener( + this->attr_, opposite_attr, + std::bind(&ShmReceiver::OnNewMessage, this, std::placeholders::_1, +diff --git a/cyber/transport/rtps/attributes_filler.cc b/cyber/transport/rtps/attributes_filler.cc +index 411e12d..3a203f7 100644 +--- a/cyber/transport/rtps/attributes_filler.cc ++++ b/cyber/transport/rtps/attributes_filler.cc +@@ -35,7 +35,7 @@ bool AttributesFiller::FillInPubAttr( + + pub_attr->topic.topicName = channel_name; + pub_attr->topic.topicDataType = "UnderlayMessage"; +- pub_attr->topic.topicKind = eprosima::fastrtps::NO_KEY; ++ pub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; + + switch (qos.history()) { + case QosHistoryPolicy::HISTORY_KEEP_LAST: +@@ -88,7 +88,7 @@ bool AttributesFiller::FillInPubAttr( + // transform messages per second to rtps heartbeat + // set default heartbeat period + pub_attr->times.heartbeatPeriod.seconds = 1; +- pub_attr->times.heartbeatPeriod.fraction = 0; ++ pub_attr->times.heartbeatPeriod.fraction(0); + if (qos.mps() != 0) { + uint64_t mps = qos.mps(); + +@@ -104,13 +104,13 @@ bool AttributesFiller::FillInPubAttr( + int32_t seconds = static_cast(fractions >> 32); + + pub_attr->times.heartbeatPeriod.seconds = seconds; +- pub_attr->times.heartbeatPeriod.fraction = fraction; ++ pub_attr->times.heartbeatPeriod.fraction(fraction); + } + + pub_attr->qos.m_publishMode.kind = + eprosima::fastrtps::ASYNCHRONOUS_PUBLISH_MODE; + pub_attr->historyMemoryPolicy = +- eprosima::fastrtps::DYNAMIC_RESERVE_MEMORY_MODE; ++ eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; + pub_attr->topic.resourceLimitsQos.max_samples = 10000; + + return true; +@@ -122,7 +122,7 @@ bool AttributesFiller::FillInSubAttr( + RETURN_VAL_IF_NULL(sub_attr, false); + sub_attr->topic.topicName = channel_name; + sub_attr->topic.topicDataType = "UnderlayMessage"; +- sub_attr->topic.topicKind = eprosima::fastrtps::NO_KEY; ++ sub_attr->topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; + + switch (qos.history()) { + case QosHistoryPolicy::HISTORY_KEEP_LAST: +@@ -173,7 +173,7 @@ bool AttributesFiller::FillInSubAttr( + } + + sub_attr->historyMemoryPolicy = +- eprosima::fastrtps::DYNAMIC_RESERVE_MEMORY_MODE; ++ eprosima::fastrtps::rtps::DYNAMIC_RESERVE_MEMORY_MODE; + sub_attr->topic.resourceLimitsQos.max_samples = 10000; + + return true; +diff --git a/cyber/transport/rtps/attributes_filler.h b/cyber/transport/rtps/attributes_filler.h +index 44ab135..df57571 100644 +--- a/cyber/transport/rtps/attributes_filler.h ++++ b/cyber/transport/rtps/attributes_filler.h +@@ -19,6 +19,8 @@ + + #include + ++#include "cyber/base/macros.h" ++ + #include "cyber/proto/qos_profile.pb.h" + #include "fastrtps/attributes/PublisherAttributes.h" + #include "fastrtps/attributes/SubscriberAttributes.h" +diff --git a/cyber/transport/rtps/participant.cc b/cyber/transport/rtps/participant.cc +index 169ac48..6a362be 100644 +--- a/cyber/transport/rtps/participant.cc ++++ b/cyber/transport/rtps/participant.cc +@@ -1,5 +1,5 @@ + /****************************************************************************** +- * Copyright 2018 The Apollo Authors. All Rights Reserved. ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -13,130 +13,207 @@ + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +- + #include "cyber/transport/rtps/participant.h" + +-#include "cyber/common/global_data.h" +-#include "cyber/common/log.h" +-#include "cyber/proto/transport_conf.pb.h" ++#include + + namespace apollo { + namespace cyber { + namespace transport { + +-Participant::Participant(const std::string& name, int send_port, +- eprosima::fastrtps::ParticipantListener* listener) ++auto Participant::CreateSubscriber(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ const rtps::subsciber_callback& callback) ++ -> std::shared_ptr { ++ if (!participant_) { ++ AWARN << "DDSParticipant already released when the subscriber created, " ++ "channel:" ++ << channel_name; ++ return nullptr; ++ } ++ auto subscriber_ptr = std::make_shared( ++ channel_name, qos, participant_, callback); ++ RETURN_VAL_IF(!subscriber_ptr->Init(), nullptr); ++ std::lock_guard lock(subscriber_mutex_); ++ subscriber_map_.emplace(channel_name, subscriber_ptr); ++ return subscriber_ptr; ++} ++ ++Participant::Participant( ++ const std::string& name, int send_port, ++ eprosima::fastdds::dds::DomainParticipantListener* listener) + : shutdown_(false), + name_(name), + send_port_(send_port), + listener_(listener), +- fastrtps_participant_(nullptr) {} ++ type_support_(new UnderlayMessageType()), ++ participant_(nullptr) {} + + Participant::~Participant() {} + ++bool Participant::Init() { ++ return CreateParticipant(name_, send_port_, listener_); ++} ++ + void Participant::Shutdown() { + if (shutdown_.exchange(true)) { + return; + } + +- std::lock_guard lk(mutex_); +- if (fastrtps_participant_ != nullptr) { +- eprosima::fastrtps::Domain::removeParticipant(fastrtps_participant_); +- fastrtps_participant_ = nullptr; ++ publisher_map_.clear(); ++ subscriber_map_.clear(); ++ if (listener_ != nullptr) { ++ delete listener_; + listener_ = nullptr; + } + } + +-eprosima::fastrtps::Participant* Participant::fastrtps_participant() { +- if (shutdown_.load()) { ++auto Participant::CreatePublisher(const std::string& channel_name, ++ const proto::QosProfile& qos) ++ -> std::shared_ptr { ++ if (!participant_) { ++ AWARN << "DDSParticipant already released when the publisher created, " ++ "channel:" ++ << channel_name; + return nullptr; + } ++ auto publisher_ptr = ++ std::make_shared(channel_name, qos, participant_); + +- std::lock_guard lk(mutex_); +- if (fastrtps_participant_ != nullptr) { +- return fastrtps_participant_; +- } +- +- CreateFastRtpsParticipant(name_, send_port_, listener_); +- return fastrtps_participant_; ++ RETURN_VAL_IF(!publisher_ptr->Init(), nullptr); ++ std::lock_guard lock(publisher_mutex_); ++ publisher_map_.emplace(channel_name, publisher_ptr); ++ return publisher_ptr; + } + +-void Participant::CreateFastRtpsParticipant( ++bool Participant::CreateParticipant( + const std::string& name, int send_port, +- eprosima::fastrtps::ParticipantListener* listener) { ++ eprosima::fastdds::dds::DomainParticipantListener* listener) { + uint32_t domain_id = 80; +- + const char* val = ::getenv("CYBER_DOMAIN_ID"); + if (val != nullptr) { + try { + domain_id = std::stoi(val); + } catch (const std::exception& e) { + AERROR << "convert domain_id error " << e.what(); +- return; ++ return false; + } + } + +- auto part_attr_conf = std::make_shared(); +- auto& global_conf = common::GlobalData::Instance()->Config(); +- if (global_conf.has_transport_conf() && +- global_conf.transport_conf().has_participant_attr()) { +- part_attr_conf->CopyFrom(global_conf.transport_conf().participant_attr()); +- } +- +- eprosima::fastrtps::ParticipantAttributes attr; +- attr.rtps.defaultSendPort = send_port; +- attr.rtps.port.domainIDGain = +- static_cast(part_attr_conf->domain_id_gain()); +- attr.rtps.port.portBase = static_cast(part_attr_conf->port_base()); +- attr.rtps.use_IP6_to_send = false; +- attr.rtps.builtin.use_SIMPLE_RTPSParticipantDiscoveryProtocol = true; +- attr.rtps.builtin.use_SIMPLE_EndpointDiscoveryProtocol = true; +- attr.rtps.builtin.m_simpleEDP.use_PublicationReaderANDSubscriptionWriter = +- true; +- attr.rtps.builtin.m_simpleEDP.use_PublicationWriterANDSubscriptionReader = +- true; +- attr.rtps.builtin.domainId = domain_id; +- +- /** +- * The user should set the lease_duration and the announcement_period with +- * values that differ in at least 30%. Values too close to each other may +- * cause the failure of the writer liveliness assertion in networks with high +- * latency or with lots of communication errors. +- */ +- attr.rtps.builtin.leaseDuration.seconds = part_attr_conf->lease_duration(); +- attr.rtps.builtin.leaseDuration_announcementperiod.seconds = +- part_attr_conf->announcement_period(); +- +- attr.rtps.setName(name.c_str()); +- + std::string ip_env("127.0.0.1"); + const char* ip_val = ::getenv("CYBER_IP"); + if (ip_val != nullptr) { + ip_env = ip_val; + if (ip_env.empty()) { + AERROR << "invalid CYBER_IP (an empty string)"; +- return; ++ return false; + } + } +- ADEBUG << "cyber ip: " << ip_env; + ++ auto part_attr_conf = std::make_shared(); ++ auto& global_conf = common::GlobalData::Instance()->Config(); ++ ++ if (!global_conf.has_transport_conf() || ++ !global_conf.transport_conf().has_participant_attr()) { ++ AERROR << "No rtps participant attr conf."; ++ return false; ++ } ++ ++ part_attr_conf->CopyFrom(global_conf.transport_conf().participant_attr()); ++ ++ // set wire protocol ++ eprosima::fastdds::dds::WireProtocolConfigQos wire_protocol; ++ wire_protocol.port.domainIDGain = ++ static_cast(part_attr_conf->domain_id_gain()); ++ wire_protocol.port.portBase = ++ static_cast(part_attr_conf->port_base()); ++ wire_protocol.builtin.discovery_config.discoveryProtocol = ++ eprosima::fastrtps::rtps::DiscoveryProtocol_t::SIMPLE; ++ wire_protocol.builtin.discovery_config.use_SIMPLE_EndpointDiscoveryProtocol = ++ true; ++ wire_protocol.builtin.discovery_config.m_simpleEDP ++ .use_PublicationReaderANDSubscriptionWriter = true; ++ wire_protocol.builtin.discovery_config.m_simpleEDP ++ .use_PublicationWriterANDSubscriptionReader = true; ++ wire_protocol.builtin.discovery_config.leaseDuration.seconds = ++ part_attr_conf->lease_duration(); ++ wire_protocol.builtin.discovery_config.leaseDuration_announcementperiod ++ .seconds = part_attr_conf->announcement_period(); ++ wire_protocol.builtin.discovery_config.ignoreParticipantFlags = static_cast< ++ eprosima::fastrtps::rtps::ParticipantFilteringFlags>( ++ eprosima::fastrtps::rtps::ParticipantFilteringFlags::FILTER_SAME_PROCESS); ++ ++ // set transport locator + eprosima::fastrtps::rtps::Locator_t locator; + locator.port = 0; +- RETURN_IF(!locator.set_IP4_address(ip_env)); +- ++ RETURN_VAL_IF(!eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, ip_env), ++ false); + locator.kind = LOCATOR_KIND_UDPv4; ++ wire_protocol.default_unicast_locator_list.push_back(locator); ++ wire_protocol.builtin.metatrafficUnicastLocatorList.push_back(locator); ++ eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, 239, 255, 0, 1); ++ wire_protocol.builtin.metatrafficMulticastLocatorList.push_back(locator); ++ ++ // set participant qos ++ eprosima::fastdds::dds::PropertyPolicyQos properties; ++ eprosima::fastdds::dds::DomainParticipantQos participant_qos; ++ participant_qos.name(this->name_.c_str()); ++ participant_qos.wire_protocol(wire_protocol); ++ participant_qos.properties(properties); ++ ++ // UDP ++ auto udp_transport = ++ std::make_shared(); ++ udp_transport->sendBufferSize = 1024 * 1025 * 10; ++ udp_transport->receiveBufferSize = 1024 * 1025 * 10; ++ udp_transport->interfaceWhiteList.push_back(ip_env); ++ participant_qos.transport().user_transports.push_back(udp_transport); ++ participant_qos.transport().use_builtin_transports = false; ++ AINFO << "part name: " << participant_qos.name() << ", port: " << send_port_; ++ ++ participant_ = ++ eprosima::fastdds::dds::DomainParticipantFactory::get_instance() ++ ->create_participant(domain_id, participant_qos, listener_, ++ eprosima::fastdds::dds::StatusMask::none()); ++ RETURN_VAL_IF_NULL(participant_, false); ++ if (type_support_.register_type(participant_) != ReturnCode_t::RETCODE_OK) { ++ AERROR << "Register type failed!"; ++ return false; ++ } ++ return true; ++} + +- attr.rtps.defaultUnicastLocatorList.push_back(locator); +- attr.rtps.defaultOutLocatorList.push_back(locator); +- attr.rtps.builtin.metatrafficUnicastLocatorList.push_back(locator); +- +- locator.set_IP4_address(239, 255, 0, 1); +- attr.rtps.builtin.metatrafficMulticastLocatorList.push_back(locator); ++bool Participant::CheckIPVaild(std::string ip_env) { ++ struct ifaddrs *ifap, *ifa; ++ struct sockaddr_in* sa; ++ char ip_address[INET_ADDRSTRLEN]; ++ if (getifaddrs(&ifap) == -1) { ++ AERROR << "getifaddrs error"; ++ return false; ++ } ++ std::vector ip_vec; ++ std::stringstream ip_info; ++ ip_info << "All ip info: \n"; ++ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { ++ if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) { ++ sa = (struct sockaddr_in*)ifa->ifa_addr; ++ inet_ntop(AF_INET, &sa->sin_addr, ip_address, sizeof(ip_address)); ++ ip_info << " " << ifa->ifa_name << " " << ip_address << "\n"; ++ ip_vec.push_back(ip_address); ++ } ++ } ++ AINFO << ip_info.str(); ++ freeifaddrs(ifap); + +- fastrtps_participant_ = +- eprosima::fastrtps::Domain::createParticipant(attr, listener); +- RETURN_IF_NULL(fastrtps_participant_); +- eprosima::fastrtps::Domain::registerType(fastrtps_participant_, &type_); ++ for (std::string ip_interface : ip_vec) { ++ if (ip_interface == ip_env) { ++ AINFO << "Find same the ip interface in host as cyber ip: " << ip_env; ++ return true; ++ } ++ } ++ AERROR << "The same ip interface in host as cyber ip was not found: " ++ << ip_env; ++ return false; + } + + } // namespace transport +diff --git a/cyber/transport/rtps/participant.h b/cyber/transport/rtps/participant.h +index 455c897..9950cbe 100644 +--- a/cyber/transport/rtps/participant.h ++++ b/cyber/transport/rtps/participant.h +@@ -1,5 +1,5 @@ + /****************************************************************************** +- * Copyright 2018 The Apollo Authors. All Rights Reserved. ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -17,47 +17,81 @@ + #ifndef CYBER_TRANSPORT_RTPS_PARTICIPANT_H_ + #define CYBER_TRANSPORT_RTPS_PARTICIPANT_H_ + ++#include ++#include ++ + #include + #include + #include + #include ++#include ++ ++#include "fastdds/dds/domain/DomainParticipantFactory.hpp" ++#include "fastdds/dds/domain/DomainParticipantListener.hpp" ++#include "fastdds/rtps/transport/TCPv4TransportDescriptor.h" ++#include "fastdds/rtps/transport/UDPv4TransportDescriptor.h" ++#include "fastrtps/utils/IPLocator.h" ++ ++#include "cyber/base/macros.h" + ++#include "cyber/proto/qos_profile.pb.h" ++#include "cyber/proto/transport_conf.pb.h" ++ ++#include "cyber/common/global_data.h" ++#include "cyber/common/log.h" ++#include "cyber/transport/rtps/publisher.h" ++#include "cyber/transport/rtps/subscriber.h" + #include "cyber/transport/rtps/underlay_message_type.h" +-#include "fastrtps/Domain.h" +-#include "fastrtps/attributes/ParticipantAttributes.h" +-#include "fastrtps/participant/Participant.h" +-#include "fastrtps/participant/ParticipantListener.h" +-#include "fastrtps/rtps/common/Locator.h" + + namespace apollo { + namespace cyber { + namespace transport { + +-class Participant; +-using ParticipantPtr = std::shared_ptr; +- + class Participant { + public: +- Participant(const std::string& name, int send_port, +- eprosima::fastrtps::ParticipantListener* listener = nullptr); ++ Participant( ++ const std::string& name, int send_port, ++ eprosima::fastdds::dds::DomainParticipantListener* listener = nullptr); + virtual ~Participant(); + + void Shutdown(); ++ bool Init(); ++ auto CreatePublisher(const std::string& channel_name, ++ const proto::QosProfile& qos) ++ -> std::shared_ptr; ++ ++ auto CreateSubscriber(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ const rtps::subsciber_callback& callback = nullptr) ++ -> std::shared_ptr; + +- eprosima::fastrtps::Participant* fastrtps_participant(); + bool is_shutdown() const { return shutdown_.load(); } + + private: +- void CreateFastRtpsParticipant( ++ Participant(const Participant&) = delete; ++ Participant& operator=(const Participant&) = delete; ++ bool CreateParticipant( + const std::string& name, int send_port, +- eprosima::fastrtps::ParticipantListener* listener); ++ eprosima::fastdds::dds::DomainParticipantListener* listener); + ++ bool CheckIPVaild(std::string ip_env); + std::atomic shutdown_; + std::string name_; + int send_port_; +- eprosima::fastrtps::ParticipantListener* listener_; +- UnderlayMessageType type_; +- eprosima::fastrtps::Participant* fastrtps_participant_; ++ ++ using PublisherPtrMap = ++ std::unordered_multimap>; ++ using SubscriberPtrMap = ++ std::unordered_multimap>; ++ ++ std::mutex publisher_mutex_; ++ PublisherPtrMap publisher_map_; ++ std::mutex subscriber_mutex_; ++ SubscriberPtrMap subscriber_map_; ++ ++ eprosima::fastdds::dds::DomainParticipantListener* listener_; ++ eprosima::fastdds::dds::TypeSupport type_support_; ++ eprosima::fastdds::dds::DomainParticipant* participant_; + std::mutex mutex_; + }; + +diff --git a/cyber/transport/rtps/publisher.cc b/cyber/transport/rtps/publisher.cc +new file mode 100644 +index 0000000..ab2effa +--- /dev/null ++++ b/cyber/transport/rtps/publisher.cc +@@ -0,0 +1,136 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++ ++#include "cyber/transport/rtps/publisher.h" ++#include "cyber/common/log.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++Publisher::Publisher(const std::string& channel_name, ++ const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DomainParticipant* participant) ++ : channel_name_(channel_name), ++ qos_(qos), ++ shutdown_(false), ++ participant_(participant), ++ publisher_(nullptr), ++ topic_(nullptr), ++ writer_(nullptr) {} ++ ++Publisher::~Publisher() { Shutdown(); } ++ ++bool Publisher::Init() { ++ eprosima::fastdds::dds::PublisherQos pub_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInPubQos(this->channel_name_, this->qos_, &pub_qos), ++ false); ++ publisher_ = participant_->create_publisher(pub_qos, nullptr); ++ if (publisher_ == nullptr) { ++ AINFO << "something went wrong while creating the publisher..."; ++ return false; ++ } ++ ++ if (!EnsureCreateTopic(this->channel_name_)) { ++ AINFO << "something went wrong while creating the topic..."; ++ return false; ++ } ++ ++ eprosima::fastdds::dds::DataWriterQos writer_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInWriterQos(this->channel_name_, this->qos_, &writer_qos), ++ false); ++ writer_ = publisher_->create_datawriter(topic_, writer_qos, nullptr); ++ if (writer_ == nullptr) { ++ AINFO << "something went wrong while creating the datawriter..."; ++ return false; ++ } ++ ++ return true; ++} ++ ++bool Publisher::Write(const UnderlayMessage& msg, bool is_topo_msg) { ++ RETURN_VAL_IF(shutdown_.load(), false); ++ if (is_topo_msg) { ++ AINFO << "FastDDSPublisher::Write data size: " << msg.data().size(); ++ } ++ return writer_->write( ++ reinterpret_cast(const_cast(&msg))); ++} ++ ++bool Publisher::Write(const UnderlayMessage& msg, const MessageInfo& msg_info, ++ bool is_topo_msg) { ++ RETURN_VAL_IF(shutdown_.load(), false); ++ if (is_topo_msg) { ++ AINFO << "FastDDSPublisher::Write data size: " << msg.data().size(); ++ } ++ ++ eprosima::fastrtps::rtps::WriteParams wparams; ++ ++ char* ptr = ++ reinterpret_cast(&wparams.related_sample_identity().writer_guid()); ++ ++ memcpy(ptr, msg_info.sender_id().data(), ID_SIZE); ++ memcpy(ptr + ID_SIZE, msg_info.spare_id().data(), ID_SIZE); ++ ++ wparams.related_sample_identity().sequence_number().high = ++ (int32_t)((msg_info.seq_num() & 0xFFFFFFFF00000000) >> 32); ++ wparams.related_sample_identity().sequence_number().low = ++ (int32_t)(msg_info.seq_num() & 0xFFFFFFFF); ++ ++ return writer_->write( ++ reinterpret_cast(const_cast(&msg)), wparams); ++} ++ ++void Publisher::Shutdown() { ++ RETURN_IF(shutdown_.exchange(true)); ++ ++ if (publisher_ != nullptr && writer_ != nullptr) { ++ publisher_->delete_datawriter(writer_); ++ writer_ = nullptr; ++ } ++ if (participant_ != nullptr && publisher_ != nullptr) { ++ if (participant_->delete_publisher(publisher_) == ++ eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { ++ publisher_ = nullptr; ++ } else { ++ AERROR << channel_name_ << ": Failed to delete the publisher."; ++ } ++ } ++ if (participant_ != nullptr && topic_ != nullptr) { ++ participant_->delete_topic(topic_); ++ topic_ = nullptr; ++ } ++} ++ ++bool Publisher::EnsureCreateTopic(const std::string& channel_name) { ++ topic_ = dynamic_cast( ++ participant_->lookup_topicdescription(channel_name)); ++ if (topic_ == nullptr) { ++ eprosima::fastdds::dds::TopicQos topic_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInTopicQos(channel_name, this->qos_, &topic_qos), ++ false); ++ topic_ = ++ participant_->create_topic(channel_name, "UnderlayMessage", topic_qos); ++ } ++ return (topic_ != nullptr); ++} ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/rtps/publisher.h b/cyber/transport/rtps/publisher.h +new file mode 100644 +index 0000000..720fee5 +--- /dev/null ++++ b/cyber/transport/rtps/publisher.h +@@ -0,0 +1,73 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_TRANSPORT_RTPS_PUBLISHER_H ++#define CYBER_TRANSPORT_RTPS_PUBLISHER_H ++ ++#include ++#include ++ ++#include "fastdds/dds/domain/DomainParticipant.hpp" ++#include "fastdds/dds/domain/DomainParticipantFactory.hpp" ++#include "fastdds/dds/publisher/DataWriter.hpp" ++#include "fastdds/dds/publisher/DataWriterListener.hpp" ++#include "fastdds/dds/publisher/Publisher.hpp" ++#include "fastdds/dds/topic/Topic.hpp" ++#include "fastdds/dds/topic/TypeSupport.hpp" ++#include "cyber/proto/qos_profile.pb.h" ++#include "cyber/base/macros.h" ++#include "cyber/common/log.h" ++#include "cyber/transport/message/message_info.h" ++#include "cyber/transport/qos/qos_filler.h" ++#include "cyber/transport/rtps/underlay_message.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++class Publisher; ++using PublisherPtr = std::shared_ptr; ++class Publisher { ++ public: ++ Publisher(const std::string& channel_name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DomainParticipant* participant); ++ virtual ~Publisher(); ++ ++ bool Init(); ++ bool Write(const UnderlayMessage& msg, bool is_topo_msg = false); ++ bool Write(const UnderlayMessage& msg, const MessageInfo& msg_info, ++ bool is_topo_msg = false); ++ void Shutdown(); ++ ++ private: ++ Publisher(const Publisher&) = delete; ++ Publisher& operator=(const Publisher&) = delete; ++ bool EnsureCreateTopic(const std::string& channel_name); ++ ++ std::string channel_name_; ++ proto::QosProfile qos_; ++ std::atomic shutdown_; ++ ++ eprosima::fastdds::dds::DomainParticipant* participant_; ++ eprosima::fastdds::dds::Publisher* publisher_; ++ eprosima::fastdds::dds::Topic* topic_; ++ eprosima::fastdds::dds::DataWriter* writer_; ++}; ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_TRANSPORT_RTPS_PUBLISHER_H +diff --git a/cyber/transport/rtps/rtps_test.cc b/cyber/transport/rtps/rtps_test.cc +index 0f6cab4..1e6401b 100644 +--- a/cyber/transport/rtps/rtps_test.cc ++++ b/cyber/transport/rtps/rtps_test.cc +@@ -14,142 +14,159 @@ + * limitations under the License. + *****************************************************************************/ + ++#include + #include + #include + +-#include "fastcdr/Cdr.h" +-#include "fastcdr/exceptions/BadParamException.h" + #include "gtest/gtest.h" + +-#include "cyber/common/global_data.h" + #include "cyber/common/log.h" ++#include "cyber/transport/qos/qos_filler.h" + #include "cyber/transport/qos/qos_profile_conf.h" + #include "cyber/transport/rtps/attributes_filler.h" +-#include "cyber/transport/rtps/participant.h" + #include "cyber/transport/rtps/underlay_message.h" +-#include "cyber/transport/rtps/underlay_message_type.h" + + namespace apollo { + namespace cyber { + namespace transport { + +-TEST(AttributesFillerTest, fill_in_pub_attr_test) { ++TEST(QosFillerTest, fill_in_pub_qos_test) { + QosProfile qos; +- AttributesFiller filler; +- eprosima::fastrtps::PublisherAttributes attrs; ++ QosFiller filler; ++ eprosima::fastdds::dds::PublisherQos pub_qos; ++ eprosima::fastdds::dds::DataWriterQos writer_qos; + qos.set_history(QosHistoryPolicy::HISTORY_KEEP_LAST); + qos.set_durability(QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); + qos.set_mps(32); +- filler.FillInPubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_LAST_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::TRANSIENT_LOCAL_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::BEST_EFFORT_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); +- AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " +- << attrs.times.heartbeatPeriod.fraction; ++ filler.FillInPubQos("channel", qos, &pub_qos); ++ filler.FillInWriterQos("channel", qos, &writer_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, ++ writer_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, ++ writer_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, ++ writer_qos.reliability().kind); ++ AINFO << "heartbeat period: " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds ++ << ", " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; + qos.set_depth(1024); +- attrs.topic.historyQos.depth = 512; +- filler.FillInPubAttr("channel", qos, &attrs); ++ filler.FillInPubQos("channel", qos, &pub_qos); ++ filler.FillInWriterQos("channel", qos, &writer_qos); + AINFO << qos.depth() << ", " + << QosProfileConf::QOS_HISTORY_DEPTH_SYSTEM_DEFAULT << ", " +- << attrs.topic.historyQos.depth; +- EXPECT_EQ(qos.depth(), attrs.topic.historyQos.depth); ++ << writer_qos.history().depth; ++ EXPECT_EQ(qos.depth(), writer_qos.history().depth); + + qos.set_history(QosHistoryPolicy::HISTORY_KEEP_ALL); + qos.set_durability(QosDurabilityPolicy::DURABILITY_VOLATILE); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_RELIABLE); + qos.set_mps(65); +- filler.FillInPubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); +- AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " +- << attrs.times.heartbeatPeriod.fraction; ++ filler.FillInPubQos("channel", qos, &pub_qos); ++ filler.FillInWriterQos("channel", qos, &writer_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS, ++ writer_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, ++ writer_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, ++ writer_qos.reliability().kind); ++ AINFO << "heartbeat period: " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds ++ << ", " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; + + qos.set_history(QosHistoryPolicy::HISTORY_SYSTEM_DEFAULT); + qos.set_durability(QosDurabilityPolicy::DURABILITY_SYSTEM_DEFAULT); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_SYSTEM_DEFAULT); + qos.set_mps(1025); +- filler.FillInPubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); +- AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " +- << attrs.times.heartbeatPeriod.fraction; ++ filler.FillInPubQos("channel", qos, &pub_qos); ++ filler.FillInWriterQos("channel", qos, &writer_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, ++ writer_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, ++ writer_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, ++ writer_qos.reliability().kind); ++ AINFO << "heartbeat period: " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds ++ << ", " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; + qos.set_mps(0); +- filler.FillInPubAttr("channel", qos, &attrs); +- AINFO << "heartbeat period: " << attrs.times.heartbeatPeriod.seconds << ", " +- << attrs.times.heartbeatPeriod.fraction; ++ filler.FillInPubQos("channel", qos, &pub_qos); ++ filler.FillInWriterQos("channel", qos, &writer_qos); ++ AINFO << "heartbeat period: " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.seconds ++ << ", " ++ << writer_qos.reliable_writer_qos().times.heartbeatPeriod.nanosec; ++ qos.set_depth(-1); ++ EXPECT_FALSE(filler.FillInPubQos("channel", qos, &pub_qos)); ++ EXPECT_FALSE(filler.FillInWriterQos("channel", qos, &writer_qos)); + } + + TEST(AttributesFillerTest, fill_in_sub_attr_test) { + QosProfile qos; +- AttributesFiller filler; +- eprosima::fastrtps::SubscriberAttributes attrs; ++ QosFiller filler; ++ eprosima::fastdds::dds::SubscriberQos sub_qos; ++ eprosima::fastdds::dds::DataReaderQos reader_qos; + qos.set_history(QosHistoryPolicy::HISTORY_KEEP_LAST); + qos.set_durability(QosDurabilityPolicy::DURABILITY_TRANSIENT_LOCAL); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_BEST_EFFORT); + qos.set_mps(32); +- filler.FillInSubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_LAST_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::TRANSIENT_LOCAL_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::BEST_EFFORT_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); ++ filler.FillInSubQos("channel", qos, &sub_qos); ++ filler.FillInReaderQos("channel", qos, &reader_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, ++ reader_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::TRANSIENT_LOCAL_DURABILITY_QOS, ++ reader_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, ++ reader_qos.reliability().kind); + qos.set_depth(1024); +- attrs.topic.historyQos.depth = 512; +- filler.FillInSubAttr("channel", qos, &attrs); +- EXPECT_EQ(qos.depth(), attrs.topic.historyQos.depth); ++ // attrs.topic.historyQos.depth = 512; ++ filler.FillInSubQos("channel", qos, &sub_qos); ++ filler.FillInReaderQos("channel", qos, &reader_qos); ++ EXPECT_EQ(qos.depth(), reader_qos.history().depth); + + qos.set_history(QosHistoryPolicy::HISTORY_KEEP_ALL); + qos.set_durability(QosDurabilityPolicy::DURABILITY_VOLATILE); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_RELIABLE); + qos.set_mps(65); +- filler.FillInSubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); ++ filler.FillInSubQos("channel", qos, &sub_qos); ++ filler.FillInReaderQos("channel", qos, &reader_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_ALL_HISTORY_QOS, ++ reader_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, ++ reader_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS, ++ reader_qos.reliability().kind); + + qos.set_history(QosHistoryPolicy::HISTORY_SYSTEM_DEFAULT); + qos.set_durability(QosDurabilityPolicy::DURABILITY_SYSTEM_DEFAULT); + qos.set_reliability(QosReliabilityPolicy::RELIABILITY_SYSTEM_DEFAULT); + qos.set_mps(1025); +- filler.FillInSubAttr("channel", qos, &attrs); +- EXPECT_EQ(eprosima::fastrtps::KEEP_ALL_HISTORY_QOS, +- attrs.topic.historyQos.kind); +- EXPECT_EQ(eprosima::fastrtps::VOLATILE_DURABILITY_QOS, +- attrs.qos.m_durability.kind); +- EXPECT_EQ(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS, +- attrs.qos.m_reliability.kind); +-} +- +-TEST(ParticipantTest, participant_test) { +- eprosima::fastrtps::ParticipantListener listener; +- eprosima::fastrtps::ParticipantListener listener1; ++ filler.FillInSubQos("channel", qos, &sub_qos); ++ filler.FillInReaderQos("channel", qos, &reader_qos); ++ EXPECT_EQ(eprosima::fastdds::dds::KEEP_LAST_HISTORY_QOS, ++ reader_qos.history().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::VOLATILE_DURABILITY_QOS, ++ reader_qos.durability().kind); ++ EXPECT_EQ(eprosima::fastdds::dds::BEST_EFFORT_RELIABILITY_QOS, ++ reader_qos.reliability().kind); ++ ++ qos.set_depth(-1); ++ EXPECT_FALSE(filler.FillInSubQos("channel", qos, &sub_qos)); ++ EXPECT_FALSE(filler.FillInReaderQos("channel", qos, &reader_qos)); + } + + TEST(UnderlayMessageTest, underlay_message_test) { + UnderlayMessage message; + message.timestamp(1024); +- int32_t& t = message.timestamp(); ++ uint64_t& t = message.timestamp(); + t = 256; + EXPECT_EQ(256, message.timestamp()); + + message.seq(1024); +- int32_t& seq = message.seq(); ++ uint64_t& seq = message.seq(); + seq = 256; + EXPECT_EQ(256, message.seq()); + +@@ -160,51 +177,35 @@ TEST(UnderlayMessageTest, underlay_message_test) { + message.data(std::forward("data forward")); + EXPECT_EQ("data forward", message.data()); + +- message.datatype("datatype"); +- std::string& datatype = message.datatype(); +- datatype = "datatype string"; +- EXPECT_EQ(datatype, message.datatype()); +- message.datatype("datatype assign"); +- EXPECT_EQ("datatype assign", message.datatype()); +- message.datatype(std::forward("datatype forward")); +- EXPECT_EQ("datatype forward", message.datatype()); +- + const UnderlayMessage const_message(message); + std::string data1 = const_message.data(); +- std::string datatype1 = const_message.datatype(); + EXPECT_EQ(256, const_message.timestamp()); + EXPECT_EQ(256, const_message.seq()); + EXPECT_EQ("data forward", const_message.data()); +- EXPECT_EQ("datatype forward", const_message.datatype()); + + UnderlayMessage message2; + message2 = message; + EXPECT_EQ(256, message2.timestamp()); + EXPECT_EQ(256, message2.seq()); + EXPECT_EQ("data forward", message2.data()); +- EXPECT_EQ("datatype forward", message2.datatype()); + + UnderlayMessage message3; + message3 = std::forward(message2); + EXPECT_EQ(256, message3.timestamp()); + EXPECT_EQ(256, message3.seq()); + EXPECT_EQ("data forward", message3.data()); +- EXPECT_EQ("datatype forward", message3.datatype()); + + UnderlayMessage message4(message3); + EXPECT_EQ(256, message4.timestamp()); + EXPECT_EQ(256, message4.seq()); + EXPECT_EQ("data forward", message4.data()); +- EXPECT_EQ("datatype forward", message4.datatype()); + + UnderlayMessage message5(std::forward(message4)); + EXPECT_EQ(256, message5.timestamp()); + EXPECT_EQ(256, message5.seq()); + EXPECT_EQ("data forward", message5.data()); +- EXPECT_EQ("datatype forward", message5.datatype()); + + EXPECT_EQ("", message4.data()); +- EXPECT_EQ("", message4.datatype()); + } + + } // namespace transport +diff --git a/cyber/transport/rtps/sub_listener.cc b/cyber/transport/rtps/sub_listener.cc +deleted file mode 100644 +index e623f5b..0000000 +--- a/cyber/transport/rtps/sub_listener.cc ++++ /dev/null +@@ -1,77 +0,0 @@ +-/****************************************************************************** +- * Copyright 2018 The Apollo Authors. All Rights Reserved. +- * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- *****************************************************************************/ +- +-#include "cyber/transport/rtps/sub_listener.h" +- +-#include "cyber/common/log.h" +-#include "cyber/common/util.h" +- +-namespace apollo { +-namespace cyber { +-namespace transport { +- +-SubListener::SubListener(const NewMsgCallback& callback) +- : callback_(callback) {} +- +-SubListener::~SubListener() {} +- +-void SubListener::onNewDataMessage(eprosima::fastrtps::Subscriber* sub) { +- RETURN_IF_NULL(sub); +- RETURN_IF_NULL(callback_); +- std::lock_guard lock(mutex_); +- +- // fetch channel name +- auto channel_id = common::Hash(sub->getAttributes().topic.getTopicName()); +- eprosima::fastrtps::SampleInfo_t m_info; +- UnderlayMessage m; +- +- RETURN_IF(!sub->takeNextData(reinterpret_cast(&m), &m_info)); +- RETURN_IF(m_info.sampleKind != eprosima::fastrtps::ALIVE); +- +- // fetch MessageInfo +- char* ptr = +- reinterpret_cast(&m_info.related_sample_identity.writer_guid()); +- Identity sender_id(false); +- sender_id.set_data(ptr); +- msg_info_.set_sender_id(sender_id); +- +- Identity spare_id(false); +- spare_id.set_data(ptr + ID_SIZE); +- msg_info_.set_spare_id(spare_id); +- +- uint64_t seq_num = +- ((int64_t)m_info.related_sample_identity.sequence_number().high) << 32 | +- m_info.related_sample_identity.sequence_number().low; +- msg_info_.set_seq_num(seq_num); +- +- // fetch message string +- std::shared_ptr msg_str = +- std::make_shared(m.data()); +- +- // callback +- callback_(channel_id, msg_str, msg_info_); +-} +- +-void SubListener::onSubscriptionMatched( +- eprosima::fastrtps::Subscriber* sub, +- eprosima::fastrtps::MatchingInfo& info) { +- (void)sub; +- (void)info; +-} +- +-} // namespace transport +-} // namespace cyber +-} // namespace apollo +diff --git a/cyber/transport/rtps/subscriber.cc b/cyber/transport/rtps/subscriber.cc +new file mode 100644 +index 0000000..52fbfdb +--- /dev/null ++++ b/cyber/transport/rtps/subscriber.cc +@@ -0,0 +1,113 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#include "cyber/transport/rtps/subscriber.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++Subscriber::Subscriber(const std::string& name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DomainParticipant* participant, ++ const rtps::subsciber_callback& callback) ++ : channel_name_(name), ++ qos_(qos), ++ shutdown_(false), ++ callback_(callback), ++ subscriber_listener_(nullptr), ++ participant_(participant), ++ subscriber_(nullptr), ++ topic_(nullptr), ++ reader_(nullptr) {} ++ ++Subscriber::~Subscriber() {} ++ ++bool Subscriber::Init() { ++ eprosima::fastdds::dds::SubscriberQos sub_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInSubQos(this->channel_name_, this->qos_, &sub_qos), ++ false); ++ subscriber_ = participant_->create_subscriber(sub_qos); ++ if (subscriber_ == nullptr) { ++ AINFO << "something went wrong while creating the fastdds subscriber..."; ++ return false; ++ } ++ ++ if (!EnsureCreateTopic(this->channel_name_)) { ++ AINFO << "something went wrong while creating the fastdds topic..."; ++ return false; ++ } ++ ++ eprosima::fastdds::dds::DataReaderQos reader_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInReaderQos(this->channel_name_, this->qos_, &reader_qos), ++ false); ++ subscriber_listener_ = new dispatcher::SubscriberListener(this->callback_); ++ ++ reader_ = ++ subscriber_->create_datareader(topic_, reader_qos, subscriber_listener_); ++ if (reader_ == nullptr) { ++ AINFO << "something went wrong while creating the fastdds datareader..."; ++ return false; ++ } ++ ++ ADEBUG << "dds reader: " << reader_ << ", subscriber: " << this ++ << ", reader guid: " << reader_->guid() ++ << ", channel: " << this->channel_name_; ++ return true; ++} ++ ++void Subscriber::Shutdown() { ++ RETURN_IF(shutdown_.exchange(true)); ++ ++ if (subscriber_ != nullptr && reader_ != nullptr) { ++ subscriber_->delete_datareader(reader_); ++ reader_ = nullptr; ++ } ++ if (participant_ != nullptr && subscriber_ != nullptr) { ++ if (participant_->delete_subscriber(subscriber_) == ++ eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK) { ++ subscriber_ = nullptr; ++ } else { ++ AERROR << channel_name_ << ": Failed to delete the subscriber."; ++ } ++ } ++ if (participant_ != nullptr && topic_ != nullptr) { ++ participant_->delete_topic(topic_); ++ topic_ = nullptr; ++ } ++ ++ if (subscriber_listener_ != nullptr) { ++ delete subscriber_listener_; ++ } ++} ++ ++bool Subscriber::EnsureCreateTopic(const std::string& channel_name) { ++ topic_ = dynamic_cast( ++ participant_->lookup_topicdescription(channel_name)); ++ if (topic_ == nullptr) { ++ eprosima::fastdds::dds::TopicQos topic_qos; ++ RETURN_VAL_IF( ++ !QosFiller::FillInTopicQos(channel_name, this->qos_, &topic_qos), ++ false); ++ topic_ = ++ participant_->create_topic(channel_name, "UnderlayMessage", topic_qos); ++ } ++ return (topic_ != nullptr); ++} ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/rtps/subscriber.h b/cyber/transport/rtps/subscriber.h +new file mode 100644 +index 0000000..1cb5904 +--- /dev/null ++++ b/cyber/transport/rtps/subscriber.h +@@ -0,0 +1,75 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_TRANSPORT_RTPS_SUBSCRIBER_H ++#define CYBER_TRANSPORT_RTPS_SUBSCRIBER_H ++ ++#include ++#include ++#include ++ ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/domain/DomainParticipant.hpp" ++#include "fastdds/dds/domain/DomainParticipantFactory.hpp" ++#include "fastdds/dds/subscriber/DataReader.hpp" ++#include "fastdds/dds/subscriber/DataReaderListener.hpp" ++#include "fastdds/dds/subscriber/Subscriber.hpp" ++#include "fastdds/dds/topic/Topic.hpp" ++#include "fastdds/dds/topic/TypeSupport.hpp" ++ ++#include "cyber/proto/qos_profile.pb.h" ++ ++#include "cyber/common/log.h" ++#include "cyber/service_discovery/communication/subscriber_listener.h" ++#include "cyber/transport/dispatcher/subscriber_listener.h" ++#include "cyber/transport/message/message_info.h" ++#include "cyber/transport/qos/qos_filler.h" ++#include "cyber/transport/rtps/underlay_message.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++class Subscriber { ++ public: ++ Subscriber(const std::string& name, const proto::QosProfile& qos, ++ eprosima::fastdds::dds::DomainParticipant* participant, ++ const rtps::subsciber_callback& callback); ++ virtual ~Subscriber(); ++ ++ bool Init(); ++ void Shutdown(); ++ ++ private: ++ Subscriber(const Subscriber&) = delete; ++ Subscriber& operator=(const Subscriber&) = delete; ++ bool EnsureCreateTopic(const std::string& channel_name); ++ ++ std::string channel_name_; ++ proto::QosProfile qos_; ++ std::atomic shutdown_; ++ rtps::subsciber_callback callback_; ++ ++ eprosima::fastdds::dds::SubscriberListener* subscriber_listener_; ++ eprosima::fastdds::dds::DomainParticipant* participant_; ++ eprosima::fastdds::dds::Subscriber* subscriber_; ++ eprosima::fastdds::dds::Topic* topic_; ++ eprosima::fastdds::dds::DataReader* reader_; ++}; ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif // CYBER_TRANSPORT_RTPS_SUBSCRIBER_H +diff --git a/cyber/transport/rtps/underlay_message.cc b/cyber/transport/rtps/underlay_message.cc +index 581af65..e1fbcf2 100644 +--- a/cyber/transport/rtps/underlay_message.cc ++++ b/cyber/transport/rtps/underlay_message.cc +@@ -22,15 +22,17 @@ + + #include "cyber/transport/rtps/underlay_message.h" + +-#include "fastcdr/exceptions/BadParamException.h" +- + namespace apollo { + namespace cyber { + namespace transport { + ++#define UnderlayMessage_max_cdr_typesize 276ULL; ++#define UnderlayMessage_max_key_cdr_typesize 0ULL; ++ + UnderlayMessage::UnderlayMessage() { + m_timestamp = 0; + m_seq = 0; ++ m_data = ""; + } + + UnderlayMessage::~UnderlayMessage() {} +@@ -39,21 +41,18 @@ UnderlayMessage::UnderlayMessage(const UnderlayMessage& x) { + m_timestamp = x.m_timestamp; + m_seq = x.m_seq; + m_data = x.m_data; +- m_datatype = x.m_datatype; + } + + UnderlayMessage::UnderlayMessage(UnderlayMessage&& x) { + m_timestamp = x.m_timestamp; + m_seq = x.m_seq; + m_data = std::move(x.m_data); +- m_datatype = std::move(x.m_datatype); + } + + UnderlayMessage& UnderlayMessage::operator=(const UnderlayMessage& x) { + m_timestamp = x.m_timestamp; + m_seq = x.m_seq; + m_data = x.m_data; +- m_datatype = x.m_datatype; + + return *this; + } +@@ -62,27 +61,12 @@ UnderlayMessage& UnderlayMessage::operator=(UnderlayMessage&& x) { + m_timestamp = x.m_timestamp; + m_seq = x.m_seq; + m_data = std::move(x.m_data); +- m_datatype = std::move(x.m_datatype); + + return *this; + } + + size_t UnderlayMessage::getMaxCdrSerializedSize(size_t current_alignment) { +- size_t initial_alignment = current_alignment; +- +- current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); +- +- current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); +- +- current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + 255 + 1; +- +- current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + 255 + 1; +- +- return current_alignment - initial_alignment; ++ return UnderlayMessage_max_cdr_typesize; + } + + size_t UnderlayMessage::getCdrSerializedSize(const UnderlayMessage& data, +@@ -90,41 +74,32 @@ size_t UnderlayMessage::getCdrSerializedSize(const UnderlayMessage& data, + size_t initial_alignment = current_alignment; + + current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); ++ 8 + eprosima::fastcdr::Cdr::alignment(current_alignment, 8); + + current_alignment += +- 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); ++ 8 + eprosima::fastcdr::Cdr::alignment(current_alignment, 8); + + current_alignment += 4 + + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + + data.data().size() + 1; + +- current_alignment += 4 + +- eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + +- data.datatype().size() + 1; +- + return current_alignment - initial_alignment; + } + + void UnderlayMessage::serialize(eprosima::fastcdr::Cdr& scdr) const { + scdr << m_timestamp; +- + scdr << m_seq; +- + scdr << m_data; +- scdr << m_datatype; + } + + void UnderlayMessage::deserialize(eprosima::fastcdr::Cdr& dcdr) { + dcdr >> m_timestamp; + dcdr >> m_seq; + dcdr >> m_data; +- dcdr >> m_datatype; + } + + size_t UnderlayMessage::getKeyMaxCdrSerializedSize(size_t current_alignment) { +- size_t current_align = current_alignment; +- return current_align; ++ return UnderlayMessage_max_key_cdr_typesize; + } + + bool UnderlayMessage::isKeyDefined() { return false; } +diff --git a/cyber/transport/rtps/underlay_message.h b/cyber/transport/rtps/underlay_message.h +index b80e32e..e279df2 100644 +--- a/cyber/transport/rtps/underlay_message.h ++++ b/cyber/transport/rtps/underlay_message.h +@@ -24,6 +24,8 @@ + #include + #include + ++#include "cyber/base/macros.h" ++ + #include "fastcdr/Cdr.h" + + namespace apollo { +@@ -75,36 +77,36 @@ class UnderlayMessage { + * @brief This function sets a value in member timestamp + * @param _timestamp New value for member timestamp + */ +- inline void timestamp(int32_t _timestamp) { m_timestamp = _timestamp; } ++ inline void timestamp(uint64_t _timestamp) { m_timestamp = _timestamp; } + + /*! + * @brief This function returns the value of member timestamp + * @return Value of member timestamp + */ +- inline int32_t timestamp() const { return m_timestamp; } ++ inline uint64_t timestamp() const { return m_timestamp; } + + /*! + * @brief This function returns a reference to member timestamp + * @return Reference to member timestamp + */ +- inline int32_t& timestamp() { return m_timestamp; } ++ inline uint64_t& timestamp() { return m_timestamp; } + /*! + * @brief This function sets a value in member seq + * @param _seq New value for member seq + */ +- inline void seq(int32_t _seq) { m_seq = _seq; } ++ inline void seq(uint64_t _seq) { m_seq = _seq; } + + /*! + * @brief This function returns the value of member seq + * @return Value of member seq + */ +- inline int32_t seq() const { return m_seq; } ++ inline uint64_t seq() const { return m_seq; } + + /*! + * @brief This function returns a reference to member seq + * @return Reference to member seq + */ +- inline int32_t& seq() { return m_seq; } ++ inline uint64_t& seq() { return m_seq; } + /*! + * @brief This function copies the value in member data + * @param _data New value to be copied in member data +@@ -128,31 +130,6 @@ class UnderlayMessage { + * @return Reference to member data + */ + inline std::string& data() { return m_data; } +- /*! +- * @brief This function copies the value in member datatype +- * @param _datatype New value to be copied in member datatype +- */ +- inline void datatype(const std::string& _datatype) { m_datatype = _datatype; } +- +- /*! +- * @brief This function moves the value in member datatype +- * @param _datatype New value to be moved in member datatype +- */ +- inline void datatype(std::string&& _datatype) { +- m_datatype = std::move(_datatype); +- } +- +- /*! +- * @brief This function returns a constant reference to member datatype +- * @return Constant reference to member datatype +- */ +- inline const std::string& datatype() const { return m_datatype; } +- +- /*! +- * @brief This function returns a reference to member datatype +- * @return Reference to member datatype +- */ +- inline std::string& datatype() { return m_datatype; } + + /*! + * @brief This function returns the maximum serialized size of an object +@@ -206,10 +183,9 @@ class UnderlayMessage { + void serializeKey(eprosima::fastcdr::Cdr& cdr) const; // NOLINT + + private: +- int32_t m_timestamp; +- int32_t m_seq; ++ uint64_t m_timestamp; ++ uint64_t m_seq; + std::string m_data; +- std::string m_datatype; + }; + + } // namespace transport +diff --git a/cyber/transport/rtps/underlay_message_type.cc b/cyber/transport/rtps/underlay_message_type.cc +index 8af2601..8c0c425 100644 +--- a/cyber/transport/rtps/underlay_message_type.cc ++++ b/cyber/transport/rtps/underlay_message_type.cc +@@ -21,6 +21,8 @@ + + #include "cyber/transport/rtps/underlay_message_type.h" + ++#include ++ + #include "fastcdr/Cdr.h" + #include "fastcdr/FastBuffer.h" + +@@ -32,13 +34,16 @@ namespace transport { + + UnderlayMessageType::UnderlayMessageType() { + setName("UnderlayMessage"); +- m_typeSize = (uint32_t)UnderlayMessage::getMaxCdrSerializedSize() + +- 4 /*encapsulation*/; ++ auto type_size = UnderlayMessage::getMaxCdrSerializedSize(); ++ type_size += eprosima::fastcdr::Cdr::alignment( ++ type_size, 4); /* possible submessage alignment */ ++ m_typeSize = static_cast(type_size) + 4; /*encapsulation*/ + m_isGetKeyDefined = UnderlayMessage::isKeyDefined(); +- m_keyBuffer = +- (unsigned char*)malloc(UnderlayMessage::getKeyMaxCdrSerializedSize() > 16 +- ? UnderlayMessage::getKeyMaxCdrSerializedSize() +- : 16); ++ size_t keyLength = UnderlayMessage::getKeyMaxCdrSerializedSize() > 16 ++ ? UnderlayMessage::getKeyMaxCdrSerializedSize() ++ : 16; ++ m_keyBuffer = (unsigned char*)malloc(keyLength); ++ memset(m_keyBuffer, 0, keyLength); + } + + UnderlayMessageType::~UnderlayMessageType() { +@@ -47,41 +52,61 @@ UnderlayMessageType::~UnderlayMessageType() { + } + } + +-bool UnderlayMessageType::serialize(void* data, SerializedPayload_t* payload) { ++bool UnderlayMessageType::serialize( ++ void* data, eprosima::fastrtps::rtps::SerializedPayload_t* payload) { + UnderlayMessage* p_type = reinterpret_cast(data); + eprosima::fastcdr::FastBuffer fastbuffer( + reinterpret_cast(payload->data), + payload->max_size); // Object that manages the raw buffer. + eprosima::fastcdr::Cdr ser( + fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, +- eprosima::fastcdr::Cdr::DDS_CDR); // Object that serializes the data. ++ eprosima::fastcdr::CdrVersion::DDS_CDR); // Object that serializes the ++ // data. + payload->encapsulation = + ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE + : CDR_LE; +- // Serialize encapsulation +- ser.serialize_encapsulation(); +- p_type->serialize(ser); // Serialize the object: ++ try { ++ // Serialize encapsulation ++ ser.serialize_encapsulation(); ++ // Serialize the object. ++ p_type->serialize(ser); ++ } catch (eprosima::fastcdr::exception::Exception& e) { ++ AERROR << "serialize exception: " << e.what(); ++ return false; ++ } ++ + payload->length = +- (uint32_t)ser.getSerializedDataLength(); // Get the serialized length ++ (uint32_t)ser.get_serialized_data_length(); // Get the serialized length + return true; + } + +-bool UnderlayMessageType::deserialize(SerializedPayload_t* payload, +- void* data) { +- UnderlayMessage* p_type = reinterpret_cast( +- data); // Convert DATA to pointer of your type +- eprosima::fastcdr::FastBuffer fastbuffer( +- reinterpret_cast(payload->data), +- payload->length); // Object that manages the raw buffer. +- eprosima::fastcdr::Cdr deser( +- fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, +- eprosima::fastcdr::Cdr::DDS_CDR); // Object that deserializes the data. +- // Deserialize encapsulation. +- deser.read_encapsulation(); +- payload->encapsulation = +- deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE +- : CDR_LE; +- p_type->deserialize(deser); // Deserialize the object: ++bool UnderlayMessageType::deserialize( ++ eprosima::fastrtps::rtps::SerializedPayload_t* payload, void* data) { ++ try { ++ // Convert DATA to pointer of your type ++ UnderlayMessage* p_type = static_cast(data); ++ ++ // Object that manages the raw buffer. ++ eprosima::fastcdr::FastBuffer fastbuffer( ++ reinterpret_cast(payload->data), payload->length); ++ ++ // Object that deserializes the data. ++ eprosima::fastcdr::Cdr deser(fastbuffer, ++ eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, ++ eprosima::fastcdr::CdrVersion::DDS_CDR); ++ ++ // Deserialize encapsulation. ++ deser.read_encapsulation(); ++ payload->encapsulation = ++ deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE ++ : CDR_LE; ++ ++ // Deserialize the object. ++ p_type->deserialize(deser); ++ } catch (eprosima::fastcdr::exception::Exception& e) { ++ AERROR << "deserialize exception: " << e.what(); ++ return false; ++ } + return true; + } + +@@ -90,7 +115,7 @@ std::function UnderlayMessageType::getSerializedSizeProvider( + return [data]() -> uint32_t { + return (uint32_t)type::getCdrSerializedSize( + *static_cast(data)) + +- 4 /*encapsulation*/; ++ 4u /*encapsulation*/; + }; + } + +@@ -102,21 +127,23 @@ void UnderlayMessageType::deleteData(void* data) { + delete (reinterpret_cast(data)); + } + +-bool UnderlayMessageType::getKey(void* data, InstanceHandle_t* handle) { +- RETURN_VAL_IF((!m_isGetKeyDefined), false); ++bool UnderlayMessageType::getKey( ++ void* data, eprosima::fastrtps::rtps::InstanceHandle_t* handle, ++ bool force_md5) { ++ RETURN_VAL_IF(!m_isGetKeyDefined, false); + UnderlayMessage* p_type = reinterpret_cast(data); + eprosima::fastcdr::FastBuffer fastbuffer( + reinterpret_cast(m_keyBuffer), + UnderlayMessage::getKeyMaxCdrSerializedSize()); // Object that manages + // the raw buffer. +- eprosima::fastcdr::Cdr ser( +- fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS); // Object that +- // serializes the +- // data. ++ // Object that serializes the data. ++ eprosima::fastcdr::Cdr ser(fastbuffer, ++ eprosima::fastcdr::Cdr::BIG_ENDIANNESS); + p_type->serializeKey(ser); +- if (UnderlayMessage::getKeyMaxCdrSerializedSize() > 16) { ++ if (force_md5 || UnderlayMessage::getKeyMaxCdrSerializedSize() > 16) { + m_md5.init(); +- m_md5.update(m_keyBuffer, (unsigned int)ser.getSerializedDataLength()); ++ m_md5.update(m_keyBuffer, ++ static_cast(ser.get_serialized_data_length())); + m_md5.finalize(); + for (uint8_t i = 0; i < 16; ++i) { + handle->value[i] = m_md5.digest[i]; +diff --git a/cyber/transport/rtps/underlay_message_type.h b/cyber/transport/rtps/underlay_message_type.h +index 01db001..a57a012 100644 +--- a/cyber/transport/rtps/underlay_message_type.h ++++ b/cyber/transport/rtps/underlay_message_type.h +@@ -17,8 +17,11 @@ + #ifndef CYBER_TRANSPORT_RTPS_UNDERLAY_MESSAGE_TYPE_H_ + #define CYBER_TRANSPORT_RTPS_UNDERLAY_MESSAGE_TYPE_H_ + ++#include "cyber/base/macros.h" ++ ++#include "fastdds/dds/topic/TopicDataType.hpp" ++#include "fastrtps/utils/md5.h" + #include "cyber/transport/rtps/underlay_message.h" +-#include "fastrtps/TopicDataType.h" + + namespace apollo { + namespace cyber { +@@ -29,18 +32,25 @@ namespace transport { + * defined by the user in the IDL file. + * @ingroup UNDERLAYMESSAGE + */ +-class UnderlayMessageType : public eprosima::fastrtps::TopicDataType { ++class UnderlayMessageType : public eprosima::fastdds::dds::TopicDataType { + public: + using type = UnderlayMessage; + + UnderlayMessageType(); + virtual ~UnderlayMessageType(); +- bool serialize(void* data, SerializedPayload_t* payload); +- bool deserialize(SerializedPayload_t* payload, void* data); +- std::function getSerializedSizeProvider(void* data); +- bool getKey(void* data, InstanceHandle_t* ihandle); +- void* createData(); +- void deleteData(void* data); ++ virtual bool serialize( // NOLINT ++ void* data, ++ eprosima::fastrtps::rtps::SerializedPayload_t* payload) override; ++ virtual bool deserialize( // NOLINT ++ eprosima::fastrtps::rtps::SerializedPayload_t* payload, ++ void* data) override; ++ virtual std::function getSerializedSizeProvider( // NOLINT ++ void* data) override; ++ virtual bool getKey(void* data, // NOLINT ++ eprosima::fastrtps::rtps::InstanceHandle_t* ihandle, ++ bool force_md5 = false) override; ++ virtual void* createData() override; // NOLINT ++ virtual void deleteData(void* data) override; // NOLINT + MD5 m_md5; + unsigned char* m_keyBuffer; + }; +diff --git a/cyber/transport/shm/arena_address_allocator.cc b/cyber/transport/shm/arena_address_allocator.cc +new file mode 100644 +index 0000000..bd94084 +--- /dev/null ++++ b/cyber/transport/shm/arena_address_allocator.cc +@@ -0,0 +1,458 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#include "cyber/transport/shm/arena_address_allocator.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "cyber/base/pthread_rw_lock.h" ++#include "cyber/base/rw_lock_guard.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++ArenaAddressAllocator::ArenaAddressAllocator() ++ : meta_shm_key_( ++ std::hash{}("/apollo/__arena__/__address__/__meta__")), ++ node_shm_key_( ++ std::hash{}("/apollo/__arena__/__address__/__node__")), ++ meta_(nullptr), ++ nodes_(nullptr), ++ reclaim_stack_(nullptr) { ++ // TODO(all): configurable and address management for shared memory of cyber ++ meta_shm_address_ = nullptr; ++ // use fixed address ++ node_shm_address_ = reinterpret_cast(0x7f0000000000); ++ ++ // ensure the allocator's segment size is larger ++ // than the actual arena's segment size ++ // otherwise the shmat will fail ++ Init(1024, reinterpret_cast( ++ 0x710000000000), 2ULL * 1024 * 1024 * 1024); ++} ++ ++ArenaAddressAllocator::~ArenaAddressAllocator() { ++ if (meta_ && meta_->struct_.ref_count_.fetch_sub(1) == 0) { ++ shmdt(meta_); ++ shmctl(shmget(meta_shm_key_, 0, 0), IPC_RMID, nullptr); ++ shmdt(nodes_); ++ shmctl(shmget(node_shm_key_, 0, 0), IPC_RMID, nullptr); ++ } ++} ++ ++bool ArenaAddressAllocator::Init(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size) { ++ if (!OpenMetaShm(capacity, base_address, address_segment_size)) { ++ return false; ++ } ++ if (!OpenNodeShm(capacity, base_address, address_segment_size)) { ++ return false; ++ } ++ meta_->struct_.occupied_.store(false); ++ return true; ++} ++ ++bool ArenaAddressAllocator::Open(uint64_t key, void* base_address, ++ void** shm_address) { ++ auto shmid = shmget(static_cast(key), 0, 0); ++ ++ shmid = shmget(static_cast(key), 0, 0); ++ if (shmid == -1) { ++ // open failed ++ return false; ++ } ++ *shm_address = shmat(shmid, base_address, 0); ++ if (*shm_address == reinterpret_cast(-1)) { ++ // shmat failed ++ return false; ++ } ++ return true; ++} ++ ++bool ArenaAddressAllocator::OpenOrCreate(uint64_t key, uint64_t size, ++ void* base_address, void** shm_address, ++ bool* is_created) { ++ auto shmid = ++ shmget(static_cast(key), size, 0644 | IPC_CREAT | IPC_EXCL); ++ ++ if (shmid == -1) { ++ if (errno == EINVAL) { ++ // TODO(all): recreate larger shm ++ } else if (errno == EEXIST) { ++ *is_created = false; ++ return Open(key, base_address, shm_address); ++ } else { ++ return false; ++ } ++ } ++ *shm_address = shmat(shmid, base_address, 0); ++ if (*shm_address == reinterpret_cast(-1)) { ++ // shmat failed ++ return false; ++ } ++ *is_created = true; ++ return true; ++} ++ ++bool ArenaAddressAllocator::OpenMetaShm(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size) { ++ bool is_created = false; ++ bool ret = false; ++ for (uint32_t retry = 0; retry < 2 && !ret; ++ ++retry, ret = OpenOrCreate( ++ meta_shm_key_, sizeof(ArenaAddressAllocatorMeta), ++ meta_shm_address_, reinterpret_cast(&meta_), ++ &is_created)) { ++ } ++ if (!ret) { ++ // create or open failed ++ return false; ++ } ++ if (!is_created) { ++ meta_->struct_.ref_count_.fetch_add(1); ++ } else { ++ meta_->struct_.version_ = 1; ++ meta_->struct_.capacity_ = capacity; ++ meta_->struct_.base_address_ = base_address; ++ meta_->struct_.address_segment_size_ = address_segment_size; ++ meta_->struct_.root_ = nullptr; ++ meta_->struct_.allocated_index_ = 0; ++ meta_->struct_.reclaim_stack_top_ = 0; ++ meta_->struct_.ref_count_.store(1); ++ } ++ return true; ++} ++ ++bool ArenaAddressAllocator::OpenNodeShm(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size) { ++ uint64_t size = sizeof(ArenaAddressAllocatorMeta) + ++ sizeof(ArenaAddressNode) * (capacity + 1) + ++ sizeof(uint64_t) * capacity; ++ bool is_created = false; ++ bool ret = false; ++ for (uint32_t retry = 0; retry < 2 && !ret; ++ ++retry, ret = OpenOrCreate(node_shm_key_, size, node_shm_address_, ++ reinterpret_cast(&nodes_), ++ &is_created)) { ++ } ++ if (!ret) { ++ // create or open failed ++ return false; ++ } ++ ++ reclaim_stack_ = reinterpret_cast( ++ reinterpret_cast(nodes_) + sizeof(ArenaAddressNode) * capacity); ++ return true; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::NewNode(uint64_t key) { ++ if (meta_->struct_.reclaim_stack_top_ > 0) { ++ uint64_t index = reclaim_stack_[--meta_->struct_.reclaim_stack_top_]; ++ nodes_[index].left_ = nullptr; ++ nodes_[index].right_ = nullptr; ++ nodes_[index].key_ = key; ++ return &nodes_[index]; ++ } ++ if (meta_->struct_.allocated_index_ >= meta_->struct_.capacity_) { ++ // TODO(all): expand nodes ++ return nullptr; ++ } ++ nodes_[meta_->struct_.allocated_index_].left_ = nullptr; ++ nodes_[meta_->struct_.allocated_index_].right_ = nullptr; ++ nodes_[meta_->struct_.allocated_index_].key_ = key; ++ nodes_[meta_->struct_.allocated_index_].index_ = ++ meta_->struct_.allocated_index_; ++ return &nodes_[meta_->struct_.allocated_index_++]; ++} ++ ++void ArenaAddressAllocator::ReclaimNode(ArenaAddressNode* node) { ++ nodes_[node->index_].left_ = nullptr; ++ nodes_[node->index_].right_ = nullptr; ++ nodes_[node->index_].parent_ = nullptr; ++ reclaim_stack_[meta_->struct_.reclaim_stack_top_++] = node->index_; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::FindNode(ArenaAddressNode* node, ++ uint64_t key) { ++ if (node == nullptr) { ++ return nullptr; ++ } ++ if (key < node->key_) { ++ return FindNode(node->left_, key); ++ } else if (key > node->key_) { ++ return FindNode(node->right_, key); ++ } ++ return node; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::FindOrInsertNode( ++ ArenaAddressNode* node, ArenaAddressNode** node_p, ArenaAddressNode* parent, ++ uint64_t key) { ++ if (node == nullptr) { ++ auto target = NewNode(key); ++ *node_p = target; ++ target->parent_ = parent; ++ return target; ++ } ++ if (key < node->key_) { ++ auto target = FindOrInsertNode(node->left_, &(node->left_), node, key); ++ TreeRebalance(node->left_, &(node->left_)); ++ return target; ++ } else if (key > node->key_) { ++ auto target = FindOrInsertNode(node->right_, &(node->right_), node, key); ++ TreeRebalance(node->right_, &(node->right_)); ++ return target; ++ } ++ // key == node->key_ ++ return node; ++} ++ ++void ArenaAddressAllocator::RemoveNode(ArenaAddressNode* node, ++ ArenaAddressNode** node_p, ++ uint64_t key) { ++ if (!node) { ++ return; ++ } ++ if (!FindNode(node, key)) { ++ return; ++ } ++ if (key < node->key_) { ++ RemoveNode(node->left_, &(node->left_), key); ++ if (TreeBalanceFactor(node) < -1) { ++ TreeRebalance(meta_->struct_.root_, &(meta_->struct_.root_)); ++ } ++ return; ++ } else if (key > node->key_) { ++ RemoveNode(node->right_, &(node->right_), key); ++ if (TreeBalanceFactor(node) > 1) { ++ TreeRebalance(meta_->struct_.root_, &(meta_->struct_.root_)); ++ } ++ return; ++ } ++ // node->key_ == key ++ // left and right both exist ++ if (node->left_ && node->right_) { ++ if (TreeBalanceFactor(node) > 0) { ++ auto max_p = &(node->left_); ++ auto max = TreeMax(node->left_, &max_p); ++ SwapNodePosition(node, node_p, max, max_p); ++ RemoveNode(max->left_, &(max->left_), key); ++ return; ++ } else { ++ auto min_p = &(node->right_); ++ auto min = TreeMin(node->right_, &min_p); ++ SwapNodePosition(node, node_p, min, min_p); ++ RemoveNode(min->right_, &(min->right_), key); ++ return; ++ } ++ } ++ // left or right exist ++ *node_p = node->left_ ? node->left_ : node->right_; ++ ReclaimNode(node); ++} ++ ++void ArenaAddressAllocator::SwapNodePosition(ArenaAddressNode* x, ++ ArenaAddressNode** x_p, ++ ArenaAddressNode* y, ++ ArenaAddressNode** y_p) { ++ if (x == nullptr || y == nullptr) { ++ // cannot swap nullptr ++ return; ++ } ++ ++ // swap address ++ *x_p = y; ++ *y_p = x; ++ // swap parent ++ auto parent_x = x->parent_; ++ auto parent_y = y->parent_; ++ x->parent_ = parent_y; ++ y->parent_ = parent_x; ++ ++ ArenaAddressNode* tmp = nullptr; ++ ++ // swap left ++ tmp = x->left_; ++ x->left_ = y->left_; ++ if (x->left_) { ++ x->left_->parent_ = x; ++ } ++ y->left_ = tmp; ++ if (y->left_) { ++ y->left_->parent_ = y; ++ } ++ ++ // swap right ++ tmp = x->right_; ++ x->right_ = y->right_; ++ if (x->right_) { ++ x->right_->parent_ = x; ++ } ++ y->right_ = tmp; ++ if (y->right_) { ++ y->right_->parent_ = y; ++ } ++} ++ ++uint64_t ArenaAddressAllocator::TreeHeight(ArenaAddressNode* node) { ++ if (node == nullptr) { ++ return 0; ++ } ++ return 1 + std::max(TreeHeight(node->left_), TreeHeight(node->right_)); ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeMax(ArenaAddressNode* node, ++ ArenaAddressNode*** node_pp) { ++ if (node == nullptr) { ++ return nullptr; ++ } ++ for (; node->right_;) { ++ *node_pp = &(node->right_); ++ node = node->right_; ++ } ++ return node; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeMin(ArenaAddressNode* node, ++ ArenaAddressNode*** node_pp) { ++ if (node == nullptr) { ++ return nullptr; ++ } ++ for (; node->left_;) { ++ *node_pp = &(node->left_); ++ node = node->left_; ++ } ++ return node; ++} ++ ++int64_t ArenaAddressAllocator::TreeBalanceFactor(ArenaAddressNode* node) { ++ if (node == nullptr) { ++ return 0; ++ } ++ return TreeHeight(node->left_) - TreeHeight(node->right_); ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeRotateLeft( ++ ArenaAddressNode* node, ArenaAddressNode** node_p) { ++ auto parent = node->parent_; ++ auto right = node->right_; ++ ++ node->right_ = right->left_; ++ right->left_ = node; ++ node->parent_ = right; ++ *node_p = right; ++ right->parent_ = parent; ++ ++ return right; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeRotateRight( ++ ArenaAddressNode* node, ArenaAddressNode** node_p) { ++ auto parent = node->parent_; ++ auto left = node->left_; ++ ++ node->left_ = left->right_; ++ left->right_ = node; ++ node->parent_ = left; ++ *node_p = left; ++ left->parent_ = parent; ++ ++ return left; ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeRotateLeftRight( ++ ArenaAddressNode* node, ArenaAddressNode** node_p) { ++ TreeRotateLeft(node->left_, &(node->left_)); ++ return TreeRotateRight(node, node_p); ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeRotateRightLeft( ++ ArenaAddressNode* node, ArenaAddressNode** node_p) { ++ TreeRotateRight(node->right_, &(node->right_)); ++ return TreeRotateLeft(node, node_p); ++} ++ ++ArenaAddressNode* ArenaAddressAllocator::TreeRebalance( ++ ArenaAddressNode* node, ArenaAddressNode** node_p) { ++ if (node == nullptr) { ++ return nullptr; ++ } ++ auto balance_factor = TreeBalanceFactor(node); ++ if (balance_factor > 1) { ++ if (TreeBalanceFactor(node->left_) > 0) { ++ return TreeRotateRight(node, node_p); ++ } else { ++ return TreeRotateLeftRight(node, node_p); ++ } ++ } else if (balance_factor < -1) { ++ if (TreeBalanceFactor(node->right_) < 0) { ++ return TreeRotateLeft(node, node_p); ++ } else { ++ return TreeRotateRightLeft(node, node_p); ++ } ++ } ++ return node; ++} ++ ++void* ArenaAddressAllocator::Allocate(uint64_t key) { ++ bool idle_status = false; ++ bool occupied_status = true; ++ while (!meta_->struct_.occupied_.compare_exchange_strong( ++ idle_status, occupied_status)) { ++ // exchange failed, idle_status is set to true. ++ idle_status = false; ++ std::this_thread::sleep_for(std::chrono::microseconds(1000)); ++ } ++ auto node = FindOrInsertNode(meta_->struct_.root_, &(meta_->struct_.root_), ++ nullptr, key); ++ meta_->struct_.occupied_.store(false); ++ if (node == nullptr) { ++ return nullptr; ++ } ++ ++ node->ref_count_.fetch_add(1); ++ ++ return reinterpret_cast( ++ reinterpret_cast(meta_->struct_.base_address_) + ++ meta_->struct_.address_segment_size_ * node->index_); ++} ++ ++void ArenaAddressAllocator::Deallocate(uint64_t key) { ++ bool idle_status = false; ++ bool occupied_status = true; ++ while (!meta_->struct_.occupied_.compare_exchange_strong( ++ idle_status, occupied_status)) { ++ // exchange failed, idle_status is set to true. ++ idle_status = false; ++ std::this_thread::sleep_for(std::chrono::microseconds(1000)); ++ } ++ auto node = FindNode(meta_->struct_.root_, key); ++ meta_->struct_.occupied_.store(false); ++ if (node == nullptr) { ++ return; ++ } ++ ++ if (node->ref_count_.fetch_sub(1) == 0) { ++ RemoveNode(meta_->struct_.root_, &(meta_->struct_.root_), key); ++ } ++} ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/shm/arena_address_allocator.h b/cyber/transport/shm/arena_address_allocator.h +new file mode 100644 +index 0000000..7ddc3c1 +--- /dev/null ++++ b/cyber/transport/shm/arena_address_allocator.h +@@ -0,0 +1,121 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_TRANSPORT_SHM_ARENA_ADDRESS_ALLOCATOR_H_ ++#define CYBER_TRANSPORT_SHM_ARENA_ADDRESS_ALLOCATOR_H_ ++ ++#include ++#include ++ ++#include "cyber/base/pthread_rw_lock.h" ++#include "cyber/common/macros.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++struct ArenaAddressNode { ++ uint64_t key_; ++ uint64_t index_; ++ std::atomic ref_count_; ++ struct ArenaAddressNode* parent_; ++ struct ArenaAddressNode* left_; ++ struct ArenaAddressNode* right_; ++}; ++ ++union ArenaAddressAllocatorMeta { ++ struct { ++ uint64_t version_; ++ uint64_t capacity_; ++ std::atomic ref_count_; ++ void* base_address_; ++ // TODO(ALL): support multiple size ++ uint64_t address_segment_size_; ++ ArenaAddressNode* root_; ++ uint64_t allocated_index_; ++ uint64_t reclaim_stack_top_; ++ // base::PthreadRWLock mutex_; ++ std::atomic occupied_; ++ } struct_; ++ uint8_t bytes_[128]; ++}; ++ ++class ArenaAddressAllocator { ++ public: ++ ArenaAddressAllocator(); ++ ~ArenaAddressAllocator(); ++ ++ bool Init(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size); ++ ++ bool OpenOrCreate(uint64_t key, uint64_t size, void* base_address, ++ void** shm_address, bool* is_created); ++ bool Open(uint64_t key, void* base_address, void** shm_address); ++ ++ bool OpenOrCreate(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size); ++ ++ bool OpenMetaShm(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size); ++ ++ bool OpenNodeShm(uint64_t capacity, void* base_address, ++ uint64_t address_segment_size); ++ ++ ArenaAddressNode* NewNode(uint64_t key); ++ void ReclaimNode(ArenaAddressNode* node); ++ ArenaAddressNode* FindNode(ArenaAddressNode* node, uint64_t key); ++ ArenaAddressNode* FindOrInsertNode(ArenaAddressNode* node, ++ ArenaAddressNode** node_p, ++ ArenaAddressNode* parent, uint64_t key); ++ void RemoveNode(ArenaAddressNode* node, ArenaAddressNode** node_addr, ++ uint64_t key); ++ void SwapNodePosition(ArenaAddressNode* x, ArenaAddressNode** x_p, ++ ArenaAddressNode* y, ArenaAddressNode** y_p); ++ uint64_t TreeHeight(ArenaAddressNode* node); ++ ArenaAddressNode* TreeMax(ArenaAddressNode* node, ++ ArenaAddressNode*** node_pp); ++ ArenaAddressNode* TreeMin(ArenaAddressNode* node, ++ ArenaAddressNode*** node_pp); ++ int64_t TreeBalanceFactor(ArenaAddressNode* node); ++ ArenaAddressNode* TreeRebalance(ArenaAddressNode* node, ++ ArenaAddressNode** node_p); ++ ArenaAddressNode* TreeRotateLeft(ArenaAddressNode* node, ++ ArenaAddressNode** node_p); ++ ArenaAddressNode* TreeRotateRight(ArenaAddressNode* node, ++ ArenaAddressNode** node_p); ++ ArenaAddressNode* TreeRotateLeftRight(ArenaAddressNode* node, ++ ArenaAddressNode** node_p); ++ ArenaAddressNode* TreeRotateRightLeft(ArenaAddressNode* node, ++ ArenaAddressNode** node_p); ++ void* Allocate(uint64_t key); ++ void Deallocate(uint64_t key); ++ ++ private: ++ uint64_t meta_shm_key_; ++ uint64_t node_shm_key_; ++ void* meta_shm_address_; ++ void* node_shm_address_; ++ ArenaAddressAllocatorMeta* meta_; ++ ArenaAddressNode* nodes_; ++ ArenaAddressNode* root_; ++ uint64_t* reclaim_stack_; ++ // DECLARE_SINGLETON(ArenaAddressAllocator) ++}; ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif +diff --git a/cyber/transport/shm/posix_segment.cc b/cyber/transport/shm/posix_segment.cc +index c1519ed..d9d963b 100644 +--- a/cyber/transport/shm/posix_segment.cc ++++ b/cyber/transport/shm/posix_segment.cc +@@ -96,13 +96,28 @@ bool PosixSegment::OpenOrCreate() { + return false; + } + ++ // create field arena_blocks_ ++ arena_blocks_ = new (static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block)) Block[ ++ ShmConf::ARENA_BLOCK_NUM]; ++ if (arena_blocks_ == nullptr) { ++ AERROR << "create blocks failed."; ++ state_->~State(); ++ state_ = nullptr; ++ munmap(managed_shm_, conf_.managed_shm_size()); ++ managed_shm_ = nullptr; ++ shm_unlink(shm_name_.c_str()); ++ return false; ++ } ++ + // create block buf + uint32_t i = 0; + for (; i < conf_.block_num(); ++i) { + uint8_t* addr = +- new (static_cast(managed_shm_) + sizeof(State) + +- conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()) +- uint8_t[conf_.block_buf_size()]; ++ new (static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + \ ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ ++ i * conf_.block_buf_size()) uint8_t[conf_.block_buf_size()]; + + if (addr == nullptr) { + break; +@@ -112,15 +127,38 @@ bool PosixSegment::OpenOrCreate() { + block_buf_addrs_[i] = addr; + } + +- if (i != conf_.block_num()) { +- AERROR << "create block buf failed."; ++ // create arena block buf ++ uint32_t ai = 0; ++ for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { ++ uint8_t* addr = \ ++ new(static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + \ ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ ++ conf_.block_num() * conf_.block_buf_size() + \ ++ ai * ShmConf::ARENA_MESSAGE_SIZE) uint8_t[ ++ ShmConf::ARENA_MESSAGE_SIZE]; ++ if (addr == nullptr) { ++ break; ++ } ++ ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_[ai] = addr; ++ } ++ ++ if (ai != ShmConf::ARENA_BLOCK_NUM || i != conf_.block_num()) { ++ AERROR << "create arena block buf failed."; + state_->~State(); + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard lg(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard lg(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + munmap(managed_shm_, conf_.managed_shm_size()); + managed_shm_ = nullptr; + shm_unlink(shm_name_.c_str()); +@@ -183,26 +221,64 @@ bool PosixSegment::OpenOnly() { + return false; + } + ++ // get field arena_blocks_ ++ arena_blocks_ = reinterpret_cast( ++ static_cast(managed_shm_) + sizeof(State) + ++ sizeof(Block) * conf_.block_num()); ++ if (blocks_ == nullptr) { ++ AERROR << "get arena blocks failed."; ++ state_ = nullptr; ++ munmap(managed_shm_, conf_.managed_shm_size()); ++ managed_shm_ = nullptr; ++ return false; ++ } ++ + // get block buf + uint32_t i = 0; + for (; i < conf_.block_num(); ++i) { + uint8_t* addr = reinterpret_cast( + static_cast(managed_shm_) + sizeof(State) + +- conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()); ++ conf_.block_num() * sizeof(Block) + ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + ++ i * conf_.block_buf_size()); + ++ if (addr == nullptr) { ++ break; ++ } + std::lock_guard lg(block_buf_lock_); + block_buf_addrs_[i] = addr; + } + +- if (i != conf_.block_num()) { ++ // get arena block buf ++ uint32_t ai = 0; ++ for (; i < ShmConf::ARENA_BLOCK_NUM; ++ai) { ++ uint8_t* addr = reinterpret_cast( ++ static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + ShmConf::ARENA_BLOCK_NUM * \ ++ sizeof(Block) + conf_.block_num() * conf_.block_buf_size() + \ ++ ai * ShmConf::ARENA_MESSAGE_SIZE); ++ ++ if (addr == nullptr) { ++ break; ++ } ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_[ai] = addr; ++ } ++ ++ if (i != conf_.block_num() || ai != ShmConf::ARENA_BLOCK_NUM) { + AERROR << "open only failed."; + state_->~State(); + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard lg(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard lg(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + munmap(managed_shm_, conf_.managed_shm_size()); + managed_shm_ = nullptr; + shm_unlink(shm_name_.c_str()); +@@ -226,10 +302,15 @@ bool PosixSegment::Remove() { + void PosixSegment::Reset() { + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard lg(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard lg(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + if (managed_shm_ != nullptr) { + munmap(managed_shm_, conf_.managed_shm_size()); + managed_shm_ = nullptr; +diff --git a/cyber/transport/shm/protobuf_arena_manager.cc b/cyber/transport/shm/protobuf_arena_manager.cc +new file mode 100644 +index 0000000..30db9b7 +--- /dev/null ++++ b/cyber/transport/shm/protobuf_arena_manager.cc +@@ -0,0 +1,564 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#include "cyber/transport/shm/protobuf_arena_manager.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "cyber/transport/shm/segment_factory.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++const int32_t ArenaSegmentBlock::kRWLockFree = 0; ++const int32_t ArenaSegmentBlock::kWriteExclusive = -1; ++const int32_t ArenaSegmentBlock::kMaxTryLockTimes = 5; ++ ++ArenaSegment::ArenaSegment() ++ : channel_id_(0), key_id_(0), base_address_(nullptr) {} ++ ++ArenaSegment::ArenaSegment(uint64_t channel_id) ++ : channel_id_(channel_id), ++ key_id_(std::hash{}("/apollo/__arena__/" + ++ std::to_string(channel_id))) {} ++ ++ArenaSegment::ArenaSegment(uint64_t channel_id, void* base_address) ++ : channel_id_(channel_id), ++ key_id_(std::hash{}("/apollo/__arena__/" + ++ std::to_string(channel_id))), ++ base_address_(base_address) {} ++ ++ArenaSegment::ArenaSegment(uint64_t channel_id, uint64_t message_size, ++ uint64_t block_num, void* base_address) ++ : channel_id_(channel_id), ++ key_id_(std::hash{}("/apollo/__arena__/" + ++ std::to_string(channel_id))), ++ base_address_(base_address) { ++ Init(message_size, block_num); ++} ++ ++ArenaSegment::~ArenaSegment() {} ++ ++bool ArenaSegment::Init(uint64_t message_size, uint64_t block_num) { ++ uint64_t key_id = std::hash{}("/apollo/__arena__/" + ++ std::to_string(channel_id_)); ++ // fprintf(stderr, "channel_id: %lx, key_id: %lx\n", channel_id_, key_id); ++ ++ for (uint32_t retry = 0; retry < 2 && !OpenOrCreate(message_size, block_num); ++ ++retry) { ++ } ++ ++ return true; ++} ++ ++bool ArenaSegment::OpenOrCreate(uint64_t message_size, uint64_t block_num) { ++ auto arena_conf = ++ cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id_); ++ auto shared_buffer_size = arena_conf.shared_buffer_size(); ++ auto size = sizeof(ArenaSegmentState) + ++ sizeof(ArenaSegmentBlockDescriptor) * block_num + ++ message_size * block_num + shared_buffer_size; ++ auto shmid = ++ shmget(static_cast(key_id_), size, 0644 | IPC_CREAT | IPC_EXCL); ++ if (shmid == -1) { ++ if (errno == EINVAL) { ++ // TODO(all): need larger space, recreate ++ } else if (errno == EEXIST) { ++ // TODO(all): shm already exist, open only ++ return Open(message_size, block_num); ++ } else { ++ // create or open shm failed ++ return false; ++ } ++ } ++ message_capacity_ = message_size; ++ shm_address_ = shmat(shmid, base_address_, 0); ++ if (shm_address_ == reinterpret_cast(-1)) { ++ // shmat failed ++ return false; ++ } ++ ++ arenas_.resize(block_num, nullptr); ++ if (shared_buffer_size == 0) { ++ shared_buffer_arena_ = nullptr; ++ } else { ++ google::protobuf::ArenaOptions options; ++ options.start_block_size = shared_buffer_size; ++ options.max_block_size = shared_buffer_size; ++ options.initial_block = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + block_num * message_size); ++ options.initial_block_size = shared_buffer_size; ++ shared_buffer_arena_ = std::make_shared(options); ++ } ++ for (size_t i = 0; i < block_num; i++) { ++ arena_block_address_.push_back( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + i * message_size); ++ } ++ ++ state_ = reinterpret_cast(shm_address_); ++ state_->struct_.ref_count_.store(1); ++ state_->struct_.auto_extended_.store(false); ++ state_->struct_.message_size_.store(message_size); ++ state_->struct_.block_num_.store(block_num); ++ state_->struct_.message_seq_.store(0); ++ blocks_ = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState)); ++ for (uint64_t i = 0; i < block_num; ++i) { ++ blocks_[i].size_ = message_size; ++ // blocks_[i].writing_ref_count_.store(0); ++ // blocks_[i].reading_ref_count_.store(0); ++ blocks_[i].lock_num_.store(0); ++ } ++ return true; ++} ++ ++bool ArenaSegment::Open(uint64_t message_size, uint64_t block_num) { ++ auto arena_conf = ++ cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id_); ++ auto shared_buffer_size = arena_conf.shared_buffer_size(); ++ auto shmid = shmget(static_cast(key_id_), 0, 0644); ++ if (shmid == -1) { ++ // shm not exist ++ return false; ++ } ++ shm_address_ = shmat(shmid, base_address_, 0); ++ if (shm_address_ == reinterpret_cast(-1)) { ++ // shmat failed ++ return false; ++ } ++ message_capacity_ = message_size; ++ state_ = reinterpret_cast(shm_address_); ++ state_->struct_.ref_count_.fetch_add(1); ++ blocks_ = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState)); ++ ++ arenas_.resize(block_num, nullptr); ++ if (shared_buffer_size == 0) { ++ shared_buffer_arena_ = nullptr; ++ } else { ++ google::protobuf::ArenaOptions options; ++ options.start_block_size = shared_buffer_size; ++ options.max_block_size = shared_buffer_size; ++ options.initial_block = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + block_num * message_size); ++ options.initial_block_size = shared_buffer_size; ++ shared_buffer_arena_ = std::make_shared(options); ++ } ++ for (size_t i = 0; i < block_num; i++) { ++ arena_block_address_.push_back( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + i * message_size); ++ } ++ return true; ++} ++ ++void* ArenaSegment::GetShmAddress() { return shm_address_; } ++ ++uint64_t ArenaSegment::GetNextWritableBlockIndex() { ++ const auto block_num = state_->struct_.block_num_.load(); ++ while (1) { ++ uint64_t next_idx = state_->struct_.message_seq_.fetch_add(1) % block_num; ++ if (AddBlockWriteLock(next_idx)) { ++ return next_idx; ++ } ++ } ++ return 0; ++} ++ ++bool ArenaSegment::AddBlockWriteLock(uint64_t block_index) { ++ // base::WriteLockGuard lock( ++ // blocks_[block_index].read_write_mutex_); ++ // if (blocks_[block_index].writing_ref_count_.load() > 0) { ++ // return false; ++ // } ++ // if (blocks_[block_index].reading_ref_count_.load() > 0) { ++ // return false; ++ // } ++ // blocks_[block_index].writing_ref_count_.fetch_add(1); ++ auto& block = blocks_[block_index]; ++ int32_t rw_lock_free = ArenaSegmentBlock::kRWLockFree; ++ if (!block.lock_num_.compare_exchange_weak( ++ rw_lock_free, ArenaSegmentBlock::kWriteExclusive, ++ std::memory_order_acq_rel, std::memory_order_relaxed)) { ++ ADEBUG << "lock num: " << block.lock_num_.load(); ++ return false; ++ } ++ return true; ++} ++ ++void ArenaSegment::RemoveBlockWriteLock(uint64_t block_index) { ++ blocks_[block_index].lock_num_.fetch_add(1); ++} ++ ++bool ArenaSegment::AddBlockReadLock(uint64_t block_index) { ++ // when multiple readers are reading an arena channel ++ // at the same time, using write locks can cause one ++ // or more readers to hang at the lock, whereas ++ // read locks do not have this problem ++ // base::ReadLockGuard lock( ++ // blocks_[block_index].read_write_mutex_); ++ // if (blocks_[block_index].writing_ref_count_.load() > 0) { ++ // return false; ++ // } ++ // blocks_[block_index].reading_ref_count_.fetch_add(1); ++ auto& block = blocks_[block_index]; ++ int32_t lock_num = block.lock_num_.load(); ++ if (lock_num < ArenaSegmentBlock::kRWLockFree) { ++ AINFO << "block is being written."; ++ return false; ++ } ++ ++ int32_t try_times = 0; ++ while (!block.lock_num_.compare_exchange_weak(lock_num, lock_num + 1, ++ std::memory_order_acq_rel, ++ std::memory_order_relaxed)) { ++ ++try_times; ++ if (try_times == ArenaSegmentBlock::kMaxTryLockTimes) { ++ AINFO << "fail to add read lock num, curr num: " << lock_num; ++ return false; ++ } ++ ++ lock_num = block.lock_num_.load(); ++ if (lock_num < ArenaSegmentBlock::kRWLockFree) { ++ AINFO << "block is being written."; ++ return false; ++ } ++ } ++ return true; ++} ++ ++void ArenaSegment::RemoveBlockReadLock(uint64_t block_index) { ++ blocks_[block_index].lock_num_.fetch_sub(1); ++} ++ ++bool ArenaSegment::AcquireBlockToWrite(uint64_t size, ++ ArenaSegmentBlockInfo* block_info) { ++ if (!block_info) { ++ return false; ++ } ++ if (!state_ || !blocks_) { ++ return false; ++ } ++ ++ // TODO(all): support dynamic block size ++ ++ uint64_t block_num = state_->struct_.block_num_.load(); ++ uint64_t block_size = state_->struct_.message_size_.load(); ++ uint64_t block_index = GetNextWritableBlockIndex(); ++ block_info->block_index_ = block_index; ++ block_info->block_ = &blocks_[block_index]; ++ block_info->block_buffer_address_ = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + block_index * block_size); ++ return true; ++} ++ ++void ArenaSegment::ReleaseWrittenBlock( ++ const ArenaSegmentBlockInfo& block_info) { ++ if (!state_ || !blocks_) { ++ return; ++ } ++ if (block_info.block_index_ >= state_->struct_.block_num_.load()) { ++ return; ++ } ++ RemoveBlockWriteLock(block_info.block_index_); ++} ++ ++bool ArenaSegment::AcquireBlockToRead(ArenaSegmentBlockInfo* block_info) { ++ if (!block_info) { ++ return false; ++ } ++ if (!state_ || !blocks_) { ++ return false; ++ } ++ ++ if (block_info->block_index_ >= state_->struct_.block_num_.load()) { ++ return false; ++ } ++ ++ // TODO(all): support dynamic block size ++ ++ if (!AddBlockReadLock(block_info->block_index_)) { ++ return false; ++ } ++ uint64_t block_num = state_->struct_.block_num_.load(); ++ uint64_t block_size = state_->struct_.message_size_.load(); ++ ++ block_info->block_ = &blocks_[block_info->block_index_]; ++ block_info->block_buffer_address_ = reinterpret_cast( ++ reinterpret_cast(shm_address_) + sizeof(ArenaSegmentState) + ++ block_num * sizeof(ArenaSegmentBlock) + ++ block_info->block_index_ * block_size); ++ return true; ++} ++ ++void ArenaSegment::ReleaseReadBlock(const ArenaSegmentBlockInfo& block_info) { ++ if (!state_ || !blocks_) { ++ return; ++ } ++ if (block_info.block_index_ >= state_->struct_.block_num_.load()) { ++ return; ++ } ++ RemoveBlockReadLock(block_info.block_index_); ++} ++ ++ProtobufArenaManager::ProtobufArenaManager() { ++ address_allocator_ = std::make_shared(); ++} ++ ++ProtobufArenaManager::~ProtobufArenaManager() { Destroy(); } ++ ++uint64_t ProtobufArenaManager::GetBaseAddress( ++ const message::ArenaMessageWrapper* wrapper) { ++ return 0; ++} ++ ++std::shared_ptr ProtobufArenaManager::GetSegment( ++ uint64_t channel_id) { ++ std::lock_guard lock(segments_mutex_); ++ if (segments_.find(channel_id) == segments_.end()) { ++ return nullptr; ++ } ++ return segments_[channel_id]; ++} ++ ++void* ProtobufArenaManager::SetMessage(message::ArenaMessageWrapper* wrapper, ++ const void* message) { ++ auto input_msg = reinterpret_cast(message); ++ auto channel_id = GetMessageChannelId(wrapper); ++ auto segment = GetSegment(channel_id); ++ auto arena_ptr = input_msg->GetArena(); ++ google::protobuf::ArenaOptions options; ++ ++ if (!segment) { ++ return nullptr; ++ } ++ ++ void* msg_output = nullptr; ++ if (arena_ptr == nullptr) { ++ auto arena_conf = ++ cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); ++ google::protobuf::ArenaOptions options; ++ options.start_block_size = arena_conf.max_msg_size(); ++ options.max_block_size = arena_conf.max_msg_size(); ++ ++ if (!segment) { ++ return nullptr; ++ } ++ ++ ResetMessageRelatedBlocks(wrapper); ++ ++ ArenaSegmentBlockInfo wb; ++ // TODO(all): AcquireBlockToWrite for dynamic adjust block ++ // auto size = input_msg->ByteSizeLong(); ++ uint64_t size = 0; ++ if (!segment->AcquireBlockToWrite(size, &wb)) { ++ return nullptr; ++ } ++ this->AddMessageRelatedBlock(wrapper, wb.block_index_); ++ options.initial_block = ++ reinterpret_cast(segment->arena_block_address_[wb.block_index_]); ++ options.initial_block_size = segment->message_capacity_; ++ if (segment->arenas_[wb.block_index_] != nullptr) { ++ segment->arenas_[wb.block_index_] = nullptr; ++ } ++ segment->arenas_[wb.block_index_] = ++ std::make_shared(options); ++ auto msg = input_msg->New(segment->arenas_[wb.block_index_].get()); ++ msg->CopyFrom(*input_msg); ++ SetMessageAddressOffset( ++ wrapper, reinterpret_cast(msg) - ++ reinterpret_cast(segment->GetShmAddress())); ++ msg_output = reinterpret_cast(msg); ++ segment->ReleaseWrittenBlock(wb); ++ } else { ++ ArenaSegmentBlockInfo wb; ++ int block_index = -1; ++ for (size_t i = 0; i < segment->message_capacity_; i++) { ++ if (segment->arenas_[i].get() == arena_ptr) { ++ block_index = i; ++ break; ++ } ++ } ++ if (block_index == -1) { ++ return nullptr; ++ } ++ wb.block_index_ = block_index; ++ ResetMessageRelatedBlocks(wrapper); ++ this->AddMessageRelatedBlock(wrapper, block_index); ++ SetMessageAddressOffset( ++ wrapper, reinterpret_cast(input_msg) - ++ reinterpret_cast(segment->GetShmAddress())); ++ msg_output = reinterpret_cast( ++ const_cast(input_msg)); ++ segment->ReleaseWrittenBlock(wb); ++ } ++ ++ return msg_output; ++} ++ ++void* ProtobufArenaManager::GetMessage(message::ArenaMessageWrapper* wrapper) { ++ auto segment = GetSegment(GetMessageChannelId(wrapper)); ++ if (!segment) { ++ return nullptr; ++ } ++ ++ auto address = reinterpret_cast(segment->GetShmAddress()) + ++ GetMessageAddressOffset(wrapper); ++ ++ return reinterpret_cast(address); ++} ++ ++bool ProtobufArenaManager::Enable() { ++ if (init_) { ++ return true; ++ } ++ ++ // do something ++ ++ init_ = true; ++ return true; ++} ++ ++bool ProtobufArenaManager::EnableSegment(uint64_t channel_id) { ++ if (segments_.find(channel_id) != segments_.end()) { ++ if (arena_buffer_callbacks_.find(channel_id) != ++ arena_buffer_callbacks_.end()) { ++ arena_buffer_callbacks_[channel_id](); ++ } ++ return true; ++ } ++ ++ // uint64_t asociated_channel_id = channel_id + 1; ++ // auto segment = SegmentFactory::CreateSegment(asociated_channel_id); ++ // segment->InitOnly(10 * 1024); ++ auto cyber_config = apollo::cyber::common::GlobalData::Instance()->Config(); ++ if (!cyber_config.has_transport_conf()) { ++ return false; ++ } ++ if (!cyber_config.transport_conf().has_shm_conf()) { ++ return false; ++ } ++ if (!cyber_config.transport_conf().shm_conf().has_arena_shm_conf()) { ++ return false; ++ } ++ if (!cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ channel_id)) { ++ return false; ++ } ++ auto arena_conf = ++ cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); ++ auto segment_shm_address = address_allocator_->Allocate(channel_id); ++ auto segment = std::make_shared( ++ channel_id, arena_conf.max_msg_size(), arena_conf.max_pool_size(), ++ reinterpret_cast(segment_shm_address)); ++ segments_[channel_id] = segment; ++ if (arena_buffer_callbacks_.find(channel_id) != ++ arena_buffer_callbacks_.end()) { ++ arena_buffer_callbacks_[channel_id](); ++ } ++ return true; ++} ++ ++bool ProtobufArenaManager::Destroy() { ++ if (!init_) { ++ return true; ++ } ++ ++ for (auto& segment : segments_) { ++ address_allocator_->Deallocate(segment.first); ++ } ++ for (auto& buffer : non_arena_buffers_) { ++ delete buffer.second; ++ } ++ segments_.clear(); ++ ++ init_ = false; ++ return true; ++} ++ ++void ProtobufArenaManager::SetMessageChannelId( ++ message::ArenaMessageWrapper* wrapper, uint64_t channel_id) { ++ wrapper->GetExtended()->meta_.channel_id_ = channel_id; ++} ++ ++uint64_t ProtobufArenaManager::GetMessageChannelId( ++ message::ArenaMessageWrapper* wrapper) { ++ return wrapper->GetExtended()->meta_.channel_id_; ++} ++ ++void ProtobufArenaManager::SetMessageAddressOffset( ++ message::ArenaMessageWrapper* wrapper, uint64_t address_offset) { ++ wrapper->GetExtended()->meta_.address_offset_ = ++ address_offset; ++} ++ ++uint64_t ProtobufArenaManager::GetMessageAddressOffset( ++ message::ArenaMessageWrapper* wrapper) { ++ return wrapper->GetExtended()->meta_.address_offset_; ++} ++ ++std::vector ProtobufArenaManager::GetMessageRelatedBlocks( ++ message::ArenaMessageWrapper* wrapper) { ++ std::vector related_blocks; ++ auto extended = wrapper->GetExtended(); ++ for (uint64_t i = 0; i < extended->meta_.related_blocks_size_; ++i) { ++ related_blocks.push_back(extended->meta_.related_blocks_[i]); ++ } ++ return related_blocks; ++} ++ ++void ProtobufArenaManager::ResetMessageRelatedBlocks( ++ message::ArenaMessageWrapper* wrapper) { ++ auto extended = wrapper->GetExtended(); ++ extended->meta_.related_blocks_size_ = 0; ++ // memset(extended->meta_.related_blocks_, 0, ++ // sizeof(extended->meta_.related_blocks_)); ++} ++ ++void ProtobufArenaManager::AddMessageRelatedBlock( ++ message::ArenaMessageWrapper* wrapper, uint64_t block_index) { ++ auto extended = wrapper->GetExtended(); ++ if (extended->meta_.related_blocks_size_ >= ++ sizeof(extended->meta_.related_blocks_) / sizeof(uint64_t)) { ++ return; ++ } ++ extended->meta_.related_blocks_[extended->meta_.related_blocks_size_++] = ++ block_index; ++} ++ ++ProtobufArenaManager::ArenaAllocCallback ProtobufArenaManager::arena_alloc_cb_ = ++ nullptr; ++ ++void* ProtobufArenaManager::ArenaAlloc(uint64_t size) { ++ return arena_alloc_cb_ ? arena_alloc_cb_(size) : nullptr; ++} ++ ++void ProtobufArenaManager::ArenaDealloc(void* addr, uint64_t size) {} ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo +diff --git a/cyber/transport/shm/protobuf_arena_manager.h b/cyber/transport/shm/protobuf_arena_manager.h +new file mode 100644 +index 0000000..d250ccc +--- /dev/null ++++ b/cyber/transport/shm/protobuf_arena_manager.h +@@ -0,0 +1,319 @@ ++/****************************************************************************** ++ * Copyright 2024 The Apollo Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ *****************************************************************************/ ++#ifndef CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_ ++#define CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "cyber/base/arena_queue.h" ++#include "cyber/base/pthread_rw_lock.h" ++#include "cyber/common/global_data.h" ++#include "cyber/common/macros.h" ++#include "cyber/message/arena_manager_base.h" ++#include "cyber/message/arena_message_wrapper.h" ++#include "cyber/transport/shm/arena_address_allocator.h" ++#include "cyber/transport/shm/segment.h" ++ ++namespace apollo { ++namespace cyber { ++namespace transport { ++ ++union ArenaSegmentState { ++ struct { ++ std::atomic ref_count_; ++ std::atomic auto_extended_; ++ std::atomic message_size_; ++ std::atomic block_num_; ++ std::atomic message_seq_; ++ std::mutex mutex_; ++ } struct_; ++ uint8_t bytes_[128]; ++}; ++ ++union ArenaSegmentBlockDescriptor { ++ struct { ++ uint64_t size_; ++ std::atomic writing_ref_count_; ++ std::atomic reading_ref_count_; ++ base::PthreadRWLock read_write_mutex_; ++ } struct_; ++ uint8_t bytes_[128]; ++}; ++ ++struct ArenaSegmentBlock { ++ uint64_t size_; ++ // std::atomic writing_ref_count_; ++ // std::atomic reading_ref_count_; ++ // base::PthreadRWLock read_write_mutex_; ++ static const int32_t kRWLockFree; ++ static const int32_t kWriteExclusive; ++ static const int32_t kMaxTryLockTimes; ++ std::atomic lock_num_ = {0}; ++}; ++ ++struct ArenaSegmentBlockInfo { ++ uint64_t block_index_; ++ ArenaSegmentBlock* block_; ++ void* block_buffer_address_; ++}; ++ ++class ArenaSegment { ++ public: ++ ArenaSegment(); ++ explicit ArenaSegment(uint64_t channel_id); ++ ArenaSegment(uint64_t channel_id, void* base_address); ++ ArenaSegment(uint64_t channel_id, uint64_t message_size, uint64_t block_num, ++ void* base_address); ++ ~ArenaSegment(); ++ ++ bool Init(uint64_t message_size, uint64_t block_num); ++ // bool Create(uint64_t message_size, uint64_t block_num); ++ bool Open(uint64_t message_size, uint64_t block_num); ++ bool OpenOrCreate(uint64_t message_size, uint64_t block_num); ++ ++ void* GetShmAddress(); ++ ++ uint64_t GetNextWritableBlockIndex(); ++ bool AddBlockWriteLock(uint64_t block_index); ++ void RemoveBlockWriteLock(uint64_t block_index); ++ bool AddBlockReadLock(uint64_t block_index); ++ void RemoveBlockReadLock(uint64_t block_index); ++ ++ bool AcquireBlockToWrite(uint64_t size, ArenaSegmentBlockInfo* block_info); ++ void ReleaseWrittenBlock(const ArenaSegmentBlockInfo& block_info); ++ ++ bool AcquireBlockToRead(ArenaSegmentBlockInfo* block_info); ++ void ReleaseReadBlock(const ArenaSegmentBlockInfo& block_info); ++ ++ // uint64_t GetCapicity(); ++ ++ public: ++ ArenaSegmentState* state_; ++ ArenaSegmentBlock* blocks_; ++ std::vector> arenas_; ++ std::vector arena_block_address_; ++ uint64_t channel_id_; ++ uint64_t key_id_; ++ void* base_address_; ++ void* shm_address_; ++ std::shared_ptr shared_buffer_arena_; ++ void* arena_buffer_address_ = nullptr; ++ ++ uint64_t message_capacity_; ++}; ++ ++union ExtendedStruct { ++ struct { ++ uint64_t channel_id_; ++ uint64_t address_offset_; ++ uint64_t related_blocks_[4]; ++ uint64_t related_blocks_size_ = 0; ++ } meta_; ++ uint8_t bytes_[256]; ++}; ++ ++union ProtobufArenaManagerMeta { ++ struct { ++ uint64_t version_; ++ uint64_t base_address_; ++ uint64_t segment_size_; ++ uint64_t block_size_; ++ uint64_t block_num_; ++ uint64_t message_size_; ++ uint64_t message_num_; ++ uint64_t message_seq_; ++ uint64_t extended_struct_size_; ++ uint64_t extended_struct_num_; ++ uint64_t extended_struct_seq_; ++ } struct_; ++ uint8_t bytes_[256]; ++}; ++ ++class ProtobufArenaManager : public message::ArenaManagerBase { ++ public: ++ using ArenaAllocCallback = std::function; ++ ++ ~ProtobufArenaManager(); ++ ++ uint64_t GetBaseAddress(const message::ArenaMessageWrapper* wrapper) override; ++ ++ bool Enable(); ++ bool EnableSegment(uint64_t channel_id); ++ bool Destroy(); ++ // bool Shutdown(); ++ ++ void SetMessageChannelId(message::ArenaMessageWrapper* wrapper, ++ uint64_t channel_id); ++ uint64_t GetMessageChannelId(message::ArenaMessageWrapper* wrapper); ++ void SetMessageAddressOffset(message::ArenaMessageWrapper* wrapper, ++ uint64_t offset); ++ uint64_t GetMessageAddressOffset(message::ArenaMessageWrapper* wrapper); ++ std::vector GetMessageRelatedBlocks( ++ message::ArenaMessageWrapper* wrapper); ++ void ResetMessageRelatedBlocks(message::ArenaMessageWrapper* wrapper); ++ void AddMessageRelatedBlock(message::ArenaMessageWrapper* wrapper, ++ uint64_t block_index); ++ ++ std::shared_ptr GetSegment(uint64_t channel_id); ++ ++ void* SetMessage(message::ArenaMessageWrapper* wrapper, ++ const void* message) override; ++ void* GetMessage(message::ArenaMessageWrapper* wrapper) override; ++ ++ void* GetAvailableBuffer(uint64_t channel_id) { ++ auto segment = this->GetSegment(channel_id); ++ if (!segment) { ++ if (non_arena_buffers_.find(channel_id) == non_arena_buffers_.end()) { ++ return nullptr; ++ } ++ return non_arena_buffers_[channel_id]; ++ } ++ if (segment->arena_buffer_address_ != nullptr) { ++ return segment->arena_buffer_address_; ++ } ++ return non_arena_buffers_[channel_id]; ++ } ++ ++ template ++ bool RegisterQueue(uint64_t channel_id, uint64_t size) { ++ if (non_arena_buffers_.find(channel_id) == non_arena_buffers_.end() || ++ arena_buffer_callbacks_.find(channel_id) == ++ arena_buffer_callbacks_.end()) { ++ auto non_arena_buffer_ptr = new apollo::cyber::base::ArenaQueue(); ++ non_arena_buffer_ptr->Init(size); ++ non_arena_buffers_[channel_id] = non_arena_buffer_ptr; ++ arena_buffer_callbacks_[channel_id] = [this, channel_id, size]() { ++ auto segment = this->GetSegment(channel_id); ++ if (!segment) { ++ ADEBUG << "channel id '" << channel_id << "' not enable"; ++ ADEBUG << "fallback to use nomarl queue"; ++ return; ++ } ++ if (segment->shared_buffer_arena_ == nullptr) { ++ ADEBUG << "Not enable arena shared buffer in channel id '" ++ << channel_id << "'"; ++ ADEBUG << "fallback to use nomarl queue"; ++ return; ++ } ++ if (segment->arena_buffer_address_ == nullptr) { ++ auto ptr = google::protobuf::Arena::Create>( ++ segment->shared_buffer_arena_.get()); ++ ptr->Init(size, segment->shared_buffer_arena_.get()); ++ segment->arena_buffer_address_ = reinterpret_cast(ptr); ++ } ++ }; ++ } ++ // try enable arena buffer ++ auto segment = GetSegment(channel_id); ++ if (segment) { ++ arena_buffer_callbacks_[channel_id](); ++ } ++ return true; ++ } ++ ++ template ::value, ++ M>::type* = nullptr> ++ void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr& ret_msg) { ++ auto arena_conf = ++ cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id); ++ google::protobuf::ArenaOptions options; ++ options.start_block_size = arena_conf.max_msg_size(); ++ options.max_block_size = arena_conf.max_msg_size(); ++ ++ auto segment = GetSegment(channel_id); ++ if (!segment) { ++ return; ++ } ++ ++ ArenaSegmentBlockInfo wb; ++ // TODO(All): size should be send to ++ // AcquireBlockToWrite for dynamic adjust block size ++ // auto size = input_msg->ByteSizeLong(); ++ uint64_t size = 0; ++ if (!segment->AcquireBlockToWrite(size, &wb)) { ++ return; ++ } ++ options.initial_block = ++ reinterpret_cast(segment->arena_block_address_[wb.block_index_]); ++ options.initial_block_size = segment->message_capacity_; ++ if (segment->arenas_[wb.block_index_] != nullptr) { ++ segment->arenas_[wb.block_index_] = nullptr; ++ } ++ segment->arenas_[wb.block_index_] = ++ std::make_shared(options); ++ ++ // deconstructor do nothing to avoid proto ++ // instance deconstructed before arena allocator ++ ret_msg = std::shared_ptr( ++ google::protobuf::Arena::CreateMessage( ++ segment->arenas_[wb.block_index_].get()), ++ [segment, wb](M* ptr) { ++ int32_t lock_num = segment->blocks_[wb.block_index_].lock_num_.load(); ++ if (lock_num < ArenaSegmentBlock::kRWLockFree) { ++ segment->ReleaseWrittenBlock(wb); ++ } ++ }); ++ return; ++ } ++ ++ template ::value, ++ M>::type* = nullptr> ++ void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr& ret_msg) { ++ return; ++ } ++ ++ private: ++ bool init_; ++ std::unordered_map> segments_; ++ std::unordered_map non_arena_buffers_; ++ std::unordered_map> arena_buffer_callbacks_; ++ std::mutex segments_mutex_; ++ ++ std::shared_ptr address_allocator_; ++ ++ static ArenaAllocCallback arena_alloc_cb_; ++ static void* ArenaAlloc(uint64_t size); ++ static void ArenaDealloc(void* addr, uint64_t size); ++ ++ std::mutex arena_alloc_cb_mutex_; ++ ++ std::unordered_map managed_wrappers_; ++ ++ DECLARE_SINGLETON(ProtobufArenaManager) ++}; ++ ++// template ++// std::shared_ptr ProtobufArenaManager::CreateMessage( ++// message::ArenaMessageWrapper* wrapper, const MessageT& message) {} ++ ++// template ++// std::shared_ptr ProtobufArenaManager::LoadMessage( ++// message::ArenaMessageWrapper* wrapper) {} ++ ++} // namespace transport ++} // namespace cyber ++} // namespace apollo ++ ++#endif +diff --git a/cyber/transport/shm/readable_info.cc b/cyber/transport/shm/readable_info.cc +index 605da79..5f7c332 100644 +--- a/cyber/transport/shm/readable_info.cc ++++ b/cyber/transport/shm/readable_info.cc +@@ -24,13 +24,21 @@ namespace apollo { + namespace cyber { + namespace transport { + +-const size_t ReadableInfo::kSize = sizeof(uint64_t) * 2 + sizeof(uint32_t); +- +-ReadableInfo::ReadableInfo() : host_id_(0), block_index_(0), channel_id_(0) {} +- +-ReadableInfo::ReadableInfo(uint64_t host_id, uint32_t block_index, +- uint64_t channel_id) +- : host_id_(host_id), block_index_(block_index), channel_id_(channel_id) {} ++const size_t ReadableInfo::kSize = sizeof(uint64_t) * 2 + \ ++ sizeof(int32_t) + sizeof(int32_t); ++ ++ReadableInfo::ReadableInfo() ++ : host_id_(0), ++ block_index_(0), ++ arena_block_index_(-1), ++ channel_id_(0) {} ++ ++ReadableInfo::ReadableInfo(uint64_t host_id, int32_t block_index, ++ uint64_t channel_id, int32_t arena_block_index) ++ : host_id_(host_id), ++ block_index_(block_index), ++ arena_block_index_(arena_block_index), ++ channel_id_(channel_id) {} + + ReadableInfo::~ReadableInfo() {} + +@@ -39,6 +47,7 @@ ReadableInfo& ReadableInfo::operator=(const ReadableInfo& other) { + this->host_id_ = other.host_id_; + this->block_index_ = other.block_index_; + this->channel_id_ = other.channel_id_; ++ this->arena_block_index_ = other.arena_block_index_; + } + return *this; + } +@@ -48,10 +57,12 @@ bool ReadableInfo::SerializeTo(std::string* dst) const { + + dst->assign(reinterpret_cast(const_cast(&host_id_)), + sizeof(host_id_)); +- dst->append(reinterpret_cast(const_cast(&block_index_)), ++ dst->append(reinterpret_cast(const_cast(&block_index_)), + sizeof(block_index_)); + dst->append(reinterpret_cast(const_cast(&channel_id_)), + sizeof(channel_id_)); ++ dst->append(reinterpret_cast(const_cast( ++ &arena_block_index_)), sizeof(arena_block_index_)); + return true; + } + +@@ -72,7 +83,9 @@ bool ReadableInfo::DeserializeFrom(const char* src, std::size_t len) { + memcpy(reinterpret_cast(&block_index_), ptr, sizeof(block_index_)); + ptr += sizeof(block_index_); + memcpy(reinterpret_cast(&channel_id_), ptr, sizeof(channel_id_)); +- ++ ptr += sizeof(channel_id_); ++ memcpy(reinterpret_cast(&arena_block_index_), ++ ptr, sizeof(arena_block_index_)); + return true; + } + +diff --git a/cyber/transport/shm/readable_info.h b/cyber/transport/shm/readable_info.h +index ffeb5c8..06d4e71 100644 +--- a/cyber/transport/shm/readable_info.h ++++ b/cyber/transport/shm/readable_info.h +@@ -32,7 +32,8 @@ using ReadableInfoPtr = std::shared_ptr; + class ReadableInfo { + public: + ReadableInfo(); +- ReadableInfo(uint64_t host_id, uint32_t block_index, uint64_t channel_id); ++ ReadableInfo(uint64_t host_id, int32_t block_index, ++ uint64_t channel_id, int32_t arena_block_index = -1); + virtual ~ReadableInfo(); + + ReadableInfo& operator=(const ReadableInfo& other); +@@ -44,8 +45,12 @@ class ReadableInfo { + uint64_t host_id() const { return host_id_; } + void set_host_id(uint64_t host_id) { host_id_ = host_id; } + +- uint32_t block_index() const { return block_index_; } +- void set_block_index(uint32_t block_index) { block_index_ = block_index; } ++ int32_t block_index() const { return block_index_; } ++ void set_block_index(int32_t block_index) { block_index_ = block_index; } ++ ++ int32_t arena_block_index() const { return arena_block_index_; } ++ void set_arena_block_index( ++ int32_t arena_block_index) { arena_block_index_ = arena_block_index; } + + uint64_t channel_id() const { return channel_id_; } + void set_channel_id(uint64_t channel_id) { channel_id_ = channel_id; } +@@ -54,7 +59,8 @@ class ReadableInfo { + + private: + uint64_t host_id_; +- uint32_t block_index_; ++ int32_t block_index_; ++ int32_t arena_block_index_; + uint64_t channel_id_; + }; + +diff --git a/cyber/transport/shm/segment.cc b/cyber/transport/shm/segment.cc +index 1890e1b..a250f6c 100644 +--- a/cyber/transport/shm/segment.cc ++++ b/cyber/transport/shm/segment.cc +@@ -30,9 +30,12 @@ Segment::Segment(uint64_t channel_id) + channel_id_(channel_id), + state_(nullptr), + blocks_(nullptr), ++ arena_blocks_(nullptr), + managed_shm_(nullptr), + block_buf_lock_(), +- block_buf_addrs_() {} ++ arena_block_buf_lock_(), ++ block_buf_addrs_(), ++ arena_block_buf_addrs_() {} + + bool Segment::AcquireBlockToWrite(std::size_t msg_size, + WritableBlock* writable_block) { +@@ -66,6 +69,25 @@ bool Segment::AcquireBlockToWrite(std::size_t msg_size, + return true; + } + ++bool Segment::AcquireArenaBlockToWrite(std::size_t msg_size, ++ WritableBlock* writable_block) { ++ RETURN_VAL_IF_NULL(writable_block, false); ++ if (!init_ && !OpenOrCreate()) { ++ AERROR << "create shm failed, can't write now."; ++ return false; ++ } ++ ++ if (state_->need_remap()) { ++ Remap(); ++ } ++ ++ uint32_t index = GetNextArenaWritableBlockIndex(); ++ writable_block->index = index; ++ writable_block->block = &arena_blocks_[index]; ++ writable_block->buf = arena_block_buf_addrs_[index]; ++ return true; ++} ++ + void Segment::ReleaseWrittenBlock(const WritableBlock& writable_block) { + auto index = writable_block.index; + if (index >= conf_.block_num()) { +@@ -74,6 +96,14 @@ void Segment::ReleaseWrittenBlock(const WritableBlock& writable_block) { + blocks_[index].ReleaseWriteLock(); + } + ++void Segment::ReleaseArenaWrittenBlock(const WritableBlock& writable_block) { ++ auto index = writable_block.index; ++ if (index >= ShmConf::ARENA_BLOCK_NUM) { ++ return; ++ } ++ arena_blocks_[index].ReleaseWriteLock(); ++} ++ + bool Segment::AcquireBlockToRead(ReadableBlock* readable_block) { + RETURN_VAL_IF_NULL(readable_block, false); + if (!init_ && !OpenOnly()) { +@@ -105,6 +135,45 @@ bool Segment::AcquireBlockToRead(ReadableBlock* readable_block) { + return true; + } + ++bool Segment::AcquireArenaBlockToRead(ReadableBlock* readable_block) { ++ RETURN_VAL_IF_NULL(readable_block, false); ++ if (!init_ && !OpenOnly()) { ++ AERROR << "failed to open shared memory, can't read now."; ++ return false; ++ } ++ ++ auto index = readable_block->index; ++ if (index >= ShmConf::ARENA_BLOCK_NUM) { ++ AERROR << "invalid arena block_index[" << index << "]."; ++ return false; ++ } ++ ++ bool result = true; ++ if (state_->need_remap()) { ++ result = Remap(); ++ } ++ ++ if (!result) { ++ AERROR << "segment update failed."; ++ return false; ++ } ++ ++ if (!arena_blocks_[index].TryLockForRead()) { ++ return false; ++ } ++ readable_block->block = arena_blocks_ + index; ++ readable_block->buf = arena_block_buf_addrs_[index]; ++ return true; ++} ++ ++void Segment::ReleaseArenaReadBlock(const ReadableBlock& readable_block) { ++ auto index = readable_block.index; ++ if (index >= ShmConf::ARENA_BLOCK_NUM) { ++ return; ++ } ++ arena_blocks_[index].ReleaseReadLock(); ++} ++ + void Segment::ReleaseReadBlock(const ReadableBlock& readable_block) { + auto index = readable_block.index; + if (index >= conf_.block_num()) { +@@ -113,6 +182,79 @@ void Segment::ReleaseReadBlock(const ReadableBlock& readable_block) { + blocks_[index].ReleaseReadLock(); + } + ++bool Segment::InitOnly(uint64_t message_size) { ++ if (init_) { ++ return true; ++ } ++ conf_.Update(message_size); ++ if (!OpenOrCreate()) { ++ return false; ++ } ++ return true; ++} ++ ++void* Segment::GetManagedShm() { return managed_shm_; } ++ ++bool Segment::LockBlockForWriteByIndex(uint64_t block_index) { ++ if (block_index >= conf_.block_num()) { ++ return false; ++ } ++ return blocks_[block_index].TryLockForWrite(); ++} ++ ++bool Segment::ReleaseBlockForWriteByIndex(uint64_t block_index) { ++ if (block_index >= conf_.block_num()) { ++ return false; ++ } ++ blocks_[block_index].ReleaseWriteLock(); ++ return true; ++} ++ ++bool Segment::LockBlockForReadByIndex(uint64_t block_index) { ++ if (block_index >= conf_.block_num()) { ++ return false; ++ } ++ return blocks_[block_index].TryLockForRead(); ++} ++ ++bool Segment::ReleaseBlockForReadByIndex(uint64_t block_index) { ++ if (block_index >= conf_.block_num()) { ++ return false; ++ } ++ blocks_[block_index].ReleaseReadLock(); ++ return true; ++} ++ ++bool Segment::LockArenaBlockForWriteByIndex(uint64_t block_index) { ++ if (block_index >= ShmConf::ARENA_BLOCK_NUM) { ++ return false; ++ } ++ return arena_blocks_[block_index].TryLockForWrite(); ++} ++ ++bool Segment::ReleaseArenaBlockForWriteByIndex(uint64_t block_index) { ++ if (block_index >= ShmConf::ARENA_BLOCK_NUM) { ++ return false; ++ } ++ arena_blocks_[block_index].ReleaseWriteLock(); ++ return true; ++} ++ ++bool Segment::LockArenaBlockForReadByIndex(uint64_t block_index) { ++ if (block_index >= ShmConf::ARENA_BLOCK_NUM) { ++ return false; ++ } ++ return arena_blocks_[block_index].TryLockForRead(); ++} ++ ++bool Segment::ReleaseArenaBlockForReadByIndex(uint64_t block_index) { ++ if (block_index >= ShmConf::ARENA_BLOCK_NUM) { ++ return false; ++ } ++ arena_blocks_[block_index].ReleaseReadLock(); ++ return true; ++} ++ + bool Segment::Destroy() { + if (!init_) { + return true; +@@ -161,6 +303,17 @@ uint32_t Segment::GetNextWritableBlockIndex() { + return 0; + } + ++uint32_t Segment::GetNextArenaWritableBlockIndex() { ++ const auto block_num = ShmConf::ARENA_BLOCK_NUM; ++ while (1) { ++ uint32_t try_idx = state_->FetchAddArenaSeq(1) % block_num; ++ if (arena_blocks_[try_idx].TryLockForWrite()) { ++ return try_idx; ++ } ++ } ++ return 0; ++} ++ + } // namespace transport + } // namespace cyber + } // namespace apollo +diff --git a/cyber/transport/shm/segment.h b/cyber/transport/shm/segment.h +index 1adaea6..1e4416b 100644 +--- a/cyber/transport/shm/segment.h ++++ b/cyber/transport/shm/segment.h +@@ -48,9 +48,28 @@ class Segment { + bool AcquireBlockToWrite(std::size_t msg_size, WritableBlock* writable_block); + void ReleaseWrittenBlock(const WritableBlock& writable_block); + ++ bool AcquireArenaBlockToWrite( ++ std::size_t msg_size, WritableBlock* writable_block); ++ void ReleaseArenaWrittenBlock(const WritableBlock& writable_block); ++ + bool AcquireBlockToRead(ReadableBlock* readable_block); + void ReleaseReadBlock(const ReadableBlock& readable_block); + ++ bool AcquireArenaBlockToRead(ReadableBlock* readable_block); ++ void ReleaseArenaReadBlock(const ReadableBlock& readable_block); ++ ++ bool InitOnly(uint64_t message_size); ++ void* GetManagedShm(); ++ bool LockBlockForWriteByIndex(uint64_t block_index); ++ bool ReleaseBlockForWriteByIndex(uint64_t block_index); ++ bool LockBlockForReadByIndex(uint64_t block_index); ++ bool ReleaseBlockForReadByIndex(uint64_t block_index); ++ ++ bool LockArenaBlockForWriteByIndex(uint64_t block_index); ++ bool ReleaseArenaBlockForWriteByIndex(uint64_t block_index); ++ bool LockArenaBlockForReadByIndex(uint64_t block_index); ++ bool ReleaseArenaBlockForReadByIndex(uint64_t block_index); ++ + protected: + virtual bool Destroy(); + virtual void Reset() = 0; +@@ -64,14 +83,18 @@ class Segment { + + State* state_; + Block* blocks_; ++ Block* arena_blocks_; + void* managed_shm_; + std::mutex block_buf_lock_; ++ std::mutex arena_block_buf_lock_; + std::unordered_map block_buf_addrs_; ++ std::unordered_map arena_block_buf_addrs_; + + private: + bool Remap(); + bool Recreate(const uint64_t& msg_size); + uint32_t GetNextWritableBlockIndex(); ++ uint32_t GetNextArenaWritableBlockIndex(); + }; + + } // namespace transport +diff --git a/cyber/transport/shm/shm_conf.cc b/cyber/transport/shm/shm_conf.cc +index e7ffb22..44c780e 100644 +--- a/cyber/transport/shm/shm_conf.cc ++++ b/cyber/transport/shm/shm_conf.cc +@@ -31,8 +31,9 @@ void ShmConf::Update(const uint64_t& real_msg_size) { + ceiling_msg_size_ = GetCeilingMessageSize(real_msg_size); + block_buf_size_ = GetBlockBufSize(ceiling_msg_size_); + block_num_ = GetBlockNum(ceiling_msg_size_); +- managed_shm_size_ = +- EXTRA_SIZE + STATE_SIZE + (BLOCK_SIZE + block_buf_size_) * block_num_; ++ managed_shm_size_ = EXTRA_SIZE + STATE_SIZE + \ ++ (BLOCK_SIZE + block_buf_size_) * block_num_ + \ ++ (BLOCK_SIZE + ARENA_MESSAGE_SIZE) * ARENA_BLOCK_NUM; + } + + const uint64_t ShmConf::EXTRA_SIZE = 1024 * 4; +@@ -40,6 +41,9 @@ const uint64_t ShmConf::STATE_SIZE = 1024; + const uint64_t ShmConf::BLOCK_SIZE = 1024; + const uint64_t ShmConf::MESSAGE_INFO_SIZE = 1024; + ++const uint32_t ShmConf::ARENA_BLOCK_NUM = 512; ++const uint64_t ShmConf::ARENA_MESSAGE_SIZE = 1024; ++ + const uint32_t ShmConf::BLOCK_NUM_16K = 512; + const uint64_t ShmConf::MESSAGE_SIZE_16K = 1024 * 16; + +diff --git a/cyber/transport/shm/shm_conf.h b/cyber/transport/shm/shm_conf.h +index 84f9d16..d230ae1 100644 +--- a/cyber/transport/shm/shm_conf.h ++++ b/cyber/transport/shm/shm_conf.h +@@ -37,6 +37,10 @@ class ShmConf { + const uint32_t& block_num() { return block_num_; } + const uint64_t& managed_shm_size() { return managed_shm_size_; } + ++ // For arena msg ++ static const uint32_t ARENA_BLOCK_NUM; ++ static const uint64_t ARENA_MESSAGE_SIZE; ++ + private: + uint64_t GetCeilingMessageSize(const uint64_t& real_msg_size); + uint64_t GetBlockBufSize(const uint64_t& ceiling_msg_size); +diff --git a/cyber/transport/shm/state.h b/cyber/transport/shm/state.h +index 62da2a9..98cd5d2 100644 +--- a/cyber/transport/shm/state.h ++++ b/cyber/transport/shm/state.h +@@ -46,6 +46,11 @@ class State { + uint32_t FetchAddSeq(uint32_t diff) { return seq_.fetch_add(diff); } + uint32_t seq() { return seq_.load(); } + ++ uint32_t FetchAddArenaSeq(uint32_t diff) { ++ return arena_seq_.fetch_add(diff); ++ } ++ uint32_t arena_seq() { return arena_seq_.load(); } ++ + void set_need_remap(bool need) { need_remap_.store(need); } + bool need_remap() { return need_remap_; } + +@@ -55,6 +60,7 @@ class State { + private: + std::atomic need_remap_ = {false}; + std::atomic seq_ = {0}; ++ std::atomic arena_seq_ = {0}; + std::atomic reference_count_ = {0}; + std::atomic ceiling_msg_size_; + }; +diff --git a/cyber/transport/shm/xsi_segment.cc b/cyber/transport/shm/xsi_segment.cc +index dce45e7..a613222 100644 +--- a/cyber/transport/shm/xsi_segment.cc ++++ b/cyber/transport/shm/xsi_segment.cc +@@ -100,27 +100,60 @@ bool XsiSegment::OpenOrCreate() { + return false; + } + ++ // create field arena_blocks_ ++ arena_blocks_ = new (static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block)) Block[ ++ ShmConf::ARENA_BLOCK_NUM]; ++ if (arena_blocks_ == nullptr) { ++ AERROR << "create arena blocks failed."; ++ state_->~State(); ++ state_ = nullptr; ++ shmdt(managed_shm_); ++ managed_shm_ = nullptr; ++ shmctl(shmid, IPC_RMID, 0); ++ return false; ++ } ++ + // create block buf + uint32_t i = 0; + for (; i < conf_.block_num(); ++i) { +- uint8_t* addr = +- new (static_cast(managed_shm_) + sizeof(State) + +- conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()) +- uint8_t[conf_.block_buf_size()]; +- ++ uint8_t* addr = \ ++ new (static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + \ ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ ++ i * conf_.block_buf_size()) uint8_t[conf_.block_buf_size()]; + std::lock_guard _g(block_buf_lock_); + block_buf_addrs_[i] = addr; + } + +- if (i != conf_.block_num()) { +- AERROR << "create block buf failed."; ++ // create arena block buf ++ uint32_t ai = 0; ++ for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { ++ uint8_t* addr = \ ++ new(static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + \ ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ ++ conf_.block_num() * conf_.block_buf_size() + \ ++ ai * ShmConf::ARENA_MESSAGE_SIZE) uint8_t[ ++ ShmConf::ARENA_MESSAGE_SIZE]; ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_[ai] = addr; ++ } ++ ++ if (ai != ShmConf::ARENA_BLOCK_NUM || i != conf_.block_num()) { ++ AERROR << "create arena block or block buf failed."; + state_->~State(); + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard _g(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + shmdt(managed_shm_); + managed_shm_ = nullptr; + shmctl(shmid, IPC_RMID, 0); +@@ -174,12 +207,26 @@ bool XsiSegment::OpenOnly() { + return false; + } + ++ // get field arena_blocks_ ++ arena_blocks_ = reinterpret_cast( ++ static_cast(managed_shm_) + sizeof(State) + \ ++ sizeof(Block) * conf_.block_num()); ++ if (arena_blocks_ == nullptr) { ++ AERROR << "get blocks failed."; ++ state_ = nullptr; ++ shmdt(managed_shm_); ++ managed_shm_ = nullptr; ++ return false; ++ } ++ + // get block buf + uint32_t i = 0; + for (; i < conf_.block_num(); ++i) { + uint8_t* addr = reinterpret_cast( +- static_cast(managed_shm_) + sizeof(State) + +- conf_.block_num() * sizeof(Block) + i * conf_.block_buf_size()); ++ static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + \ ++ ShmConf::ARENA_BLOCK_NUM * sizeof(Block) + \ ++ i * conf_.block_buf_size()); + + if (addr == nullptr) { + break; +@@ -188,15 +235,36 @@ bool XsiSegment::OpenOnly() { + block_buf_addrs_[i] = addr; + } + +- if (i != conf_.block_num()) { ++ // get arena block buf ++ uint32_t ai = 0; ++ for (; ai < ShmConf::ARENA_BLOCK_NUM; ++ai) { ++ uint8_t* addr = reinterpret_cast( ++ static_cast(managed_shm_) + sizeof(State) + \ ++ conf_.block_num() * sizeof(Block) + ShmConf::ARENA_BLOCK_NUM * \ ++ sizeof(Block) + conf_.block_num() * conf_.block_buf_size() + \ ++ ai * ShmConf::ARENA_MESSAGE_SIZE); ++ ++ if (addr == nullptr) { ++ break; ++ } ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_[ai] = addr; ++ } ++ ++ if (i != conf_.block_num() || ai != ShmConf::ARENA_BLOCK_NUM) { + AERROR << "open only failed."; + state_->~State(); + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard _g(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + shmdt(managed_shm_); + managed_shm_ = nullptr; + shmctl(shmid, IPC_RMID, 0); +@@ -222,10 +290,15 @@ bool XsiSegment::Remove() { + void XsiSegment::Reset() { + state_ = nullptr; + blocks_ = nullptr; ++ arena_blocks_ = nullptr; + { + std::lock_guard _g(block_buf_lock_); + block_buf_addrs_.clear(); + } ++ { ++ std::lock_guard _g(arena_block_buf_lock_); ++ arena_block_buf_addrs_.clear(); ++ } + if (managed_shm_ != nullptr) { + shmdt(managed_shm_); + managed_shm_ = nullptr; +diff --git a/cyber/transport/transmitter/hybrid_transmitter.h b/cyber/transport/transmitter/hybrid_transmitter.h +index 1afba70..fe176d4 100644 +--- a/cyber/transport/transmitter/hybrid_transmitter.h ++++ b/cyber/transport/transmitter/hybrid_transmitter.h +@@ -25,12 +25,13 @@ + #include + #include + ++#include "cyber/proto/role_attributes.pb.h" ++#include "cyber/proto/transport_conf.pb.h" + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/common/types.h" +-#include "cyber/proto/role_attributes.pb.h" +-#include "cyber/proto/transport_conf.pb.h" + #include "cyber/task/task.h" ++#include "cyber/transport/dispatcher/rtps_dispatcher.h" + #include "cyber/transport/message/history.h" + #include "cyber/transport/rtps/participant.h" + #include "cyber/transport/transmitter/intra_transmitter.h" +@@ -71,6 +72,8 @@ class HybridTransmitter : public Transmitter { + + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + ++ bool AcquireMessage(std::shared_ptr& msg); ++ + private: + void InitMode(); + void ObtainConfig(); +@@ -141,7 +144,7 @@ void HybridTransmitter::Enable(const RoleAttributes& opposite_attr) { + uint64_t id = opposite_attr.id(); + std::lock_guard lock(mutex_); + receivers_[mapping_table_[relation]].insert(id); +- transmitters_[mapping_table_[relation]]->Enable(); ++ transmitters_[mapping_table_[relation]]->Enable(opposite_attr); + TransmitHistoryMsg(opposite_attr); + } + +@@ -155,9 +158,7 @@ void HybridTransmitter::Disable(const RoleAttributes& opposite_attr) { + uint64_t id = opposite_attr.id(); + std::lock_guard lock(mutex_); + receivers_[mapping_table_[relation]].erase(id); +- if (receivers_[mapping_table_[relation]].empty()) { +- transmitters_[mapping_table_[relation]]->Disable(); +- } ++ transmitters_[mapping_table_[relation]]->Disable(opposite_attr); + } + + template +@@ -165,12 +166,25 @@ bool HybridTransmitter::Transmit(const MessagePtr& msg, + const MessageInfo& msg_info) { + std::lock_guard lock(mutex_); + history_->Add(msg, msg_info); ++ bool return_val = false; + for (auto& item : transmitters_) { + item.second->Transmit(msg, msg_info); + } + return true; + } + ++template ++bool HybridTransmitter::AcquireMessage(std::shared_ptr& msg) { ++ bool result = false; ++ for (auto& item : transmitters_) { ++ result = item.second->AcquireMessage(msg); ++ if (result) { ++ return true; ++ } ++ } ++ return false; ++} ++ + template + void HybridTransmitter::InitMode() { + mode_ = std::make_shared(); +diff --git a/cyber/transport/transmitter/intra_transmitter.h b/cyber/transport/transmitter/intra_transmitter.h +index 1235652..de9ab7c 100644 +--- a/cyber/transport/transmitter/intra_transmitter.h ++++ b/cyber/transport/transmitter/intra_transmitter.h +@@ -39,13 +39,23 @@ class IntraTransmitter : public Transmitter { + void Enable() override; + void Disable() override; + ++ void Enable(const RoleAttributes& opposite_attr) override; ++ void Disable(const RoleAttributes& opposite_attr) override; ++ + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + ++ bool AcquireMessage(std::shared_ptr& msg); ++ + private: + uint64_t channel_id_; + IntraDispatcherPtr dispatcher_; + }; + ++template ++bool IntraTransmitter::AcquireMessage(std::shared_ptr& msg) { ++ return false; ++} ++ + template + IntraTransmitter::IntraTransmitter(const RoleAttributes& attr) + : Transmitter(attr), +@@ -57,6 +67,18 @@ IntraTransmitter::~IntraTransmitter() { + Disable(); + } + ++template ++void IntraTransmitter::Enable(const RoleAttributes& opposite_attr) { ++ (void)opposite_attr; ++ this->Enable(); ++} ++ ++template ++void IntraTransmitter::Disable(const RoleAttributes& opposite_attr) { ++ (void)opposite_attr; ++ this->Disable(); ++} ++ + template + void IntraTransmitter::Enable() { + if (!this->enabled_) { +diff --git a/cyber/transport/transmitter/rtps_transmitter.h b/cyber/transport/transmitter/rtps_transmitter.h +index 54864c2..7ec65ff 100644 +--- a/cyber/transport/transmitter/rtps_transmitter.h ++++ b/cyber/transport/transmitter/rtps_transmitter.h +@@ -17,18 +17,19 @@ + #ifndef CYBER_TRANSPORT_TRANSMITTER_RTPS_TRANSMITTER_H_ + #define CYBER_TRANSPORT_TRANSMITTER_RTPS_TRANSMITTER_H_ + ++#include + #include + #include + + #include "cyber/common/log.h" + #include "cyber/message/message_traits.h" ++#include "cyber/statistics/statistics.h" ++#include "cyber/time/time.h" ++#include "cyber/transport/dispatcher/subscriber_listener.h" + #include "cyber/transport/rtps/attributes_filler.h" + #include "cyber/transport/rtps/participant.h" ++#include "cyber/transport/rtps/publisher.h" + #include "cyber/transport/transmitter/transmitter.h" +-#include "fastrtps/Domain.h" +-#include "fastrtps/attributes/PublisherAttributes.h" +-#include "fastrtps/participant/Participant.h" +-#include "fastrtps/publisher/Publisher.h" + + namespace apollo { + namespace cyber { +@@ -38,6 +39,7 @@ template + class RtpsTransmitter : public Transmitter { + public: + using MessagePtr = std::shared_ptr; ++ using ParticipantPtr = std::shared_ptr; + + RtpsTransmitter(const RoleAttributes& attr, + const ParticipantPtr& participant); +@@ -46,15 +48,25 @@ class RtpsTransmitter : public Transmitter { + void Enable() override; + void Disable() override; + ++ void Enable(const RoleAttributes& opposite_attr) override; ++ void Disable(const RoleAttributes& opposite_attr) override; ++ + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + ++ bool AcquireMessage(std::shared_ptr& msg); ++ + private: + bool Transmit(const M& msg, const MessageInfo& msg_info); + + ParticipantPtr participant_; +- eprosima::fastrtps::Publisher* publisher_; ++ PublisherPtr publisher_; + }; + ++template ++bool RtpsTransmitter::AcquireMessage(std::shared_ptr& msg) { ++ return false; ++} ++ + template + RtpsTransmitter::RtpsTransmitter(const RoleAttributes& attr, + const ParticipantPtr& participant) +@@ -65,6 +77,18 @@ RtpsTransmitter::~RtpsTransmitter() { + Disable(); + } + ++template ++void RtpsTransmitter::Enable(const RoleAttributes& opposite_attr) { ++ (void)opposite_attr; ++ this->Enable(); ++} ++ ++template ++void RtpsTransmitter::Disable(const RoleAttributes& opposite_attr) { ++ (void)opposite_attr; ++ this->Disable(); ++} ++ + template + void RtpsTransmitter::Enable() { + if (this->enabled_) { +@@ -73,11 +97,9 @@ void RtpsTransmitter::Enable() { + + RETURN_IF_NULL(participant_); + +- eprosima::fastrtps::PublisherAttributes pub_attr; +- RETURN_IF(!AttributesFiller::FillInPubAttr( +- this->attr_.channel_name(), this->attr_.qos_profile(), &pub_attr)); +- publisher_ = eprosima::fastrtps::Domain::createPublisher( +- participant_->fastrtps_participant(), pub_attr); ++ publisher_ = participant_->CreatePublisher(this->attr_.channel_name(), ++ this->attr_.qos_profile()); ++ + RETURN_IF_NULL(publisher_); + this->enabled_ = true; + } +@@ -99,30 +121,21 @@ bool RtpsTransmitter::Transmit(const MessagePtr& msg, + template + bool RtpsTransmitter::Transmit(const M& msg, const MessageInfo& msg_info) { + if (!this->enabled_) { +- ADEBUG << "not enable."; ++ ADEBUG << "RtpsTransmitter not enable."; + return false; + } + + UnderlayMessage m; + RETURN_VAL_IF(!message::SerializeToString(msg, &m.data()), false); +- +- eprosima::fastrtps::rtps::WriteParams wparams; +- +- char* ptr = +- reinterpret_cast(&wparams.related_sample_identity().writer_guid()); +- +- memcpy(ptr, msg_info.sender_id().data(), ID_SIZE); +- memcpy(ptr + ID_SIZE, msg_info.spare_id().data(), ID_SIZE); +- +- wparams.related_sample_identity().sequence_number().high = +- (int32_t)((msg_info.seq_num() & 0xFFFFFFFF00000000) >> 32); +- wparams.related_sample_identity().sequence_number().low = +- (int32_t)(msg_info.seq_num() & 0xFFFFFFFF); ++ m.timestamp(msg_info.send_time()); ++ m.seq(msg_info.seq_num()); + + if (participant_->is_shutdown()) { + return false; + } +- return publisher_->write(reinterpret_cast(&m), wparams); ++ ++ RETURN_VAL_IF_NULL(publisher_, NULL); ++ return publisher_->Write(m, msg_info); + } + + } // namespace transport +diff --git a/cyber/transport/transmitter/shm_transmitter.h b/cyber/transport/transmitter/shm_transmitter.h +index b4a6667..5d8a0d5 100644 +--- a/cyber/transport/transmitter/shm_transmitter.h ++++ b/cyber/transport/transmitter/shm_transmitter.h +@@ -21,12 +21,16 @@ + #include + #include + #include ++#include + + #include "cyber/common/global_data.h" + #include "cyber/common/log.h" + #include "cyber/common/util.h" ++#include "cyber/message/arena_message_wrapper.h" + #include "cyber/message/message_traits.h" ++#include "cyber/statistics/statistics.h" + #include "cyber/transport/shm/notifier_factory.h" ++#include "cyber/transport/shm/protobuf_arena_manager.h" + #include "cyber/transport/shm/readable_info.h" + #include "cyber/transport/shm/segment_factory.h" + #include "cyber/transport/transmitter/transmitter.h" +@@ -35,6 +39,9 @@ namespace apollo { + namespace cyber { + namespace transport { + ++template ++struct type_check : std::is_same::type, U>::type {}; ++ + template + class ShmTransmitter : public Transmitter { + public: +@@ -46,8 +53,13 @@ class ShmTransmitter : public Transmitter { + void Enable() override; + void Disable() override; + ++ void Enable(const RoleAttributes& opposite_attr); ++ void Disable(const RoleAttributes& opposite_attr); ++ + bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override; + ++ bool AcquireMessage(std::shared_ptr& msg); ++ + private: + bool Transmit(const M& msg, const MessageInfo& msg_info); + +@@ -55,15 +67,44 @@ class ShmTransmitter : public Transmitter { + uint64_t channel_id_; + uint64_t host_id_; + NotifierPtr notifier_; ++ std::atomic serialized_receiver_count_; ++ std::atomic arena_receiver_count_; ++ bool arena_transmit_; + }; + ++template ++bool ShmTransmitter::AcquireMessage(std::shared_ptr& msg) { ++ if (this->enabled_) { ++ auto msg_o = msg.get(); ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ if (!arena_manager->Enable() || ++ !arena_manager->EnableSegment(this->attr_.channel_id())) { ++ ADEBUG << "arena manager enable failed."; ++ return false; ++ } ++ arena_manager->AcquireArenaMessage(channel_id_, msg); ++ if (msg.get() != msg_o) { ++ return true; ++ } else { ++ return false; ++ } ++ } ++ return false; ++} ++ + template + ShmTransmitter::ShmTransmitter(const RoleAttributes& attr) + : Transmitter(attr), + segment_(nullptr), + channel_id_(attr.channel_id()), +- notifier_(nullptr) { ++ notifier_(nullptr), ++ serialized_receiver_count_(0), ++ arena_receiver_count_(0) { + host_id_ = common::Hash(attr.host_ip()); ++ arena_transmit_ = common::GlobalData::Instance()->IsChannelEnableArenaShm( ++ this->attr_.channel_id()) && ++ !type_check::value && ++ !type_check::value; + } + + template +@@ -71,12 +112,71 @@ ShmTransmitter::~ShmTransmitter() { + Disable(); + } + ++template ++void ShmTransmitter::Enable(const RoleAttributes& opposite_attr) { ++ if (arena_transmit_) { ++ if (opposite_attr.message_type() == ++ message::MessageType() || ++ opposite_attr.message_type() == ++ message::MessageType()) { ++ serialized_receiver_count_.fetch_add(1); ++ } else { ++ arena_receiver_count_.fetch_add(1); ++ } ++ } else { ++ serialized_receiver_count_.fetch_add(1); ++ } ++ if (!this->enabled_) { ++ this->Enable(); ++ } ++} ++ ++template ++void ShmTransmitter::Disable(const RoleAttributes& opposite_attr) { ++ if (this->enabled_) { ++ if (arena_transmit_) { ++ if (opposite_attr.message_type() == ++ message::MessageType() || ++ opposite_attr.message_type() == ++ message::MessageType()) { ++ serialized_receiver_count_.fetch_sub(1); ++ } else { ++ arena_receiver_count_.fetch_sub(1); ++ } ++ if (serialized_receiver_count_.load() <= 0 && ++ arena_receiver_count_.load() <= 0) { ++ this->Disable(); ++ } ++ } else { ++ serialized_receiver_count_.fetch_sub(1); ++ if (serialized_receiver_count_.load() <= 0) { ++ this->Disable(); ++ } ++ } ++ } ++} ++ + template + void ShmTransmitter::Enable() { + if (this->enabled_) { + return; + } + ++ if (serialized_receiver_count_.load() == 0 && ++ arena_receiver_count_.load() == 0) { ++ AERROR << "please enable shm transmitter by passing role attr."; ++ return; ++ } ++ ++ if (arena_transmit_) { ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ if (!arena_manager->Enable() || ++ !arena_manager->EnableSegment(this->attr_.channel_id())) { ++ AERROR << "arena manager enable failed."; ++ return; ++ } ++ } ++ + segment_ = SegmentFactory::CreateSegment(channel_id_); + notifier_ = NotifierFactory::CreateNotifier(); + this->enabled_ = true; +@@ -104,35 +204,119 @@ bool ShmTransmitter::Transmit(const M& msg, const MessageInfo& msg_info) { + return false; + } + ++ ReadableInfo readable_info; ++ WritableBlock arena_wb; + WritableBlock wb; +- std::size_t msg_size = message::ByteSize(msg); +- if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { +- AERROR << "acquire block failed."; +- return false; +- } + +- ADEBUG << "block index: " << wb.index; +- if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { +- AERROR << "serialize to array failed."; +- segment_->ReleaseWrittenBlock(wb); +- return false; +- } +- wb.block->set_msg_size(msg_size); ++ readable_info.set_host_id(host_id_); ++ readable_info.set_channel_id(channel_id_); ++ readable_info.set_arena_block_index(-1); ++ readable_info.set_block_index(-1); ++ ++ if (arena_transmit_) { ++ // std::size_t msg_size = sizeof(message::ArenaMessageWrapper); ++ std::size_t msg_size = 1024; ++ if (!segment_->AcquireArenaBlockToWrite(msg_size, &arena_wb)) { ++ AERROR << "acquire block failed."; ++ return false; ++ } ++ ++ ADEBUG << "arena block index: " << arena_wb.index; ++ auto arena_manager = ProtobufArenaManager::Instance(); ++ auto msg_wrapper = arena_manager->CreateMessageWrapper(); ++ arena_manager->SetMessageChannelId(msg_wrapper.get(), channel_id_); ++ M* msg_p; ++ // arena_manager->CreateMessage(msg_wrapper.get(), msg); ++ if (!message::SerializeToArenaMessageWrapper(msg, msg_wrapper.get(), ++ &msg_p)) { ++ AERROR << "serialize to arena message wrapper failed."; ++ segment_->ReleaseArenaWrittenBlock(arena_wb); ++ return false; ++ } ++ auto segment = arena_manager->GetSegment(channel_id_); ++ // auto msg_n = ++ // std::shared_ptr( ++ // msg_p, [arena_manager, segment, msg_wrapper](M* p) { ++ // auto related_blocks = ++ // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get()); ++ // for (auto block_index : related_blocks) { ++ // // segment->ReleaseBlockForWriteByIndex(block_index); ++ // segment->RemoveBlockWriteLock(block_index); ++ // } ++ // }); ++ // for (auto block_index : ++ // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get())) { ++ // segment->LockBlockForWriteByIndex(block_index); ++ // } ++ memcpy(arena_wb.buf, msg_wrapper->GetData(), msg_size); ++ arena_wb.block->set_msg_size(msg_size); ++ ++ char* msg_info_addr = reinterpret_cast(arena_wb.buf) + msg_size; ++ if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { ++ AERROR << "serialize message info failed."; ++ segment_->ReleaseArenaWrittenBlock(arena_wb); ++ return false; ++ } ++ arena_wb.block->set_msg_info_size(MessageInfo::kSize); ++ readable_info.set_arena_block_index(arena_wb.index); ++ if (serialized_receiver_count_.load() > 0) { ++ std::size_t msg_size = message::ByteSize(msg); ++ if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { ++ AERROR << "acquire block failed."; ++ return false; ++ } ++ ++ ADEBUG << "block index: " << wb.index; ++ if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { ++ AERROR << "serialize to array failed."; ++ segment_->ReleaseWrittenBlock(wb); ++ return false; ++ } ++ wb.block->set_msg_size(msg_size); + +- char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; +- if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { +- AERROR << "serialize message info failed."; ++ char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; ++ if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { ++ AERROR << "serialize message info failed."; ++ segment_->ReleaseWrittenBlock(wb); ++ return false; ++ } ++ wb.block->set_msg_info_size(MessageInfo::kSize); ++ segment_->ReleaseWrittenBlock(wb); ++ segment_->ReleaseArenaWrittenBlock(arena_wb); ++ readable_info.set_block_index(wb.index); ++ } else { ++ segment_->ReleaseArenaWrittenBlock(arena_wb); ++ } ++ } else { ++ std::size_t msg_size = message::ByteSize(msg); ++ if (!segment_->AcquireBlockToWrite(msg_size, &wb)) { ++ AERROR << "acquire block failed."; ++ return false; ++ } ++ ++ ADEBUG << "block index: " << wb.index; ++ if (!message::SerializeToArray(msg, wb.buf, static_cast(msg_size))) { ++ AERROR << "serialize to array failed."; ++ segment_->ReleaseWrittenBlock(wb); ++ return false; ++ } ++ wb.block->set_msg_size(msg_size); ++ ++ char* msg_info_addr = reinterpret_cast(wb.buf) + msg_size; ++ if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) { ++ AERROR << "serialize message info failed."; ++ segment_->ReleaseWrittenBlock(wb); ++ return false; ++ } ++ wb.block->set_msg_info_size(MessageInfo::kSize); + segment_->ReleaseWrittenBlock(wb); +- return false; ++ readable_info.set_block_index(wb.index); + } +- wb.block->set_msg_info_size(MessageInfo::kSize); +- segment_->ReleaseWrittenBlock(wb); +- +- ReadableInfo readable_info(host_id_, wb.index, channel_id_); + + ADEBUG << "Writing sharedmem message: " + << common::GlobalData::GetChannelById(channel_id_) +- << " to block: " << wb.index; ++ << " to normal block: " << readable_info.block_index() ++ << " to arena block: " << readable_info.arena_block_index(); + return notifier_->Notify(readable_info); + } + +diff --git a/cyber/transport/transmitter/transmitter.h b/cyber/transport/transmitter/transmitter.h +index b8fc7f7..de0fa96 100644 +--- a/cyber/transport/transmitter/transmitter.h ++++ b/cyber/transport/transmitter/transmitter.h +@@ -22,6 +22,7 @@ + #include + + #include "cyber/event/perf_event_cache.h" ++#include "cyber/statistics/statistics.h" + #include "cyber/transport/common/endpoint.h" + #include "cyber/transport/message/message_info.h" + +@@ -43,26 +44,32 @@ class Transmitter : public Endpoint { + virtual void Enable() = 0; + virtual void Disable() = 0; + ++ virtual bool AcquireMessage(std::shared_ptr& msg) = 0; ++ + virtual void Enable(const RoleAttributes& opposite_attr); + virtual void Disable(const RoleAttributes& opposite_attr); + + virtual bool Transmit(const MessagePtr& msg); + virtual bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) = 0; + +- uint64_t NextSeqNum() { return ++seq_num_; } ++ uint64_t NextSeqNum() { ++ (*seq_num_) << 1; ++ return seq_num_->get_value(); ++ } + +- uint64_t seq_num() const { return seq_num_; } ++ uint64_t seq_num() const { return seq_num_->get_value(); } + + protected: +- uint64_t seq_num_; + MessageInfo msg_info_; ++ std::shared_ptr<::bvar::Adder> seq_num_; + }; + + template +-Transmitter::Transmitter(const RoleAttributes& attr) +- : Endpoint(attr), seq_num_(0) { ++Transmitter::Transmitter(const RoleAttributes& attr) : Endpoint(attr) { + msg_info_.set_sender_id(this->id_); +- msg_info_.set_seq_num(this->seq_num_); ++ msg_info_.set_seq_num(0); ++ seq_num_ = ++ statistics::Statistics::Instance()->CreateAdder(Endpoint::attr_); + } + + template +@@ -71,6 +78,7 @@ Transmitter::~Transmitter() {} + template + bool Transmitter::Transmit(const MessagePtr& msg) { + msg_info_.set_seq_num(NextSeqNum()); ++ msg_info_.set_send_time(Time::Now().ToNanosecond()); + PerfEventCache::Instance()->AddTransportEvent( + TransPerf::TRANSMIT_BEGIN, attr_.channel_id(), msg_info_.seq_num()); + return Transmit(msg, msg_info_); +diff --git a/cyber/transport/transport.cc b/cyber/transport/transport.cc +index 0234871..a9d6d0c 100644 +--- a/cyber/transport/transport.cc ++++ b/cyber/transport/transport.cc +@@ -17,6 +17,7 @@ + #include "cyber/transport/transport.h" + + #include "cyber/common/global_data.h" ++#include "cyber/transport/dispatcher/rtps_dispatcher.h" + + namespace apollo { + namespace cyber { +@@ -28,7 +29,7 @@ Transport::Transport() { + intra_dispatcher_ = IntraDispatcher::Instance(); + shm_dispatcher_ = ShmDispatcher::Instance(); + rtps_dispatcher_ = RtpsDispatcher::Instance(); +- rtps_dispatcher_->set_participant(participant_); ++ rtps_dispatcher_->SetParticipant(participant_); + } + + Transport::~Transport() { Shutdown(); } +@@ -53,7 +54,11 @@ void Transport::CreateParticipant() { + std::string participant_name = + common::GlobalData::Instance()->HostName() + "+" + + std::to_string(common::GlobalData::Instance()->ProcessId()); +- participant_ = std::make_shared(participant_name, 11512); ++ participant_ = std::make_shared< ++ Participant>(participant_name, 11512); ++ if (!participant_->Init()) { ++ AERROR << "Transport inner participant init failed!"; ++ } + } + + } // namespace transport From 58dff0e85c594c678c7794b4d50b5e04037e6558 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Tue, 17 Dec 2024 16:01:51 +0800 Subject: [PATCH 08/14] chore(script): update install.py for v10 --- README.md | 11 +++- install.py | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 252607e..5fc2fd5 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,19 @@ ```shell sudo apt update -sudo apt install -y uuid-dev libncurses5-dev python3-dev python3-pip +sudo apt install -y wget autoconf automake libtool g++ pkg-config uuid-dev libncurses5-dev python3-dev python3-pip python3 -m pip install protobuf==3.14.0 ``` +| dependence | v9.0.0 | v10.0.0 | +| :---: | :---: |:---:| +| C++ STANDARD | C++14 | C+17 | +| gcc/g++ | system default | 8.1+ | +| FastDDS | v1.5.0 | v2.14.3 | +| protobuf | v3.14.0 | v3.14.0 | +| bvar | | new | +| gperftools | | gperftools-2.8 | + ## #2 Build 1. clone diff --git a/install.py b/install.py index f87676f..702d288 100644 --- a/install.py +++ b/install.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import subprocess +import re import os import argparse import time @@ -32,15 +33,23 @@ def _load_environment(self): def _cmd(self, command): """执行系统命令,使用指定的环境变量""" + if command is None: + return None print("[command] {}".format(command)) subprocess.run(command, shell=True, env=self.environment) def start(self): + self._clone_gcc() + self._clone_cmake() self._clone_setup() - self._clone_nlohmann_json() self._clone_tinyxml2() + # # self._clone_dds() + self._clone_dds2() + self._clone_nlohmann_json() + self._clone_proj() # ros_bridge of apollo v10 self._clone_gfamily() - self._clone_dds() + self._clone_gperftools() # apollo v10 + self._unpack_bvar() # apollo v10 def _clone_github_repo(self, repo_url, repo_name, *args): dowload_path = os.path.join(self._dowload_path, repo_name) @@ -73,6 +82,58 @@ def _clone_setup(self): self._cmd("make install -j$(nproc)") os.chdir(self._current_path) + def _clone_gcc(self): + print("start to install gcc") + gcc_version = "0.0" + try: + result = subprocess.run(['gcc', '--version'], stdout=subprocess.PIPE, universal_newlines=True, check=True) + output = result.stdout.splitlines()[0] + match = re.search(r'(\d+\.\d+\.\d+)', output) + if match: + gcc_version = match.group(1) + print(f"GCC version: {gcc_version}") + if "8.1" < gcc_version: + print("GCC version is greater than or equal to 8.1.0, skip installation") + return None + except Exception as e: + print("gcc error: {}".format(e)) + + self._cmd("apt update") + self._cmd("apt install -y software-properties-common") + self._cmd("add-apt-repository -y ppa:ubuntu-toolchain-r/test") + self._cmd("apt update") + self._cmd("apt install -y gcc-9 g++-9") + self._cmd("update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100") + self._cmd("update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 100") + return None + + def _clone_cmake(self): + print("start to install cmake") + cmake_version = "0.0.0" + try: + result = subprocess.run(['cmake', '--version'], stdout=subprocess.PIPE, universal_newlines=True, check=True) + output = result.stdout.splitlines()[0] + match = re.search(r'(\d+\.\d+\.\d+)', output) + if match: + cmake_version = match.group(1) + print(f"CMake version: {cmake_version}") + if "3.20" < cmake_version: + print("CMake version is greater than 3.20, skip installation") + return None + except Exception as e: + print("cmake error: {}".format(e)) + + print("CMake version is less than 3.20, start installation") + self._cmd("wget -t 10 {} -P {}".format("https://cmake.org/files/v3.22/cmake-3.22.0-linux-x86_64.tar.gz",self._dowload_path)) + os.chdir(self._dowload_path) + self._cmd("tar -zxvf cmake-3.22.0-linux-x86_64.tar.gz") + self._cmd("cp -r cmake-3.22.0-linux-x86_64/bin/* /usr/local/bin") + self._cmd("cp -r cmake-3.22.0-linux-x86_64/doc/* /usr/local/doc") + self._cmd("cp -r cmake-3.22.0-linux-x86_64/share/* /usr/local/share") + self._cmd("rm -rf cmake-3.22.0-linux-x86_64*") + os.chdir(self._current_path) + return None + def _clone_nlohmann_json(self): self._clone_github_repo( "https://github.com/nlohmann/json.git", @@ -103,6 +164,47 @@ def _clone_tinyxml2(self): self._cmd("make install -j$(nproc)") os.chdir(self._current_path) + def _clone_gperftools(self): + self._clone_github_repo( + "https://github.com/gperftools/gperftools.git", + "gperftools", + "--single-branch", + "--branch=gperftools-2.8", + "--depth=1" + ) + os.chdir(os.path.join(self._dowload_path, "gperftools")) + self._cmd("./autogen.sh || sleep 1 && ./autogen.sh") + self._cmd( + "./configure --prefix={} --libdir={}".format( + self._install_prefix, os.path.join(self._install_prefix, "lib") + ) + ) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + return None + + def _clone_proj(self): + self._clone_github_repo( + "https://github.com/OSGeo/PROJ.git", + "PROJ", + "--single-branch", + "--branch=7.1.0", + "--depth=1" + ) + os.chdir(os.path.join(self._dowload_path, "PROJ")) + self._cmd("mkdir -p build") + os.chdir("build") + self._cmd( + "cmake -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( + self._install_prefix + ) + ) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + return None + def _clone_gfamily(self): self._clone_github_repo( "https://github.com/gflags/gflags.git", @@ -209,6 +311,80 @@ def _clone_dds(self): self._cmd("rm -rf fast-rtps-1.5.0-1/") os.chdir(self._current_path) + def _clone_dds2(self): + self._clone_github_repo( + "https://github.com/chriskohlhoff/asio.git", + "asio", + "--single-branch", + "--branch=asio-1-18-1", + "--depth=1" + ) + self._clone_github_repo( + "https://github.com/eProsima/foonathan_memory_vendor.git", + "foonathan_memory_vendor", + "--single-branch", + "--branch=v1.3.1", + "--depth=1" + ) + self._clone_github_repo( + "https://github.com/eProsima/Fast-CDR.git", + "Fast-CDR", + "--single-branch", + "--branch=v2.2.2", + "--depth=1" + ) + self._clone_github_repo( + "https://github.com/eProsima/Fast-DDS.git", + "Fast-DDS", + "--single-branch", + "--branch=v2.14.3", + "--depth=1" + ) + os.chdir(os.path.join(self._dowload_path, "asio/asio")) + self._cmd("./autogen.sh") + self._cmd("./configure --prefix={}".format(self._install_prefix)) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + os.chdir(os.path.join(self._dowload_path, "foonathan_memory_vendor")) + self._cmd("mkdir -p build") + os.chdir("build") + self._cmd("cmake -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( + self._install_prefix)) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + os.chdir(os.path.join(self._dowload_path, "Fast-CDR")) + self._cmd("mkdir -p build") + os.chdir("build") + self._cmd("cmake -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( + self._install_prefix)) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + os.chdir(os.path.join(self._dowload_path, "Fast-DDS")) + self._cmd("mkdir -p build") + os.chdir("build") + self._cmd("cmake -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( + self._install_prefix)) + self._cmd("make install -j$(nproc)") + os.chdir(self._current_path) + + return None + + def _unpack_bvar(self): + download_url = "https://raw.githubusercontent.com/wiki/minhanghuang/CyberRT/libs" + bvar_name = "bvar_9.0.0-rc-r2_amd64.deb" + if "x86_64" == self._machine: + pass + else: + bvar_name = "bvar_9.0.0-rc-r3_arm64.deb" + download_url = download_url + "/" + bvar_name + self._cmd("wget -t 10 {} -O {}".format(download_url, os.path.join(self._dowload_path, "bvar.deb"))) + self._cmd("dpkg -x {} {}".format(os.path.join(self._dowload_path, "bvar.deb"), os.path.join(self._dowload_path, "bvar"))) + self._cmd("cp -r {}* {}".format(os.path.join(self._dowload_path, "bvar/usr/local/"), self._install_prefix)) + return None + def parse_config(): parser = argparse.ArgumentParser(description="install") parser.add_argument("--platform", type=str, default=platform.machine(), help="platform") @@ -219,6 +395,6 @@ def parse_config(): if __name__ == "__main__": args = parse_config() print(f"args.platform: {args.platform}, args.install_prefix: {args.install_prefix}") - time.sleep(3) + # time.sleep(3) install = Install(args.platform, args.install_prefix) install.start() From 9d58d49977ca8f5c7b92f39888e83d76238ef824 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Tue, 17 Dec 2024 16:08:07 +0800 Subject: [PATCH 09/14] chore(ci): update ci for v10 --- ...uild.yaml => ubuntu-latest-arrch64-v10.0.0-build.yaml} | 6 +++--- ...v9.0.0-build.yaml => ubuntu-latest-v10.0.0-build.yaml} | 6 +++--- ...0.0-build.yaml => ubuntu18-arrch64-v10.0.0-build.yaml} | 6 +++--- ...tu18-v9.0.0-build.yaml => ubuntu18-v10.0.0-build.yaml} | 8 ++++---- ...0.0-build.yaml => ubuntu20-arrch64-v10.0.0-build.yaml} | 6 +++--- ...tu20-v9.0.0-build.yaml => ubuntu20-v10.0.0-build.yaml} | 6 +++--- ...0.0-build.yaml => ubuntu22-arrch64-v10.0.0-build.yaml} | 6 +++--- ...tu22-v9.0.0-build.yaml => ubuntu22-v10.0.0-build.yaml} | 6 +++--- ...tu24-v9.0.0-build.yaml => ubuntu24-v10.0.0-build.yaml} | 6 +++--- README.md | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) rename .github/workflows/{ubuntu-latest-arrch64-v9.0.0-build.yaml => ubuntu-latest-arrch64-v10.0.0-build.yaml} (73%) rename .github/workflows/{ubuntu-latest-v9.0.0-build.yaml => ubuntu-latest-v10.0.0-build.yaml} (76%) rename .github/workflows/{ubuntu18-arrch64-v9.0.0-build.yaml => ubuntu18-arrch64-v10.0.0-build.yaml} (76%) rename .github/workflows/{ubuntu18-v9.0.0-build.yaml => ubuntu18-v10.0.0-build.yaml} (77%) rename .github/workflows/{ubuntu20-arrch64-v9.0.0-build.yaml => ubuntu20-arrch64-v10.0.0-build.yaml} (72%) rename .github/workflows/{ubuntu20-v9.0.0-build.yaml => ubuntu20-v10.0.0-build.yaml} (76%) rename .github/workflows/{ubuntu22-arrch64-v9.0.0-build.yaml => ubuntu22-arrch64-v10.0.0-build.yaml} (72%) rename .github/workflows/{ubuntu22-v9.0.0-build.yaml => ubuntu22-v10.0.0-build.yaml} (76%) rename .github/workflows/{ubuntu24-v9.0.0-build.yaml => ubuntu24-v10.0.0-build.yaml} (76%) diff --git a/.github/workflows/ubuntu-latest-arrch64-v9.0.0-build.yaml b/.github/workflows/ubuntu-latest-arrch64-v10.0.0-build.yaml similarity index 73% rename from .github/workflows/ubuntu-latest-arrch64-v9.0.0-build.yaml rename to .github/workflows/ubuntu-latest-arrch64-v10.0.0-build.yaml index bf99daa..04011cd 100644 --- a/.github/workflows/ubuntu-latest-arrch64-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu-latest-arrch64-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu-latest v9.0.0 build arrch64 +name: ubuntu-latest v10.0.0 build arrch64 run-name: ubuntu latest arrch64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-arm-ubuntu-latest: @@ -22,7 +22,7 @@ jobs: install: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 run: | echo "-----------------------" diff --git a/.github/workflows/ubuntu-latest-v9.0.0-build.yaml b/.github/workflows/ubuntu-latest-v10.0.0-build.yaml similarity index 76% rename from .github/workflows/ubuntu-latest-v9.0.0-build.yaml rename to .github/workflows/ubuntu-latest-v10.0.0-build.yaml index 3a66785..1e8cfff 100644 --- a/.github/workflows/ubuntu-latest-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu-latest-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu-latest v9.0.0 build x86-64 +name: ubuntu-latest v10.0.0 build x86-64 run-name: ubuntu latest x86-64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-amd-ubuntu-latest: @@ -21,7 +21,7 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 cd /workspace/${{ github.repository }} && python3 install.py - name: Build diff --git a/.github/workflows/ubuntu18-arrch64-v9.0.0-build.yaml b/.github/workflows/ubuntu18-arrch64-v10.0.0-build.yaml similarity index 76% rename from .github/workflows/ubuntu18-arrch64-v9.0.0-build.yaml rename to .github/workflows/ubuntu18-arrch64-v10.0.0-build.yaml index 2b63369..c790e6f 100644 --- a/.github/workflows/ubuntu18-arrch64-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu18-arrch64-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu18.04 v9.0.0 build arrch64 +name: ubuntu18.04 v10.0.0 build arrch64 run-name: ubuntu18 arrch64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-arm-ubuntu18: @@ -26,7 +26,7 @@ jobs: install: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 run: | echo "-----------------------" diff --git a/.github/workflows/ubuntu18-v9.0.0-build.yaml b/.github/workflows/ubuntu18-v10.0.0-build.yaml similarity index 77% rename from .github/workflows/ubuntu18-v9.0.0-build.yaml rename to .github/workflows/ubuntu18-v10.0.0-build.yaml index 2d01209..e82a6ac 100644 --- a/.github/workflows/ubuntu18-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu18-v10.0.0-build.yaml @@ -1,4 +1,4 @@ -name: ubuntu18.04 v9.0.0 build x86-64 +name: ubuntu18.04 v10.0.0 build x86-64 run-name: ubuntu18 x86-64 env: @@ -7,11 +7,11 @@ env: on: push: branches: - - v9.0.0 + - v10.0.0 pull_request: branches: - - v9.0.0 + - v10.0.0 jobs: build-amd-ubuntu18: @@ -30,7 +30,7 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 python3 install.py - name: Build diff --git a/.github/workflows/ubuntu20-arrch64-v9.0.0-build.yaml b/.github/workflows/ubuntu20-arrch64-v10.0.0-build.yaml similarity index 72% rename from .github/workflows/ubuntu20-arrch64-v9.0.0-build.yaml rename to .github/workflows/ubuntu20-arrch64-v10.0.0-build.yaml index e5a2b58..db160c0 100644 --- a/.github/workflows/ubuntu20-arrch64-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu20-arrch64-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu20.04 v9.0.0 build arrch64 +name: ubuntu20.04 v10.0.0 build arrch64 run-name: ubuntu20 arrch64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-arm-ubuntu20: @@ -22,7 +22,7 @@ jobs: install: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 run: | echo "-----------------------" diff --git a/.github/workflows/ubuntu20-v9.0.0-build.yaml b/.github/workflows/ubuntu20-v10.0.0-build.yaml similarity index 76% rename from .github/workflows/ubuntu20-v9.0.0-build.yaml rename to .github/workflows/ubuntu20-v10.0.0-build.yaml index 11d4de4..410211d 100644 --- a/.github/workflows/ubuntu20-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu20-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu20.04 v9.0.0 build x86-64 +name: ubuntu20.04 v10.0.0 build x86-64 run-name: ubuntu20 x86-64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-amd-ubuntu20: @@ -21,7 +21,7 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 cd /workspace/${{ github.repository }} && python3 install.py - name: Build diff --git a/.github/workflows/ubuntu22-arrch64-v9.0.0-build.yaml b/.github/workflows/ubuntu22-arrch64-v10.0.0-build.yaml similarity index 72% rename from .github/workflows/ubuntu22-arrch64-v9.0.0-build.yaml rename to .github/workflows/ubuntu22-arrch64-v10.0.0-build.yaml index 85531a8..df41155 100644 --- a/.github/workflows/ubuntu22-arrch64-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu22-arrch64-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu22.04 v9.0.0 build arrch64 +name: ubuntu22.04 v10.0.0 build arrch64 run-name: ubuntu22 arrch64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-arm-ubuntu22: @@ -22,7 +22,7 @@ jobs: install: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 run: | echo "-----------------------" diff --git a/.github/workflows/ubuntu22-v9.0.0-build.yaml b/.github/workflows/ubuntu22-v10.0.0-build.yaml similarity index 76% rename from .github/workflows/ubuntu22-v9.0.0-build.yaml rename to .github/workflows/ubuntu22-v10.0.0-build.yaml index 3c09fce..527ffb8 100644 --- a/.github/workflows/ubuntu22-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu22-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu22.04 v9.0.0 build x86-64 +name: ubuntu22.04 v10.0.0 build x86-64 run-name: ubuntu22 x86-64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-amd-ubuntu22: @@ -21,7 +21,7 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 cd /workspace/${{ github.repository }} && python3 install.py - name: Build diff --git a/.github/workflows/ubuntu24-v9.0.0-build.yaml b/.github/workflows/ubuntu24-v10.0.0-build.yaml similarity index 76% rename from .github/workflows/ubuntu24-v9.0.0-build.yaml rename to .github/workflows/ubuntu24-v10.0.0-build.yaml index e77ec23..56af5ac 100644 --- a/.github/workflows/ubuntu24-v9.0.0-build.yaml +++ b/.github/workflows/ubuntu24-v10.0.0-build.yaml @@ -1,10 +1,10 @@ -name: ubuntu24.04 v9.0.0 build x86-64 +name: ubuntu24.04 v10.0.0 build x86-64 run-name: ubuntu24 x86-64 on: push: branches: - - v9.0.0 + - v10.0.0 jobs: build-amd-ubuntu24: @@ -21,7 +21,7 @@ jobs: DEBIAN_FRONTEND: noninteractive run: | apt update - apt install -y lsb-release git wget pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev + apt install -y lsb-release git wget libcurl4-openssl-dev pkg-config g++ cmake uuid-dev libncurses5-dev python3-dev autoconf automake libtool libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 cd /workspace/${{ github.repository }} && python3 install.py - name: Build diff --git a/README.md b/README.md index 5fc2fd5..75395dd 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ ```shell sudo apt update -sudo apt install -y wget autoconf automake libtool g++ pkg-config uuid-dev libncurses5-dev python3-dev python3-pip +sudo apt install -y wget libcurl4-openssl-dev autoconf automake libtool g++ pkg-config uuid-dev libncurses5-dev python3-dev python3-pip libeigen3-dev libtiff-dev libsqlite3-dev sqlite3 python3 -m pip install protobuf==3.14.0 ``` From e429b0b8a99e214b252ed34347020ad9e5d952ff Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 21 Dec 2024 15:16:48 +0800 Subject: [PATCH 10/14] feat(cmake): upgrade CXX version to C++17,add v10 dependency library --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b1c5a1..b2d42c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5.1) project(cyber VERSION 10.0.0) # Apollo Version -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) # Apollo v10 set(TARGET_NAME ${PROJECT_NAME}) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(NOT CMAKE_BUILD_TYPE) @@ -47,6 +47,7 @@ pkg_check_modules(Python REQUIRED python3) pkg_check_modules(Uuid REQUIRED uuid) pkg_check_modules(Gflags REQUIRED gflags) pkg_check_modules(NlohmannJson REQUIRED nlohmann_json) +pkg_check_modules(GperfTools REQUIRED libtcmalloc) # set(Python_VERSION "${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}") set(Python_VERSION "${Python_VERSION}") @@ -72,6 +73,7 @@ set(DEPENCENCY_INCLUDE_DIRS ${glog_INCLUDE_DIRS} ${Gflags_INCLUDE_DIRS} ${NlohmannJson_INCLUDE_DIRS} + ${GperfTools_INCLUDE_DIRS} ) set(DEPENCENCY_LIB_DIRS @@ -83,6 +85,7 @@ set(DEPENCENCY_LIB_DIRS ${glog_LIBRARY_DIRS} ${Gflags_LIBRARY_DIRS} ${NlohmannJson_LIBRARY_DIRS} + ${GperfTools_LIBRARY_DIRS} ) set(DEPENCENCY_LIBS @@ -161,6 +164,7 @@ file(GLOB CYBER_SRCS "cyber/transport/*/*.cc" "cyber/*.cc" "cyber/sysmo/*.cc" + "cyber/statistics/*.cc" ${CROUTINE_FILE} ) @@ -179,8 +183,11 @@ target_link_libraries(${TARGET_NAME} ${NlohmannJson_LIBRARIES} ${Protobuf_LIBRARIES} ${Uuid_LIBRARIES} + ${GperfTools_LIBRARIES} # gperftools + profiler # gperftools fastrtps fastcdr + bvar atomic dl rt From 7873a7b9fc6bf39fb5047f8165c355ce6466ec66 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Fri, 27 Dec 2024 17:56:06 +0800 Subject: [PATCH 11/14] feat(v10): Added ros_bridge module --- CMakeLists.txt | 10 ++++++---- cyber/ros_bridge/CMakeLists.txt | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 cyber/ros_bridge/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b2d42c1..0d682d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ find_package(fastrtps REQUIRED) find_package(fastcdr REQUIRED) find_package(glog REQUIRED) find_package(Protobuf REQUIRED) +find_package(Eigen3 REQUIRED) # find_package(Python REQUIRED COMPONENTS Interpreter Development) pkg_check_modules(Python REQUIRED python3) pkg_check_modules(Uuid REQUIRED uuid) @@ -68,6 +69,7 @@ set(DEPENCENCY_INCLUDE_DIRS ${fastcdr_INCLUDE_DIR} ${fastrtps_INCLUDE_DIR} ${Protobuf_INCLUDE_DIRS} + ${EIGEN3_INCLUDE_DIRS} ${Python_INCLUDE_DIRS} ${Uuid_INCLUDE_DIRS} ${glog_INCLUDE_DIRS} @@ -100,10 +102,9 @@ include_directories( link_directories(${DEPENCENCY_LIB_DIRS}) -file(GLOB CYBER_PROTO_FILES - "${CMAKE_CURRENT_SOURCE_DIR}/modules/common_msgs/**/*.proto" - "${CMAKE_CURRENT_SOURCE_DIR}/cyber/proto/*.proto" - "${CMAKE_CURRENT_SOURCE_DIR}/cyber/examples/proto/*.proto" +file(GLOB_RECURSE CYBER_PROTO_FILES + "${CMAKE_CURRENT_SOURCE_DIR}/modules/*.proto" + "${CMAKE_CURRENT_SOURCE_DIR}/cyber/*.proto" ) if(${CYBER_MSGS_CACHE}) @@ -194,6 +195,7 @@ target_link_libraries(${TARGET_NAME} ) add_subdirectory(cyber/mainboard) +add_subdirectory(cyber/ros_bridge) add_subdirectory(cyber/examples) add_subdirectory(cyber/python) add_subdirectory(cyber/tools) diff --git a/cyber/ros_bridge/CMakeLists.txt b/cyber/ros_bridge/CMakeLists.txt new file mode 100644 index 0000000..19ef058 --- /dev/null +++ b/cyber/ros_bridge/CMakeLists.txt @@ -0,0 +1,31 @@ +project(ros_bridge VERSION 10.0.0) + +find_package(PROJ REQUIRED) + +include_directories( + ${PROJ_INCLUDE_DIRS} +) + +link_directories( + ${PROJ_LIBRARY_DIRS} +) + +file(GLOB_RECURSE ROS_BRIDGE_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/*.cc" +) + +add_executable(ros_bridge + ${ROS_BRIDGE_SOURCES} +) + +target_link_libraries(ros_bridge + ${TARGET_NAME} + ${PROJ_LIBRARIES} + ${GperfTools_LIBRARIES} + profiler + pthread +) + +set_target_properties(ros_bridge PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/cyber/ros_bridge +) From df2c9dba9bebcd520d16dd98796af29312007042 Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 21 Dec 2024 15:21:41 +0800 Subject: [PATCH 12/14] chore(cyber): comment out the eprosima_wrap macro definition --- cyber/base/macros.h | 2 +- cyber/ros_bridge/common/macros.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cyber/base/macros.h b/cyber/base/macros.h index 96442a3..1d8618d 100644 --- a/cyber/base/macros.h +++ b/cyber/base/macros.h @@ -20,7 +20,7 @@ #include #include -#define eprosima eprosima_wrap +// #define eprosima eprosima_wrap #if __GNUC__ >= 3 #define cyber_likely(x) (__builtin_expect((x), 1)) diff --git a/cyber/ros_bridge/common/macros.h b/cyber/ros_bridge/common/macros.h index feccf11..1e23af1 100644 --- a/cyber/ros_bridge/common/macros.h +++ b/cyber/ros_bridge/common/macros.h @@ -20,7 +20,7 @@ // replacement macro for eprosima namespace to eprosima_wrap // for adapting different version fastdds on a single process #ifndef eprosima -#define eprosima eprosima_wrap +// #define eprosima eprosima_wrap #endif #endif // ROS_BRIDGE_MACROS_H_ From 8e025e7410289e66271666f475b701b9fd73917b Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Fri, 27 Dec 2024 11:21:31 +0800 Subject: [PATCH 13/14] fix(recorder): cyber_recorder bugfix --- cyber/tools/cyber_recorder/recorder.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cyber/tools/cyber_recorder/recorder.cc b/cyber/tools/cyber_recorder/recorder.cc index bceee68..ec8303b 100644 --- a/cyber/tools/cyber_recorder/recorder.cc +++ b/cyber/tools/cyber_recorder/recorder.cc @@ -202,8 +202,16 @@ bool Recorder::InitReadersImpl() { } // listen new writers in future - change_conn_ = channel_manager->AddChangeListener( - std::bind(&Recorder::TopologyCallback, this, std::placeholders::_1)); + // must use async callback, otherwise deadlock may be occurred. + auto topology_callback = + [this](const apollo::cyber::proto::ChangeMsg& change_msg) { + apollo::cyber::Async( + [this, change_msg] { this->TopologyCallback(change_msg); }); + }; + change_conn_ = channel_manager->AddChangeListener(topology_callback); + // change_conn_ = channel_manager->AddChangeListener( + // std::bind(&Recorder::TopologyCallback, this, std::placeholders::_1)); + if (!change_conn_.IsConnected()) { AERROR << "change connection is not connected"; return false; From bca7c59c7956fc020279ca6772f1f1c0f1b383ab Mon Sep 17 00:00:00 2001 From: minhanghuang Date: Sat, 18 Jan 2025 14:52:24 +0800 Subject: [PATCH 14/14] feat(third_party): Added Fast-CDR-v2.2.2 patch file --- install.py | 1 + scripts/Fast-CDR_v2.2.2.patch | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 scripts/Fast-CDR_v2.2.2.patch diff --git a/install.py b/install.py index 702d288..5f0efe8 100644 --- a/install.py +++ b/install.py @@ -355,6 +355,7 @@ def _clone_dds2(self): os.chdir(self._current_path) os.chdir(os.path.join(self._dowload_path, "Fast-CDR")) + self._cmd("patch -p1 < {}".format(os.path.join(self._current_path,"scripts/Fast-CDR_v2.2.2.patch"))) self._cmd("mkdir -p build") os.chdir("build") self._cmd("cmake -DCMAKE_INSTALL_PREFIX={} -DBUILD_SHARED_LIBS=ON ..".format( diff --git a/scripts/Fast-CDR_v2.2.2.patch b/scripts/Fast-CDR_v2.2.2.patch new file mode 100644 index 0000000..7f5c5ed --- /dev/null +++ b/scripts/Fast-CDR_v2.2.2.patch @@ -0,0 +1,75 @@ +diff --git a/include/fastcdr/Cdr.h b/include/fastcdr/Cdr.h +index ba51fa2..d90dafb 100644 +--- a/include/fastcdr/Cdr.h ++++ b/include/fastcdr/Cdr.h +@@ -689,6 +689,9 @@ public: + Cdr_DllAPI Cdr& serialize( + const char* string_t); + ++ Cdr_DllAPI Cdr& serialize( ++ const char* string_t, size_t str_length); ++ + /*! + * @brief This function serializes a wstring. + * @param string_t The pointer to the wstring that will be serialized in the buffer. +@@ -708,7 +711,7 @@ public: + Cdr& serialize( + const std::string& string_t) + { +- return serialize(string_t.c_str()); ++ return serialize(string_t.c_str(), string_t.size()); + } + + /*! +diff --git a/src/cpp/Cdr.cpp b/src/cpp/Cdr.cpp +index 189ee21..3d1a5a5 100644 +--- a/src/cpp/Cdr.cpp ++++ b/src/cpp/Cdr.cpp +@@ -813,6 +813,47 @@ Cdr& Cdr::serialize( + return *this; + } + ++Cdr& Cdr::serialize( ++ const char* string_t, size_t str_length) ++{ ++ uint32_t length = 0; ++ ++ if (string_t != nullptr) ++ { ++ // length = size_to_uint32(strlen(string_t)) + 1; ++ length = (uint32_t)str_length + 1; ++ } ++ ++ if (length > 0) ++ { ++ Cdr::state state_before_error(*this); ++ serialize(length); ++ ++ if (((end_ - offset_) >= length) || resize(length)) ++ { ++ // Save last datasize. ++ last_data_size_ = sizeof(uint8_t); ++ ++ offset_.memcopy(string_t, length); ++ offset_ += length; ++ } ++ else ++ { ++ set_state(state_before_error); ++ throw NotEnoughMemoryException(NotEnoughMemoryException::NOT_ENOUGH_MEMORY_MESSAGE_DEFAULT); ++ } ++ } ++ else ++ { ++ serialize(length); ++ } ++ ++ serialized_member_size_ = SERIALIZED_MEMBER_SIZE; ++ ++ return *this; ++} ++ ++ + Cdr& Cdr::serialize( + const wchar_t* string_t) + {