From 5ddcd8eb6a8e0f87464fa66cb56feee931654af5 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Mon, 3 Apr 2023 17:26:06 +0000 Subject: [PATCH 1/6] Remove ignition namespaced files for msgs10 Signed-off-by: Michael Carroll --- CMakeLists.txt | 24 ++----- include/CMakeLists.txt | 1 - include/ignition/msgs.hh | 19 ----- include/ignition/msgs/Export.hh | 19 ----- include/ignition/msgs/Factory.hh | 22 ------ include/ignition/msgs/Filesystem.hh | 19 ----- include/ignition/msgs/MessageTypes.hh | 19 ----- .../ignition/msgs/PointCloudPackedUtils.hh | 19 ----- include/ignition/msgs/SuppressWarning.hh | 71 ------------------- include/ignition/msgs/Utility.hh | 19 ----- include/ignition/msgs/config.hh | 46 ------------ src/CMakeLists.txt | 13 +--- test/integration/deprecated_TEST.cc | 33 --------- tools/gz_msgs_generate.py | 40 +---------- 14 files changed, 7 insertions(+), 357 deletions(-) delete mode 100644 include/ignition/msgs.hh delete mode 100644 include/ignition/msgs/Export.hh delete mode 100644 include/ignition/msgs/Factory.hh delete mode 100644 include/ignition/msgs/Filesystem.hh delete mode 100644 include/ignition/msgs/MessageTypes.hh delete mode 100644 include/ignition/msgs/PointCloudPackedUtils.hh delete mode 100644 include/ignition/msgs/SuppressWarning.hh delete mode 100644 include/ignition/msgs/Utility.hh delete mode 100644 include/ignition/msgs/config.hh delete mode 100644 test/integration/deprecated_TEST.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 0943d5ac..48e1055d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,19 +45,11 @@ endif() # CMake cache variable: # > cmake -GZ_MSGS_GEN_EXECUTABLE=/bin/gz_msgs_gen .. -# TODO(CH3): Deprecated. Remove IGN_MSGS CMake variables on tick-tock. -if(INSTALL_IGN_MSGS_GEN_EXECUTABLE) - message(WARNING "INSTALL_IGN_MSGS_GEN_EXECUTABLE is deprecated, use INSTALL_GZ_MSGS_GEN_EXECUTABLE instead") - set(INSTALL_GZ_MSGS_GEN_EXECUTABLE ${INSTALL_IGN_MSGS_GEN_EXECUTABLE}) -else() - option( - INSTALL_GZ_MSGS_GEN_EXECUTABLE - "Install the gz_msgs_gen executable." - OFF) - set(INSTALL_IGN_MSGS_GEN_EXECUTABLE ${INSTALL_GZ_MSGS_GEN_EXECUTABLE}) -endif() +option( + INSTALL_GZ_MSGS_GEN_EXECUTABLE + "Install the gz_msgs_gen executable." + OFF) -mark_as_advanced(INSTALL_IGN_MSGS_GEN_EXECUTABLE) mark_as_advanced(INSTALL_GZ_MSGS_GEN_EXECUTABLE) set( @@ -67,14 +59,6 @@ set( "gz_msgs_gen executable used in the gz_msgs_protoc CMake function.") mark_as_advanced(GZ_MSGS_GEN_EXECUTABLE) -# TODO(CH3): Deprecated. Remove IGN_MSGS CMake variables on tick-tock. -set( - IGN_MSGS_GEN_EXECUTABLE - "$" - CACHE STRING - "gz_msgs_gen executable used in the gz_msgs_protoc CMake function.") -mark_as_advanced(IGN_MSGS_GEN_EXECUTABLE) - #============================================================================ # Search for project-specific dependencies #============================================================================ diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 992a1312..a35a0475 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,2 +1 @@ add_subdirectory(gz) -install(DIRECTORY ignition DESTINATION ${GZ_INCLUDE_INSTALL_DIR_FULL}) diff --git a/include/ignition/msgs.hh b/include/ignition/msgs.hh deleted file mode 100644 index eef399f2..00000000 --- a/include/ignition/msgs.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/Export.hh b/include/ignition/msgs/Export.hh deleted file mode 100644 index e23708f4..00000000 --- a/include/ignition/msgs/Export.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/Factory.hh b/include/ignition/msgs/Factory.hh deleted file mode 100644 index ec2f3b74..00000000 --- a/include/ignition/msgs/Factory.hh +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 - -#define IGN_REGISTER_STATIC_MSG(_msgtype, _classname) \ - GZ_REGISTER_STATIC_MSG(_msgtype, _classname) diff --git a/include/ignition/msgs/Filesystem.hh b/include/ignition/msgs/Filesystem.hh deleted file mode 100644 index 15c0f26f..00000000 --- a/include/ignition/msgs/Filesystem.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2018 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/MessageTypes.hh b/include/ignition/msgs/MessageTypes.hh deleted file mode 100644 index 0789efcc..00000000 --- a/include/ignition/msgs/MessageTypes.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2017 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/PointCloudPackedUtils.hh b/include/ignition/msgs/PointCloudPackedUtils.hh deleted file mode 100644 index 15ab1c7e..00000000 --- a/include/ignition/msgs/PointCloudPackedUtils.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/SuppressWarning.hh b/include/ignition/msgs/SuppressWarning.hh deleted file mode 100644 index 3ba195a5..00000000 --- a/include/ignition/msgs/SuppressWarning.hh +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 Open Source Robotics Foundation - * - * 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 IGNITION_MSGS_SUPPRESSWARNING_HH_ -#define IGNITION_MSGS_SUPPRESSWARNING_HH_ - -#include - -#pragma message("ign-msgs SuppressWarning is deprecated, use ign-utils") - -// This header contains cross-platform macros for suppressing warnings. Please -// only use these macros responsibly when you are certain that the compiler is -// producing a warning that is not applicable to the specific instance. Do not -// use these macros to ignore legitimate warnings, even if you may find them -// irritating. - -/* - * Usage example: - * - * SomeClass* ptr = CreatePtr(); - * IGN_MSGS_WARN_IGNORE__DELETE_NON_VIRTUAL_DESTRUCTOR - * delete ptr; - * IGN_MSGS_WARN_RESUME__DELETE_NON_VIRTUAL_DESTRUCTOR - * - */ - -// Be sure to call the IGN_MSGS_WARN_RESUME__XXXXX macro at the end of the -// block of code where the warning suppression is needed. Otherwise, you might -// inadvertently suppress legitimate warnings. - -// ---- List of available suppressions ---- - -/// \brief Compilers might warn about deleting a pointer to a class that has -/// virtual functions without a virtual destructor or a `final` declaration, -/// because the pointer might secretly be pointing to a more derived class type. -/// We want to suppress this warning when we know for certain (via the design -/// of our implementation) that the pointer is definitely not pointing to a more -/// derived type. -#define IGN_MSGS_WARN_IGNORE__DELETE_NON_VIRTUAL_DESTRUCTOR \ - IGN_UTILS_WARN_IGNORE__NON_VIRTUAL_DESTRUCTOR - -#define IGN_MSGS_WARN_RESUME__DELETE_NON_VIRTUAL_DESTRUCTOR \ - IGN_UTILS_WARN_RESUME__NON_VIRTUAL_DESTRUCTOR - - -/// \brief Microsoft Visual Studio does not automatically export the interface -/// information for member variables that belong to interface classes of a DLL. -/// Instead it issues this warning. When the member variable is private, we -/// choose to suppress the warning instead of needlessly adding the class -/// information to the DLL interface. -#define IGN_MSGS_WARN_IGNORE__DLL_INTERFACE_MISSING \ - IGN_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - -#define IGN_MSGS_WARN_RESUME__DLL_INTERFACE_MISSING \ - IGN_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - -#endif diff --git a/include/ignition/msgs/Utility.hh b/include/ignition/msgs/Utility.hh deleted file mode 100644 index 69b42a00..00000000 --- a/include/ignition/msgs/Utility.hh +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 diff --git a/include/ignition/msgs/config.hh b/include/ignition/msgs/config.hh deleted file mode 100644 index cfe2ec2b..00000000 --- a/include/ignition/msgs/config.hh +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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 IGNITION_MSGS__CONFIG_HH_ -#define IGNITION_MSGS__CONFIG_HH_ - -#include - -#define IGNITION_MSGS_MAJOR_VERSION GZ_MSGS_MAJOR_VERSION -#define IGNITION_MSGS_MINOR_VERSION GZ_MSGS_MINOR_VERSION -#define IGNITION_MSGS_PATCH_VERSION GZ_MSGS_PATCH_VERSION - -#define IGNITION_MSGS_VERSION GZ_MSGS_VERSION -#define IGNITION_MSGS_VERSION_FULL GZ_MSGS_VERSION_FULL - -#define IGNITION_MSGS_VERSION_NAMESPACE GZ_MSGS_VERSION_NAMESPACE - -#define IGNITION_MSGS_VERSION_HEADER GZ_MSGS_VERSION_HEADER - -namespace gz -{ -} - -namespace ignition -{ - #ifndef SUPPRESS_IGNITION_HEADER_DEPRECATION - #pragma message("ignition namespace is deprecated! Use gz instead!") - #endif - using namespace gz; -} - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56499bc8..ed0dafc0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,9 +73,7 @@ function(gz_msgs_protoc) set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.h") # Full path to generated detail header (${PROJECT_BINARY_DIR}/include/gz/msgs/details/foo.pb.h) set(output_detail_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/details/${FIL_WE}.pb.h") - # Full path to generated ignition header (${PROJECT_BINARY_DIR}/include/ignition/msgs/foo.pb.h) - set(output_ign_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}/ignition/msgs/${FIL_WE}.pb.h") - # Full path to generated ignition header (${PROJECT_BINARY_DIR}/include/foo.pb.cc) + # Full path to generated source (${PROJECT_BINARY_DIR}/include/foo.pb.cc) set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.cc") # Generate a clean relative path (gz/msgs/foo.pb.h) @@ -116,7 +114,6 @@ function(gz_msgs_protoc) --gz-generator-bin "${GZ_MSGS_GEN_EXECUTABLE}" --generate-cpp "${gz_msgs_protoc_GENERATE_CPP}" --generate-ruby "${gz_msgs_protoc_GENERATE_RUBY}" - --generate-ignition "TRUE" --output-cpp-path "${gz_msgs_protoc_OUTPUT_CPP_DIR}" --output-ruby-path "${gz_msgs_protoc_OUTPUT_RUBY_DIR}" --proto-path "${gz_msgs_protoc_PROTO_PATH}" @@ -187,9 +184,6 @@ endif() set_source_files_properties(${gen_headers} ${gen_ign_headers} ${gen_detail_headers} ${gen_sources} ${gen_ruby_scripts} PROPERTIES GENERATED TRUE) -message(STATUS "Installing Ruby messages to ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/ignition/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}") -install(FILES ${gen_ruby_scripts} DESTINATION ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/ignition/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}) - message(STATUS "Installing Ruby messages to ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/gz/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}") install(FILES ${gen_ruby_scripts} DESTINATION ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/gz/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}) @@ -203,11 +197,6 @@ gz_install_includes( "${GZ_INCLUDE_INSTALL_DIR_POSTFIX}/gz/${IGN_DESIGNATION}/details" ${gen_detail_headers}) -# Install ignition/msgs -gz_install_includes( - "${GZ_INCLUDE_INSTALL_DIR_POSTFIX}/ignition/msgs" - ${gen_ign_headers}) - ################################################## # Generate gz/msgs/MessageTypes.hh foreach (hdr ${gen_includes}) diff --git a/test/integration/deprecated_TEST.cc b/test/integration/deprecated_TEST.cc deleted file mode 100644 index 409fe449..00000000 --- a/test/integration/deprecated_TEST.cc +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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 - -#define SUPPRESS_IGNITION_HEADER_DEPRECATION - -#include -#include - -///////////////////////////////////////////////// -// Make sure the ignition namespace still works -TEST(Deprecated, IgnitionNamespace) -{ - ignition::msgs::Factory factory; - (void)factory; -} - -#undef SUPPRESS_IGNITION_HEADER_DEPRECATION diff --git a/tools/gz_msgs_generate.py b/tools/gz_msgs_generate.py index a86bfd6e..10ee41ea 100755 --- a/tools/gz_msgs_generate.py +++ b/tools/gz_msgs_generate.py @@ -36,9 +36,6 @@ def main(argv=sys.argv[1:]): parser.add_argument( '--generate-ruby', help='Flag to indicate if Ruby bindings should be generated') - parser.add_argument( - '--generate-ignition', - help='Flag to indicate if ignition/ headers should be generated') parser.add_argument( '--output-cpp-path', help='The basepath of the generated C++ files') @@ -61,10 +58,10 @@ def main(argv=sys.argv[1:]): if args.generate_cpp: cmd += [f'--plugin=protoc-gen-ignmsgs={args.gz_generator_bin}'] - cmd += [f'--cpp_out=dllexport_decl=IGNITION_MSGS_VISIBLE:{args.output_cpp_path}'] + cmd += [f'--cpp_out=dllexport_decl=GZ_MSGS_VISIBLE:{args.output_cpp_path}'] cmd += [f'--ignmsgs_out={args.output_cpp_path}'] if args.generate_ruby: - cmd += [f'--ruby_out=dllexport_decl=IGNITION_MSGS_VISIBLE:{args.output_ruby_path}'] + cmd += [f'--ruby_out=dllexport_decl=GZ_MSGS_VISIBLE:{args.output_ruby_path}'] cmd += [args.input_path] try: @@ -99,38 +96,5 @@ def main(argv=sys.argv[1:]): print(f'Failed to manipulate gz-msgs headers: {e}') sys.exit(-1) - ignition_header_dir = os.path.join(args.output_cpp_path, 'ignition', 'msgs') - ignition_header = proto_file.split(os.sep) - ignition_header[0] = 'ignition' - - proto_name = ignition_header[2] - - ignition_header = os.path.join(*ignition_header) - ignition_header = os.path.join(args.output_cpp_path, ignition_header + ".pb.h") - - os.makedirs(os.path.join(args.output_cpp_path, ignition_header_dir), - exist_ok=True) - - with open(ignition_header, 'w') as f: - f.write('''/* - * Copyright (C) 2022 Open Source Robotics Foundation - * - * 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. - * - */ - ''') - f.write(f'#include \n') - f.write('#include \n') - if __name__ == '__main__': sys.exit(main()) From 007512e2e3b7423544a91ff713a4f9bdcfb76037 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Wed, 5 Apr 2023 20:26:27 +0000 Subject: [PATCH 2/6] Refactor factory: * Split into MessageFactory, which is a non-static variant, should help with any potential ODR issues down the road * Refactor Factory to just be wrapper around a message factory singleton * Remove filesystem.hh * General cleanups Signed-off-by: Michael Carroll --- include/gz/msgs/Factory.hh | 62 ++-- include/gz/msgs/Filesystem.hh | 93 ------ include/gz/msgs/MessageFactory.hh | 101 +++++++ .../gz/msgs/detail/dynamic_message_cast.hh | 47 +++ src/CMakeLists.txt | 3 +- src/DynamicFactory.cc | 131 +++++++++ src/DynamicFactory.hh | 87 ++++++ src/Factory.cc | 278 +----------------- src/Filesystem.cc | 272 ----------------- src/MessageFactory.cc | 111 +++++++ 10 files changed, 507 insertions(+), 678 deletions(-) delete mode 100644 include/gz/msgs/Filesystem.hh create mode 100644 include/gz/msgs/MessageFactory.hh create mode 100644 include/gz/msgs/detail/dynamic_message_cast.hh create mode 100644 src/DynamicFactory.cc create mode 100644 src/DynamicFactory.hh delete mode 100644 src/Filesystem.cc create mode 100644 src/MessageFactory.cc diff --git a/include/gz/msgs/Factory.hh b/include/gz/msgs/Factory.hh index 75fdd113..87f7ee00 100644 --- a/include/gz/msgs/Factory.hh +++ b/include/gz/msgs/Factory.hh @@ -17,15 +17,6 @@ #ifndef GZ_MSGS_FACTORY_HH_ #define GZ_MSGS_FACTORY_HH_ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4100 4512 4127 4068 4244 4267 4251 4146) -#endif -#include -#ifdef _MSC_VER -#pragma warning(pop) -#endif - #include #include #include @@ -33,6 +24,7 @@ #include "gz/msgs/config.hh" #include "gz/msgs/Export.hh" +#include "gz/msgs/detail/dynamic_message_cast.hh" namespace gz { @@ -40,22 +32,23 @@ namespace gz { // Inline bracket to help doxygen filtering. inline namespace GZ_MSGS_VERSION_NAMESPACE { - // - /// \typedef FactoryFn - /// \brief Prototype for message factory generation - typedef std::unique_ptr (*FactoryFn) (); - /// \class Factory Factory.hh gz/msgs.hh + /// This class will also try to load all Protobuf descriptors specified /// \brief A factory that generates protobuf message based on a string type. - /// This class will also try to load all Protobuf descriptors specified /// in the GZ_DESCRIPTOR_PATH environment variable on program start. + class GZ_MSGS_VISIBLE Factory { + public: using Message = google::protobuf::Message; + public: using MessagePtr = std::unique_ptr; + public: using FactoryFn = + std::function; + /// \brief Register a message. /// \param[in] _msgType Type of message to register. /// \param[in] _factoryfn Function that generates the message. - public: static void Register(const std::string &_msgType, - FactoryFn _factoryfn); + public: static void + Register(const std::string &_msgType, FactoryFn _factoryFn); /// \brief Create a new instance of a message. /// \param[in] _msgType Type of message to create. @@ -64,16 +57,7 @@ namespace gz public: template static std::unique_ptr New(const std::string &_msgType) { - auto msgType = _msgType; - if (msgType.find("ignition") == 0) - { - msgType.replace(0, 8, "gz"); - std::cerr << "Trying to create deprecated message type [" - << _msgType << "]. Using [" << msgType - << "] instead." << std::endl; - } - return std::unique_ptr( - static_cast(New(msgType).release())); + return detail::dynamic_message_cast(New(_msgType)); } /// \brief Create a new instance of a message. @@ -85,32 +69,23 @@ namespace gz static std::unique_ptr New(const std::string &_msgType, const std::string &_args) { - auto msgType = _msgType; - if (msgType.find("ignition") == 0) - { - msgType.replace(0, 8, "gz"); - std::cerr << "Trying to create deprecated message type [" - << _msgType << "]. Using [" << msgType - << "] instead." << std::endl; - } - return std::unique_ptr( - static_cast(New(msgType, _args).release())); + return detail::dynamic_message_cast(New(_msgType, _args)); } /// \brief Create a new instance of a message. /// \param[in] _msgType Type of message to create. /// \return Pointer to a google protobuf message. Null if the message /// type could not be handled. - public: static std::unique_ptr New( - const std::string &_msgType); + public: static MessagePtr + New(const std::string &_msgType); /// \brief Create a new instance of a message. /// \param[in] _msgType Type of message to create. /// \param[in] _args Message arguments. This will populate the message. /// \return Pointer to a google protobuf message. Null if the message /// type could not be handled. - public: static std::unique_ptr New( - const std::string &_msgType, const std::string &_args); + public: static MessagePtr + New(const std::string &_msgType, const std::string &_args); /// \brief Get all the message types /// \param[out] _types Vector of strings of the message types. @@ -120,9 +95,6 @@ namespace gz /// \param[in] _paths A set of directories containing .desc decriptor /// files. Each directory should be separated by ":". public: static void LoadDescriptors(const std::string &_paths); - - /// \brief A list of registered message types - private: static std::map *msgMap; }; /// \brief Static message registration macro @@ -132,7 +104,7 @@ namespace gz /// \param[in] _classname Class name for message. #define GZ_REGISTER_STATIC_MSG(_msgtype, _classname) \ GZ_MSGS_VISIBLE \ - std::unique_ptr New##_classname() \ + gz::msgs::Factory::MessagePtr New##_classname() \ { \ return std::unique_ptr(\ new gz::msgs::_classname); \ diff --git a/include/gz/msgs/Filesystem.hh b/include/gz/msgs/Filesystem.hh deleted file mode 100644 index 9fa6ef05..00000000 --- a/include/gz/msgs/Filesystem.hh +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2018 Open Source Robotics Foundation - * - * 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 GZ_MSGS_FILESYSTEM_HH_ -#define GZ_MSGS_FILESYSTEM_HH_ - -#include -#include - -#include -#include - -namespace gz -{ - namespace msgs - { - /// \brief Options for how to handle errors that occur in functions that - /// manipulate the filesystem. - enum FilesystemWarningOp - { - /// \brief Errors that occur during filesystem manipulation should be - /// logged as warnings using gzwarn. (Recommended) - FSWO_LOG_WARNINGS = 0, - - /// \brief Errors that occur during filesystem manipulation should not be - /// logged. The user will be responsible for checking the system's error - /// flags. - FSWO_SUPPRESS_WARNINGS - }; - - // /// \internal - class DirIterPrivate; - - /// \class DirIter Filesystem.hh - /// \brief A class for iterating over all items in a directory. - class GZ_MSGS_VISIBLE DirIter - { - /// \brief Constructor. - /// \param[in] _in Directory to iterate over. - public: explicit DirIter(const std::string &_in); - - /// \brief Constructor for end element. - public: DirIter(); - - /// \brief Dereference operator; returns current directory record. - /// \return A string representing the entire path of the directory record. - public: std::string operator*() const; - - /// \brief Pre-increment operator; moves to next directory record. - /// \return This iterator. - public: const DirIter& operator++(); - - /// \brief Comparison operator to see if this iterator is at the - /// same point as another iterator. - /// \param[in] _other The other iterator to compare against. - /// \return true if the iterators are equal, false otherwise. - public: bool operator!=(const DirIter &_other) const; - - /// \brief Destructor - public: ~DirIter(); - - /// \brief Move to the next directory record, skipping . and .. records. - private: void Next(); - - /// \brief Set the internal variable to the empty string. - private: void SetInternalEmpty(); - - /// \brief Close an open directory handle. - private: void CloseHandle(); - - GZ_UTILS_WARN_IGNORE__DLL_INTERFACE_MISSING - /// \brief Private data. - private: std::unique_ptr dataPtr; - GZ_UTILS_WARN_RESUME__DLL_INTERFACE_MISSING - }; - } -} - -#endif diff --git a/include/gz/msgs/MessageFactory.hh b/include/gz/msgs/MessageFactory.hh new file mode 100644 index 00000000..c278d1ac --- /dev/null +++ b/include/gz/msgs/MessageFactory.hh @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 GZ_MSGS_MESSAGE_FACTORY_HH_ +#define GZ_MSGS_MESSAGE_FACTORY_HH_ + +#include +#include +#include +#include + +#include "gz/msgs/config.hh" +#include "gz/msgs/Export.hh" +#include "gz/msgs/detail/dynamic_message_cast.hh" + +namespace gz::msgs { + /// Forward declarations + class DynamicFactory; + + // Inline bracket to help doxygen filtering. + inline namespace GZ_MSGS_VERSION_NAMESPACE { + + class GZ_MSGS_VISIBLE MessageFactory + { + public: using Message = google::protobuf::Message; + public: using MessagePtr = std::unique_ptr; + public: using FactoryFn = std::function; + + public: MessageFactory(); + + /// \brief Register a message. + /// \param[in] _msgType Type of message to register. + /// \param[in] _factoryfn Function that generates the message. + public: void Register(const std::string &_msgType, FactoryFn _factoryFn); + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: template + std::unique_ptr New(const std::string &_msgType) + { + return detail::dynamic_message_cast(New(_msgType)); + } + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \param[in] _args Message arguments. This will populate the message. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: template + std::unique_ptr New(const std::string &_msgType, + const std::string &_args) + { + return detail::dynamic_message_cast(New(_msgType, _args)); + } + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: MessagePtr New(const std::string &_msgType); + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \param[in] _args Message arguments. This will populate the message. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: MessagePtr New( + const std::string &_msgType, const std::string &_args); + + /// \brief Get all the message types + /// \param[out] _types Vector of strings of the message types. + public: void Types(std::vector &_types); + + /// \brief Load a collection of descriptor .desc files. + /// \param[in] _paths A set of directories containing .desc decriptor + /// files. Each directory should be separated by ":". + public: void LoadDescriptors(const std::string &_paths); + + /// \brief A list of registered message types + private: std::map msgMap; + + private: std::unique_ptr dynamicFactory; + }; +} +} // namespace gz::msgs +#endif // GZ_MSGS_MESSAGE_FACTORY_HH_ diff --git a/include/gz/msgs/detail/dynamic_message_cast.hh b/include/gz/msgs/detail/dynamic_message_cast.hh new file mode 100644 index 00000000..d9600b8c --- /dev/null +++ b/include/gz/msgs/detail/dynamic_message_cast.hh @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * 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 GZ_MSGS_DETAIL_DYNAMIC_POINTER_CAST_HH_ +#define GZ_MSGS_DETAIL_DYNAMIC_POINTER_CAST_HH_ + +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4100 4512 4127 4068 4244 4267 4251 4146) +#endif +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +namespace gz::msgs::detail +{ + +template +std::unique_ptr dynamic_message_cast(std::unique_ptr &&_baseMsg) +{ + auto converted = std::unique_ptr{dynamic_cast(_baseMsg.get())}; + if (converted) { + (void) _baseMsg.release(); + } + return converted; +} + +} // namespace gz::msgs::detail + +#endif // GZ_MSGS_DETAIL_DYNAMIC_POINTER_CAST_HH_ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ed0dafc0..672c936c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -214,8 +214,9 @@ gz_install_includes( # Build the main library gz_create_core_library(SOURCES ${gen_sources} + ${PROJECT_SOURCE_DIR}/src/DynamicFactory.cc ${PROJECT_SOURCE_DIR}/src/Factory.cc - ${PROJECT_SOURCE_DIR}/src/Filesystem.cc + ${PROJECT_SOURCE_DIR}/src/MessageFactory.cc ${PROJECT_SOURCE_DIR}/src/gz.cc ${PROJECT_SOURCE_DIR}/src/Utility.cc ) diff --git a/src/DynamicFactory.cc b/src/DynamicFactory.cc new file mode 100644 index 00000000..111b1d59 --- /dev/null +++ b/src/DynamicFactory.cc @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 "DynamicFactory.hh" + +using namespace gz; +using namespace msgs; + +////////////////////////////////////////////////// +/// \brief split at a one character delimiter to get a vector of something +/// \param[in] _orig The string to split +/// \param[in] _delim a character to split the string at +/// \returns vector of split pieces of the string excluding the delimiter +std::vector split(const std::string &_orig, char _delim) +{ + std::vector pieces; + size_t pos1 = 0; + size_t pos2 = _orig.find(_delim); + while (pos2 != std::string::npos) + { + pieces.push_back(_orig.substr(pos1, pos2-pos1)); + pos1 = pos2+1; + pos2 = _orig.find(_delim, pos2+1); + } + pieces.push_back(_orig.substr(pos1, _orig.size()-pos1)); + return pieces; +} + +////////////////////////////////////////////////// +DynamicFactory::DynamicFactory() +{ + // Try to get the list of paths from an environment variable. + const char *descPaths = std::getenv("GZ_DESCRIPTOR_PATH"); + + // Load all the descriptors found in the paths set with GZ_DESCRIPTOR_PATH. + this->LoadDescriptors(descPaths); +} + +////////////////////////////////////////////////// +void DynamicFactory::LoadDescriptors(const std::string &_paths) +{ + if (_paths.empty()) + return; + + // Split all the directories containing .desc files. + std::vector descDirs = split(_paths, ':'); + + for (const std::string &descDir : descDirs) + { + for (auto const &dirIter : std::filesystem::directory_iterator{descDir}) + { + // Ignore files without the .desc extension. + if (dirIter.path().extension() != ".desc") + continue; + + std::ifstream ifs(dirIter.path().string(), std::ifstream::in); + if (!ifs.is_open()) + { + std::cerr << "DynamicFactory(): Unable to open [" << dirIter.path() << "]" + << std::endl; + continue; + } + + google::protobuf::FileDescriptorSet fileDescriptorSet; + if (!fileDescriptorSet.ParseFromIstream(&ifs)) + { + std::cerr << "DynamicFactory(): Unable to parse descriptor set from [" + << dirIter.path() << "]" << std::endl; + continue; + } + + for (const google::protobuf::FileDescriptorProto &fileDescriptorProto : + fileDescriptorSet.file()) + { + if (!pool.BuildFile(fileDescriptorProto)) + { + std::cerr << "DynamicFactory(). Unable to place descriptors from [" + << dirIter.path() << "] in the descriptor pool" << std::endl; + } + } + } + } +} + +////////////////////////////////////////////////// +DynamicFactory::MessagePtr DynamicFactory::New(const std::string &_msgType) +{ + auto msgType = _msgType; + + // Shortcut if the type has been already registered. + auto message_it = dynamicMsgMap.find(msgType); + if (message_it != dynamicMsgMap.end()) + return message_it ->second(); + + // Nothing to do if we don't know about this type in the descriptor map. + auto descriptor = pool.FindMessageTypeByName(msgType); + if (!descriptor) + return nullptr; + + google::protobuf::Message *msgPtr( + dynamicMessageFactory.GetPrototype(descriptor)->New()); + + // Create the lambda for registration purposes. + auto f = [msgPtr]() -> MessagePtr + { + MessagePtr ptr(msgPtr->New()); + return ptr; + }; + + // Register the new type for the future. + dynamicMsgMap[_msgType] = f; + + return f(); +} diff --git a/src/DynamicFactory.hh b/src/DynamicFactory.hh new file mode 100644 index 00000000..7dfd0dd9 --- /dev/null +++ b/src/DynamicFactory.hh @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 DYNAMIC_FACTORY_HH_ +#define DYNAMIC_FACTORY_HH_ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4146 4251) +#endif + +#include +#include + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include +#include +#include + + +namespace gz::msgs { + +///////////////////////////////////////////////// +/// \brief A factory class to generate protobuf messages at runtime based on +/// their message descriptors. The location of the .desc files is expected +/// via the GZ_DESCRIPTOR_PATH environment variable. This environment +/// variable expects paths to directories containing .desc files. +/// Any file without the .desc extension will be ignored. +class DynamicFactory +{ + public: using Message = google::protobuf::Message; + public: using MessagePtr = std::unique_ptr; + + ////////////////////////////////////////////////// + /// \brief Constructor. + /// The constructor will try to load all descriptors specified in the + /// GZ_DESCRIPTOR_PATH environment variable. + public: DynamicFactory(); + + ////////////////////////////////////////////////// + /// \brief Load descriptors into the descriptor pool. + /// \param[in] _paths A set of directories containing .desc decriptor files. + /// Each directory should be separated by ":". + public: void LoadDescriptors(const std::string &_paths); + + ////////////////////////////////////////////////// + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: MessagePtr New(const std::string &_msgType); + + /// \typedef FactoryFn + /// \brief Prototype for message factory generation + private: using FactoryFn = std::function; + + /// \brief A list of registered message types built at runtime. + /// The key is the message type. The value is a function that returns a + /// std::unique_ptr to a new empty instance of the message or nullptr if + /// the message is not registered. + private: std::map dynamicMsgMap; + + /// \brief We store the descriptors here. + private: google::protobuf::DescriptorPool pool; + + /// \brief Used to create a message from a descriptor. + private: google::protobuf::DynamicMessageFactory dynamicMessageFactory; +}; + +} // namespace gz::msgs +#endif // DYNAMIC_FACTORY_HH_ diff --git a/src/Factory.cc b/src/Factory.cc index 9f2c338a..0c8ca02f 100644 --- a/src/Factory.cc +++ b/src/Factory.cc @@ -15,304 +15,48 @@ * */ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4146 4251) -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - #include "gz/msgs/Factory.hh" -#include "gz/msgs/Filesystem.hh" +#include "gz/msgs/MessageFactory.hh" +#include using namespace gz; using namespace msgs; -/// \def ProtobufUniquePtr -/// \brief An abbreviated unique pointer to a protobuf message type. -using ProtoUniquePtr = std::unique_ptr; -////////////////////////////////////////////////// -/// \brief split at a one character delimiter to get a vector of something -/// \param[in] _orig The string to split -/// \param[in] _delim a character to split the string at -/// \returns vector of split pieces of the string excluding the delimiter -std::vector split(const std::string &_orig, char _delim) -{ - std::vector pieces; - size_t pos1 = 0; - size_t pos2 = _orig.find(_delim); - while (pos2 != std::string::npos) - { - pieces.push_back(_orig.substr(pos1, pos2-pos1)); - pos1 = pos2+1; - pos2 = _orig.find(_delim, pos2+1); - } - pieces.push_back(_orig.substr(pos1, _orig.size()-pos1)); - return pieces; +gz::msgs::MessageFactory& GetFactoryInstance() { + static gz::utils::NeverDestroyed instance; + return instance.Access(); } -///////////////////////////////////////////////// -/// \brief A factory class to generate protobuf messages at runtime based on -/// their message descriptors. The location of the .desc files is expected -/// via the GZ_DESCRIPTOR_PATH environment variable. This environment -/// variable expects paths to directories containing .desc files. -/// Any file without the .desc extension will be ignored. -class DynamicFactory -{ - ////////////////////////////////////////////////// - /// \brief Constructor. - /// The constructor will try to load all descriptors specified in the - /// GZ_DESCRIPTOR_PATH environment variable. - public: DynamicFactory() - { - // Try to get the list of paths from an environment variable. - const char *descPaths = std::getenv("GZ_DESCRIPTOR_PATH"); - if (!descPaths) - { - // TODO(CH3): Deprecated. Remove on tock. - // Remember to still return !! - descPaths = std::getenv("IGN_DESCRIPTOR_PATH"); - - if (!descPaths) - { - return; - } - else - { - std::cerr << "IGN_DESCRIPTOR_PATH is deprecated and will be removed! " - << "Use GZ_DESCRIPTOR_PATH instead!" << std::endl; - } - } - - // Load all the descriptors found in the paths set with GZ_DESCRIPTOR_PATH. - this->LoadDescriptors(descPaths); - } - - ////////////////////////////////////////////////// - /// \brief Load descriptors into the descriptor pool. - /// \param[in] _paths A set of directories containing .desc decriptor files. - /// Each directory should be separated by ":". - public: void LoadDescriptors(const std::string &_paths) - { - if (_paths.empty()) - return; - - // Split all the directories containing .desc files. - std::vector descDirs = split(_paths, ':'); - - for (const std::string &descDir : descDirs) - { - for (DirIter dirIter(descDir); dirIter != DirIter(); ++dirIter) - { - // Ignore files without the .desc extension. - if ((*dirIter).rfind(".desc") == std::string::npos) - continue; - - // Parse the .desc file. - std::ifstream ifs(*dirIter); - if (!ifs.is_open()) - { - std::cerr << "DynamicFactory(): Unable to open [" << *dirIter << "]" - << std::endl; - continue; - } - - google::protobuf::FileDescriptorSet fileDescriptorSet; - if (!fileDescriptorSet.ParseFromIstream(&ifs)) - { - std::cerr << "DynamicFactory(): Unable to parse descriptor set from [" - << *dirIter << "]" << std::endl; - continue; - } - - // Place the real descriptors in the descriptor pool. - for (const google::protobuf::FileDescriptorProto &fileDescriptorProto : - fileDescriptorSet.file()) - { - if (!pool.BuildFile(fileDescriptorProto)) - { - std::cerr << "DynamicFactory(). Unable to place descriptors from [" - << *dirIter << "] in the descriptor pool" << std::endl; - } - } - } - } - } - - ////////////////////////////////////////////////// - /// \brief Create a new instance of a message. - /// \param[in] _msgType Type of message to create. - /// \return Pointer to a google protobuf message. Null if the message - /// type could not be handled. - public: static ProtoUniquePtr New(const std::string &_msgType) - { - auto msgType = _msgType; - if (msgType.find("ignition") == 0) - { - msgType.replace(0, 8, "gz"); - std::cerr << "Trying to create deprecated message type [" - << _msgType << "]. Using [" << msgType << "] instead." - << std::endl; - } - - // Shortcut if the type has been already registered. - std::map>::iterator msgF = - dynamicMsgMap.find(msgType); - - if (msgF != dynamicMsgMap.end()) - return msgF->second(); - - // Nothing to do if we don't know about this type in the descriptor map. - const google::protobuf::Descriptor *descriptor = - pool.FindMessageTypeByName(msgType); - if (!descriptor) - return nullptr; - - google::protobuf::Message *msgPtr( - dynamicMessageFactory.GetPrototype(descriptor)->New()); - - // Create the lambda for registration purposes. - std::function f = [msgPtr]() -> ProtoUniquePtr - { - ProtoUniquePtr ptr(msgPtr->New()); - return ptr; - }; - - // Register the new type for the future. - dynamicMsgMap[_msgType] = f; - - return f(); - } - - /// \brief A list of registered message types built at runtime. - /// The key is the message type. The value is a function that returns a - /// std::unique_ptr to a new empty instance of the message or nullptr if - /// the message is not registered. - private: static std::map> dynamicMsgMap; - - /// \brief We store the descriptors here. - private: static google::protobuf::DescriptorPool pool; - - /// \brief Used to create a message from a descriptor. - private: static google::protobuf::DynamicMessageFactory dynamicMessageFactory; -}; - -// Initialization of static members, -std::map> -DynamicFactory::dynamicMsgMap; -google::protobuf::DescriptorPool DynamicFactory::pool; -google::protobuf::DynamicMessageFactory DynamicFactory::dynamicMessageFactory; -DynamicFactory dynamicFactory; -std::map *Factory::msgMap = NULL; - ///////////////////////////////////////////////// void Factory::Register(const std::string &_msgType, - FactoryFn _factoryfn) + Factory::FactoryFn _factoryfn) { - // Create the msgMap if it's null - if (!msgMap) - msgMap = new std::map; - - (*msgMap)[_msgType] = _factoryfn; + GetFactoryInstance().Register(_msgType, _factoryfn); } ///////////////////////////////////////////////// std::unique_ptr Factory::New( const std::string &_msgType) { - auto msgType = _msgType; - if (msgType.find("ignition") == 0) - { - msgType.replace(0, 8, "gz"); - std::cerr << "Trying to create deprecated message type [" - << _msgType << "]. Using [" << msgType << "] instead." - << std::endl; - } - - std::unique_ptr msg; - - std::string type; - // Convert "gz.msgs." to "gz_msgs.". - if (msgType.find("gz.msgs.") == 0) - { - type = "gz_msgs." + msgType.substr(8); - } - // Convert ".gz.msgs." to "gz_msgs.". - else if (msgType.find(".gz.msgs.") == 0) - { - type = "gz_msgs." + msgType.substr(9); - } - else - { - // Fix typenames that are missing "gz_msgs." at the beginning. - if (msgType.find("gz_msgs.") != 0) - type = "gz_msgs."; - type += msgType; - } - - // Create a new message if a FactoryFn has been assigned to the message type - if (msgMap->find(type) != msgMap->end()) - return ((*msgMap)[type]) (); - - // Check if we have the message descriptor. - msg = dynamicFactory.New(msgType); - - return msg; + return GetFactoryInstance().New(_msgType); } ///////////////////////////////////////////////// std::unique_ptr Factory::New( const std::string &_msgType, const std::string &_args) { - auto msgType = _msgType; - if (msgType.find("ignition") == 0) - { - msgType.replace(0, 8, "gz"); - std::cerr << "Trying to create deprecated message type [" - << _msgType << "]. Using [" << msgType << "] instead." - << std::endl; - } - - std::unique_ptr msg = New(msgType); - if (msg) - { - google::protobuf::TextFormat::ParseFromString(_args, msg.get()); - } - - return msg; + return GetFactoryInstance().New(_msgType, _args); } ///////////////////////////////////////////////// void Factory::Types(std::vector &_types) { - _types.clear(); - - // Return the list of all known message types. - std::map::const_iterator iter; - for (iter = msgMap->begin(); iter != msgMap->end(); ++iter) - { - _types.push_back(iter->first); - } + GetFactoryInstance().Types(_types); } ///////////////////////////////////////////////// void Factory::LoadDescriptors(const std::string &_paths) { - dynamicFactory.LoadDescriptors(_paths); + GetFactoryInstance().LoadDescriptors(_paths); } diff --git a/src/Filesystem.cc b/src/Filesystem.cc deleted file mode 100644 index aea5e352..00000000 --- a/src/Filesystem.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2002-2009, 2014 Beman Dawes - * Copyright 2001 Dietmar Kuehl - * - * Distributed under the Boost Software License, Version 1.0. - * - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * Most of this code was borrowed from Boost in - * libs/filesystem/src/operations.cpp and - * libs/filesystem/include/boost/filesystem/operations.hpp. - */ - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#endif - -#include -#include -#include -#include -#include - -#include "gz/msgs/Filesystem.hh" - -namespace gz -{ - namespace msgs - { - /// \internal - /// \brief Private data for the DirIter class. - class DirIterPrivate - { - /// \def current - /// \brief The current directory item. - public: std::string current; - - /// \def dirname - /// \brief The original path to the directory. - public: std::string dirname; - - /// \def handle - /// \brief Opaque handle for holding the directory iterator. - public: void *handle; - - /// \def end - /// \brief Private variable to indicate whether the iterator has reached - /// the end. - public: bool end; - }; - -#ifndef _WIN32 - - static const char preferred_separator = '/'; - - ////////////////////////////////////////////////// - DirIter::DirIter(const std::string &_in) : dataPtr(new DirIterPrivate) - { - this->dataPtr->dirname = _in; - - this->dataPtr->current = ""; - - this->dataPtr->handle = opendir(_in.c_str()); - - this->dataPtr->end = false; - - if (this->dataPtr->handle == nullptr) - { - this->dataPtr->end = true; - } - else - { - Next(); - } - } - - ////////////////////////////////////////////////// - void DirIter::Next() - { - while (true) - { - struct dirent *entry = - readdir(reinterpret_cast(this->dataPtr->handle)); // NOLINT - if (!entry) - { - this->dataPtr->end = true; - this->dataPtr->current = ""; - break; - } - - if ((strcmp(entry->d_name, ".") != 0) - && (strcmp(entry->d_name, "..") != 0)) - { - this->dataPtr->current = std::string(entry->d_name); - break; - } - } - } - - ////////////////////////////////////////////////// - void DirIter::CloseHandle() - { - closedir(reinterpret_cast(this->dataPtr->handle)); - } - -#else // Windows - - static const char preferred_separator = '\\'; - - ////////////////////////////////////////////////// - static bool not_found_error(int _errval) - { - return _errval == ERROR_FILE_NOT_FOUND - || _errval == ERROR_PATH_NOT_FOUND - || _errval == ERROR_INVALID_NAME // "tools/src/:sys:stat.h", "//foo" - || _errval == ERROR_INVALID_DRIVE // USB card reader with no card - || _errval == ERROR_NOT_READY // CD/DVD drive with no disc inserted - || _errval == ERROR_INVALID_PARAMETER // ":sys:stat.h" - || _errval == ERROR_BAD_PATHNAME // "//nosuch" on Win64 - || _errval == ERROR_BAD_NETPATH; // "//nosuch" on Win32 - } - -#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE -#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) -#endif - - ////////////////////////////////////////////////// - DirIter::DirIter(const std::string &_in) : dataPtr(new DirIterPrivate) - { - // use a form of search Sebastian Martel reports will work with Win98 - this->dataPtr->dirname = _in; - - this->dataPtr->current = ""; - - this->dataPtr->end = false; - - if (_in.empty()) - { - // To be compatible with Unix, if given an empty string, assume this - // is the end. - this->dataPtr->end = true; - return; - } - - std::string dirpath(_in); - dirpath += (dirpath.empty() - || (dirpath[dirpath.size()-1] != '\\' - && dirpath[dirpath.size()-1] != '/' - && dirpath[dirpath.size()-1] != ':'))? "\\*" : "*"; - - WIN32_FIND_DATAA data; - if ((this->dataPtr->handle = ::FindFirstFileA(dirpath.c_str(), &data)) - == INVALID_HANDLE_VALUE) - { - this->dataPtr->handle = nullptr; // signal eof - this->dataPtr->end = true; - } - else - { - this->dataPtr->current = std::string(data.cFileName); - } - } - - ////////////////////////////////////////////////// - void DirIter::Next() - { - WIN32_FIND_DATAA data; - if (::FindNextFileA(this->dataPtr->handle, &data) == 0) // fails - { - this->dataPtr->end = true; - this->dataPtr->current = ""; - } - else - { - this->dataPtr->current = std::string(data.cFileName); - } - } - - ////////////////////////////////////////////////// - void DirIter::CloseHandle() - { - ::FindClose(this->dataPtr->handle); - } - -#endif // _WIN32 - - ////////////////////////////////////////////////// - const std::string separator(const std::string &_p) - { - return _p + preferred_separator; - } - - ////////////////////////////////////////////////// - DirIter::DirIter() : dataPtr(new DirIterPrivate) - { - this->dataPtr->current = ""; - - this->dataPtr->dirname = ""; - - this->dataPtr->handle = nullptr; - - this->dataPtr->end = true; - } - - ////////////////////////////////////////////////// - std::string DirIter::operator*() const - { - return this->dataPtr->dirname + preferred_separator + - this->dataPtr->current; - } - - ////////////////////////////////////////////////// - // prefix operator; note that we don't support the postfix operator - // because it is complicated to do so - const DirIter& DirIter::operator++() - { - Next(); - return *this; - } - - ////////////////////////////////////////////////// - bool DirIter::operator!=(const DirIter &_other) const - { - return this->dataPtr->end != _other.dataPtr->end; - } - - ////////////////////////////////////////////////// - DirIter::~DirIter() - { - if (this->dataPtr->handle != nullptr) - { - CloseHandle(); - this->dataPtr->handle = nullptr; - } - } - } -} diff --git a/src/MessageFactory.cc b/src/MessageFactory.cc new file mode 100644 index 00000000..8fd637b6 --- /dev/null +++ b/src/MessageFactory.cc @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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. + * +*/ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4146 4251) +#endif +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "DynamicFactory.hh" +#include "gz/msgs/MessageFactory.hh" + +namespace gz::msgs +{ + +///////////////////////////////////////////////// +MessageFactory::MessageFactory(): + dynamicFactory(std::make_unique()) +{ +} + +///////////////////////////////////////////////// +void MessageFactory::Register(const std::string &_msgType, + FactoryFn _factoryfn) +{ + msgMap[_msgType] = _factoryfn; +} + +///////////////////////////////////////////////// +MessageFactory::MessagePtr MessageFactory::New( + const std::string &_msgType) +{ + auto msgType = _msgType; + MessagePtr msg; + + std::string type; + // Convert "gz.msgs." to "gz_msgs.". + if (msgType.find("gz.msgs.") == 0) + { + type = "gz_msgs." + msgType.substr(8); + } + // Convert ".gz.msgs." to "gz_msgs.". + else if (msgType.find(".gz.msgs.") == 0) + { + type = "gz_msgs." + msgType.substr(9); + } + else + { + // Fix typenames that are missing "gz_msgs." at the beginning. + if (msgType.find("gz_msgs.") != 0) + type = "gz_msgs."; + type += msgType; + } + + // Create a new message if a FactoryFn has been assigned to the message type + if (msgMap.find(type) != msgMap.end()) + return msgMap[type](); + + // Check if we have the message descriptor. + return dynamicFactory->New(msgType); +} + +///////////////////////////////////////////////// +MessageFactory::MessagePtr MessageFactory::New( + const std::string &_msgType, const std::string &_args) +{ + std::unique_ptr msg = New(_msgType); + if (msg) + { + google::protobuf::TextFormat::ParseFromString(_args, msg.get()); + } + return msg; +} + +///////////////////////////////////////////////// +void MessageFactory::Types(std::vector &_types) +{ + _types.clear(); + + // Return the list of all known message types. + std::map::const_iterator iter; + for (iter = msgMap.begin(); iter != msgMap.end(); ++iter) + { + _types.push_back(iter->first); + } +} + +///////////////////////////////////////////////// +void MessageFactory::LoadDescriptors(const std::string &_paths) +{ + dynamicFactory->LoadDescriptors(_paths); +} + +} // namespace gz::msgs From b9ea26032b06a23ffb1fba5cf2b712323b06083c Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Wed, 5 Apr 2023 20:45:43 +0000 Subject: [PATCH 3/6] Fix environment variable Signed-off-by: Michael Carroll --- .../gz/msgs/detail/dynamic_message_cast.hh | 4 +++- src/DynamicFactory.cc | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/gz/msgs/detail/dynamic_message_cast.hh b/include/gz/msgs/detail/dynamic_message_cast.hh index d9600b8c..de9a3ee4 100644 --- a/include/gz/msgs/detail/dynamic_message_cast.hh +++ b/include/gz/msgs/detail/dynamic_message_cast.hh @@ -32,8 +32,10 @@ namespace gz::msgs::detail { +/// Cast a base unique pointer to protobuf message type to child type template -std::unique_ptr dynamic_message_cast(std::unique_ptr &&_baseMsg) +std::unique_ptr +dynamic_message_cast(std::unique_ptr &&_baseMsg) { auto converted = std::unique_ptr{dynamic_cast(_baseMsg.get())}; if (converted) { diff --git a/src/DynamicFactory.cc b/src/DynamicFactory.cc index 111b1d59..a9fde499 100644 --- a/src/DynamicFactory.cc +++ b/src/DynamicFactory.cc @@ -17,12 +17,16 @@ #include #include +#include #include "DynamicFactory.hh" +#include "gz/utils/Environment.hh" using namespace gz; using namespace msgs; +static constexpr const char * kDescriptorEnv = "GZ_DESCRIPTOR_PATH"; + ////////////////////////////////////////////////// /// \brief split at a one character delimiter to get a vector of something /// \param[in] _orig The string to split @@ -47,10 +51,11 @@ std::vector split(const std::string &_orig, char _delim) DynamicFactory::DynamicFactory() { // Try to get the list of paths from an environment variable. - const char *descPaths = std::getenv("GZ_DESCRIPTOR_PATH"); - - // Load all the descriptors found in the paths set with GZ_DESCRIPTOR_PATH. - this->LoadDescriptors(descPaths); + std::string descPaths; + if (gz::utils::env(kDescriptorEnv, descPaths)) { + // Load all the descriptors found in the paths set with GZ_DESCRIPTOR_PATH. + this->LoadDescriptors(descPaths); + } } ////////////////////////////////////////////////// @@ -73,7 +78,8 @@ void DynamicFactory::LoadDescriptors(const std::string &_paths) std::ifstream ifs(dirIter.path().string(), std::ifstream::in); if (!ifs.is_open()) { - std::cerr << "DynamicFactory(): Unable to open [" << dirIter.path() << "]" + std::cerr << "DynamicFactory(): Unable to open [" + << dirIter.path() << "]" << std::endl; continue; } @@ -92,7 +98,8 @@ void DynamicFactory::LoadDescriptors(const std::string &_paths) if (!pool.BuildFile(fileDescriptorProto)) { std::cerr << "DynamicFactory(). Unable to place descriptors from [" - << dirIter.path() << "] in the descriptor pool" << std::endl; + << dirIter.path() + << "] in the descriptor pool" << std::endl; } } } From de3daa38b26184466e87667784994935de690307 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Tue, 25 Apr 2023 16:36:24 +0000 Subject: [PATCH 4/6] @wip Signed-off-by: Michael Carroll --- CMakeLists.txt | 16 +- cmake/gz_msgs_protoc.cmake | 95 ++ compiled/CMakeLists.txt | 5 + compiled/include/gz/msgs/CMakeLists.txt | 1 + .../include}/gz/msgs/Factory.hh | 0 compiled/include/gz/msgs/config.hh.in | 0 {src => compiled/src}/Factory.cc | 0 {src => compiled/src}/Factory_TEST.cc | 0 {src => compiled/src}/cmd/CMakeLists.txt | 0 {src => compiled/src}/cmd/cmdmsgs.rb.in | 0 .../src}/cmd/msgs.bash_completion.sh | 0 {src => compiled/src}/gz.cc | 0 {src => compiled/src}/gz.hh | 0 core/CMakeLists.txt | 41 + {src => core/generator}/Generator.cc | 30 - {src => core/generator}/Generator.hh | 0 {src => core/generator}/generator_main.cc | 0 {include => core/include}/CMakeLists.txt | 0 {include => core/include}/gz/CMakeLists.txt | 0 .../include}/gz/msgs/CMakeLists.txt | 0 core/include/gz/msgs/Convert.hh | 51 + .../include}/gz/msgs/MessageFactory.hh | 7 +- .../include}/gz/msgs/PointCloudPackedUtils.hh | 0 core/include/gz/msgs/Utility.hh | 0 .../include}/gz/msgs/config.hh.in | 0 core/include/gz/msgs/convert/vector2d.hh | 24 + .../gz/msgs/detail/PointCloudPackedUtils.hh | 0 .../gz/msgs/detail/dynamic_message_cast.hh | 0 {src => core/src}/DynamicFactory.cc | 8 +- {src => core/src}/DynamicFactory.hh | 0 {src => core/src}/MessageFactory.cc | 2 + .../src}/PointCloudPackedUtils_TEST.cc | 0 gz-msgs-extras.cmake.in | 100 ++ include/gz/msgs/Utility.hh | 500 ------ proto/CMakeLists.txt | 2 +- src/CMakeLists.txt | 267 ---- src/MessageTypes.hh.in | 38 - src/Utility.cc | 1365 ----------------- src/Utility_TEST.cc | 1172 -------------- test/CMakeLists.txt | 8 +- tools/CMakeLists.txt | 8 + tools/gz_msgs_factory.py | 54 + tools/gz_msgs_generate.py | 15 +- 43 files changed, 415 insertions(+), 3394 deletions(-) create mode 100644 cmake/gz_msgs_protoc.cmake create mode 100644 compiled/CMakeLists.txt create mode 100644 compiled/include/gz/msgs/CMakeLists.txt rename {include => compiled/include}/gz/msgs/Factory.hh (100%) create mode 100644 compiled/include/gz/msgs/config.hh.in rename {src => compiled/src}/Factory.cc (100%) rename {src => compiled/src}/Factory_TEST.cc (100%) rename {src => compiled/src}/cmd/CMakeLists.txt (100%) rename {src => compiled/src}/cmd/cmdmsgs.rb.in (100%) rename {src => compiled/src}/cmd/msgs.bash_completion.sh (100%) rename {src => compiled/src}/gz.cc (100%) rename {src => compiled/src}/gz.hh (100%) create mode 100644 core/CMakeLists.txt rename {src => core/generator}/Generator.cc (84%) rename {src => core/generator}/Generator.hh (100%) rename {src => core/generator}/generator_main.cc (100%) rename {include => core/include}/CMakeLists.txt (100%) rename {include => core/include}/gz/CMakeLists.txt (100%) rename {include => core/include}/gz/msgs/CMakeLists.txt (100%) create mode 100644 core/include/gz/msgs/Convert.hh rename {include => core/include}/gz/msgs/MessageFactory.hh (94%) rename {include => core/include}/gz/msgs/PointCloudPackedUtils.hh (100%) create mode 100644 core/include/gz/msgs/Utility.hh rename {include => core/include}/gz/msgs/config.hh.in (100%) create mode 100644 core/include/gz/msgs/convert/vector2d.hh rename {include => core/include}/gz/msgs/detail/PointCloudPackedUtils.hh (100%) rename {include => core/include}/gz/msgs/detail/dynamic_message_cast.hh (100%) rename {src => core/src}/DynamicFactory.cc (98%) rename {src => core/src}/DynamicFactory.hh (100%) rename {src => core/src}/MessageFactory.cc (98%) rename {src => core/src}/PointCloudPackedUtils_TEST.cc (100%) create mode 100644 gz-msgs-extras.cmake.in delete mode 100644 include/gz/msgs/Utility.hh delete mode 100644 src/CMakeLists.txt delete mode 100644 src/MessageTypes.hh.in delete mode 100644 src/Utility.cc delete mode 100644 src/Utility_TEST.cc create mode 100755 tools/gz_msgs_factory.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e1055d..c498d778 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,14 @@ find_package(gz-cmake3 REQUIRED) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -gz_configure_project(VERSION_SUFFIX) +gz_configure_project(VERSION_SUFFIX + CONFIG_EXTRAS "gz-msgs-extras.cmake.in") + +# Install cmake support files +install( + DIRECTORY cmake/ + DESTINATION "lib/cmake/${PROJECT_NAME}" +) if (UNIX AND NOT APPLE) set (EXTRA_TEST_LIB_DEPS stdc++fs) @@ -73,6 +80,11 @@ gz_find_package(GzProtobuf COMPONENTS all PRETTY Protobuf) +#-------------------------------------- +# Find gz-utils +gz_find_package(gz-utils2 REQUIRED) +set(GZ_UTILS_VER ${gz-utils2_VERSION_MAJOR}) + #-------------------------------------- # Find gz-math gz_find_package(gz-math7 REQUIRED) @@ -92,7 +104,7 @@ gz_find_package(TINYXML2 REQUIRED PRIVATE PRETTY tinyxml2) #============================================================================ # Configure the build #============================================================================ -gz_configure_build(QUIT_IF_BUILD_ERRORS) +gz_configure_build(QUIT_IF_BUILD_ERRORS COMPONENTS compiled) #============================================================================ # gz command line support diff --git a/cmake/gz_msgs_protoc.cmake b/cmake/gz_msgs_protoc.cmake new file mode 100644 index 00000000..a1043cf1 --- /dev/null +++ b/cmake/gz_msgs_protoc.cmake @@ -0,0 +1,95 @@ +################################################## +# A function that calls protoc on a protobuf file +# Options: +# GENERATE_CPP - generates c++ code for the message if specified +# One value arguments: +# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. ".gz.msgs") +# PROTOC_EXEC - Path to protoc +# INPUT_PROTO - Path to the input .proto file +# OUTPUT_CPP_DIR - Path where C++ files are saved +# OUTPUT_INCLUDES - A CMake variable name containing a list that the C++ header path should be appended to +# OUTPUT_CPP_HH_VAR - A CMake variable name containing a list that the C++ header path should be appended to +# OUTPUT_CPP_CC_VAR - A Cmake variable name containing a list that the C++ source path should be appended to +# Multi value arguments +# PROTO_PATH - Passed to protoc --proto_path +function(gz_msgs_protoc) + set(options GENERATE_CPP) + set(oneValueArgs + MSGS_GEN_SCRIPT + PROTO_PACKAGE + PROTOC_EXEC + GZ_PROTOC_PLUGIN + INPUT_PROTO + OUTPUT_CPP_DIR + OUTPUT_INCLUDES + OUTPUT_CPP_HH_VAR + OUTPUT_DETAIL_CPP_HH_VAR + OUTPUT_CPP_CC_VAR) + set(multiValueArgs PROTO_PATH) + + cmake_parse_arguments(gz_msgs_protoc "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + get_filename_component(ABS_FIL ${gz_msgs_protoc_INPUT_PROTO} ABSOLUTE) + get_filename_component(FIL_WE ${gz_msgs_protoc_INPUT_PROTO} NAME_WE) + + set(protoc_args) + set(output_files) + + set(proto_package_dir ".") + if(gz_msgs_protoc_PROTO_PACKAGE) + string(REPLACE "." "/" proto_package_dir ${gz_msgs_protoc_PROTO_PACKAGE}) + endif() + + if(gz_msgs_protoc_GENERATE_CPP) + # Full path to generated header (${PROJECT_BINARY_DIR}/include/gz/msgs/foo.pb.h) + set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.h") + # Full path to generated detail header (${PROJECT_BINARY_DIR}/include/gz/msgs/details/foo.pb.h) + set(output_detail_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/details/${FIL_WE}.pb.h") + # Full path to generated ignition header (${PROJECT_BINARY_DIR}/include/foo.pb.cc) + set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.cc") + + # Generate a clean relative path (gz/msgs/foo.pb.h) + string(REPLACE "${PROJECT_BINARY_DIR}/include/" "" output_include ${output_header}) + list(APPEND ${gz_msgs_protoc_OUTPUT_INCLUDES} "${output_include}") + + list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${output_header}) + list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${output_source}) + list(APPEND ${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR} ${output_detail_header}) + + list(APPEND output_files ${output_header}) + list(APPEND output_files ${output_detail_header}) + list(APPEND output_files ${output_source}) + + set(${gz_msgs_protoc_OUTPUT_INCLUDES} ${${gz_msgs_protoc_OUTPUT_INCLUDES}} PARENT_SCOPE) + set(${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR}} PARENT_SCOPE) + set(${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_HH_VAR}} PARENT_SCOPE) + set(${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_CC_VAR}} PARENT_SCOPE) + endif() + + set(GENERATE_ARGS + --protoc-exec "$" + --gz-generator-bin "${gz_msgs_protoc_GZ_PROTOC_PLUGIN}" + --proto-path "${gz_msgs_protoc_PROTO_PATH}" + --input-path "${ABS_FIL}" + ) + + if(${gz_msgs_protoc_GENERATE_CPP}) + list(APPEND GENERATE_ARGS + --generate-cpp + --output-cpp-path "${gz_msgs_protoc_OUTPUT_CPP_DIR}") + endif() + + add_custom_command( + OUTPUT ${output_files} + COMMAND Python3::Interpreter + ARGS ${gz_msgs_protoc_MSGS_GEN_SCRIPT} ${GENERATE_ARGS} + DEPENDS + ${ABS_FIL} + # While the script is executed in the source directory, it does not write + # to the source tree. All outputs are stored in the build directory. + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Running protoc on ${gz_msgs_protoc_INPUT_PROTO}" + VERBATIM + ) + +endfunction() diff --git a/compiled/CMakeLists.txt b/compiled/CMakeLists.txt new file mode 100644 index 00000000..1e19ac40 --- /dev/null +++ b/compiled/CMakeLists.txt @@ -0,0 +1,5 @@ +gz_get_libsources_and_unittests(sources tests) + +add_subdirectory(include/gz/msgs) + +#gz_add_component(compiled SOURCES ${sources}) diff --git a/compiled/include/gz/msgs/CMakeLists.txt b/compiled/include/gz/msgs/CMakeLists.txt new file mode 100644 index 00000000..bf4411e8 --- /dev/null +++ b/compiled/include/gz/msgs/CMakeLists.txt @@ -0,0 +1 @@ +gz_install_all_headers() diff --git a/include/gz/msgs/Factory.hh b/compiled/include/gz/msgs/Factory.hh similarity index 100% rename from include/gz/msgs/Factory.hh rename to compiled/include/gz/msgs/Factory.hh diff --git a/compiled/include/gz/msgs/config.hh.in b/compiled/include/gz/msgs/config.hh.in new file mode 100644 index 00000000..e69de29b diff --git a/src/Factory.cc b/compiled/src/Factory.cc similarity index 100% rename from src/Factory.cc rename to compiled/src/Factory.cc diff --git a/src/Factory_TEST.cc b/compiled/src/Factory_TEST.cc similarity index 100% rename from src/Factory_TEST.cc rename to compiled/src/Factory_TEST.cc diff --git a/src/cmd/CMakeLists.txt b/compiled/src/cmd/CMakeLists.txt similarity index 100% rename from src/cmd/CMakeLists.txt rename to compiled/src/cmd/CMakeLists.txt diff --git a/src/cmd/cmdmsgs.rb.in b/compiled/src/cmd/cmdmsgs.rb.in similarity index 100% rename from src/cmd/cmdmsgs.rb.in rename to compiled/src/cmd/cmdmsgs.rb.in diff --git a/src/cmd/msgs.bash_completion.sh b/compiled/src/cmd/msgs.bash_completion.sh similarity index 100% rename from src/cmd/msgs.bash_completion.sh rename to compiled/src/cmd/msgs.bash_completion.sh diff --git a/src/gz.cc b/compiled/src/gz.cc similarity index 100% rename from src/gz.cc rename to compiled/src/gz.cc diff --git a/src/gz.hh b/compiled/src/gz.hh similarity index 100% rename from src/gz.hh rename to compiled/src/gz.hh diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt new file mode 100644 index 00000000..72e8058b --- /dev/null +++ b/core/CMakeLists.txt @@ -0,0 +1,41 @@ +# Build a custom protoc plugin +################################################## +gz_add_executable(${PROJECT_NAME}_protoc_plugin + ${CMAKE_CURRENT_SOURCE_DIR}/generator/Generator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/generator/generator_main.cc) +target_link_libraries(${PROJECT_NAME}_protoc_plugin + protobuf::libprotoc + protobuf::libprotobuf) +target_include_directories(${PROJECT_NAME}_protoc_plugin PRIVATE ${PROTOBUF_INCLUDE_DIR}) +target_compile_features(${PROJECT_NAME}_protoc_plugin PRIVATE ${GZ_CXX_11_FEATURES}) + +if (UNIX) + target_link_libraries(${PROJECT_NAME}_protoc_plugin pthread) +endif() + +install( + TARGETS ${PROJECT_NAME}_protoc_plugin + DESTINATION ${GZ_BIN_INSTALL_DIR}) + + +gz_get_libsources_and_unittests(sources tests) + +# Create the library target +gz_create_core_library( + SOURCES ${sources} + ${CMAKE_CURRENT_SOURCE_DIR}/src/DynamicFactory.cc + ${CMAKE_CURRENT_SOURCE_DIR}/src/MessageFactory.cc +) + +target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME} + PUBLIC + protobuf::libprotobuf + gz-utils${GZ_UTILS_VER}::gz-utils${GZ_UTILS_VER} +) + +# Build the unit tests +#gz_build_tests( +# TYPE UNIT +# SOURCES ${tests}) + +add_subdirectory(include/gz/msgs) diff --git a/src/Generator.cc b/core/generator/Generator.cc similarity index 84% rename from src/Generator.cc rename to core/generator/Generator.cc index f6c29147..b4845bef 100644 --- a/src/Generator.cc +++ b/core/generator/Generator.cc @@ -136,15 +136,7 @@ bool Generator::Generate(const FileDescriptor *_file, #include -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4100 4512 4127 4068 4244 4267 4251 4146) -#endif - #include <$detail_header$> - )"); auto ns = getNamespaces(_file->package()); @@ -185,33 +177,11 @@ bool Generator::Generate(const FileDescriptor *_file, printer.PrintRaw("} // namespace " + *name + "\n"); } - printer.PrintRaw("#ifdef _MSC_VER\n"); - printer.PrintRaw("#pragma warning(pop)\n"); - printer.PrintRaw("#endif\n"); printer.PrintRaw("\n"); printer.Print(variables, "#endif // $define_guard$\n"); } - // Inject code in the auto-generated source files immediately following - // the #include calls. - { - std::unique_ptr output( - _generatorContext->OpenForInsert(sourceFilename, "includes")); - io::Printer printer(output.get(), '$'); - - // Add the gz-msgs Factory header - printer.Print("#include \"gz/msgs/Factory.hh\"\n", "name", - "includes"); - - for (auto i = 0; i < _file->message_type_count(); ++i) - { - std::string factory = "GZ_REGISTER_STATIC_MSG(\"gz_msgs."; - factory += _file->message_type(i)->name() + "\", " + - _file->message_type(i)->name() +")\n"; - printer.Print(factory.c_str(), "name", "includes"); - } - } return true; } } diff --git a/src/Generator.hh b/core/generator/Generator.hh similarity index 100% rename from src/Generator.hh rename to core/generator/Generator.hh diff --git a/src/generator_main.cc b/core/generator/generator_main.cc similarity index 100% rename from src/generator_main.cc rename to core/generator/generator_main.cc diff --git a/include/CMakeLists.txt b/core/include/CMakeLists.txt similarity index 100% rename from include/CMakeLists.txt rename to core/include/CMakeLists.txt diff --git a/include/gz/CMakeLists.txt b/core/include/gz/CMakeLists.txt similarity index 100% rename from include/gz/CMakeLists.txt rename to core/include/gz/CMakeLists.txt diff --git a/include/gz/msgs/CMakeLists.txt b/core/include/gz/msgs/CMakeLists.txt similarity index 100% rename from include/gz/msgs/CMakeLists.txt rename to core/include/gz/msgs/CMakeLists.txt diff --git a/core/include/gz/msgs/Convert.hh b/core/include/gz/msgs/Convert.hh new file mode 100644 index 00000000..200e915e --- /dev/null +++ b/core/include/gz/msgs/Convert.hh @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 GZ_MSGS_CONVERT_HH_ +#define GZ_MSGS_CONVERT_HH_ + +#include +#include +#include + +#include "gz/msgs/config.hh" +#include "gz/msgs/Export.hh" + +/// \file Utility.hh +/// \brief Utility functions that support conversion between message type +/// and Gazebo Math types. + +namespace gz::msgs +{ + // Inline bracket to help doxygen filtering. + inline namespace GZ_MSGS_VERSION_NAMESPACE { + + template + struct Converter { + static void Convert(const GzMsgT& in, T& out); + static void Convert(const T& in, GzMsgT& out); + }; + + template + T Convert(const GzMsgT &_msg) { + T ret; + Converter::Convert(_msg, ret); + return ret; + } + } +} // namespace gz::msgs + +#endif diff --git a/include/gz/msgs/MessageFactory.hh b/core/include/gz/msgs/MessageFactory.hh similarity index 94% rename from include/gz/msgs/MessageFactory.hh rename to core/include/gz/msgs/MessageFactory.hh index c278d1ac..07a15431 100644 --- a/include/gz/msgs/MessageFactory.hh +++ b/core/include/gz/msgs/MessageFactory.hh @@ -39,8 +39,12 @@ namespace gz::msgs { public: using MessagePtr = std::unique_ptr; public: using FactoryFn = std::function; + /// \brief Constructor public: MessageFactory(); + /// \brief Destructor + public: ~MessageFactory(); + /// \brief Register a message. /// \param[in] _msgType Type of message to register. /// \param[in] _factoryfn Function that generates the message. @@ -94,7 +98,8 @@ namespace gz::msgs { /// \brief A list of registered message types private: std::map msgMap; - private: std::unique_ptr dynamicFactory; + /// \brief Pointer to dynamic factory implementation + private: std::unique_ptr dynamicFactory; }; } } // namespace gz::msgs diff --git a/include/gz/msgs/PointCloudPackedUtils.hh b/core/include/gz/msgs/PointCloudPackedUtils.hh similarity index 100% rename from include/gz/msgs/PointCloudPackedUtils.hh rename to core/include/gz/msgs/PointCloudPackedUtils.hh diff --git a/core/include/gz/msgs/Utility.hh b/core/include/gz/msgs/Utility.hh new file mode 100644 index 00000000..e69de29b diff --git a/include/gz/msgs/config.hh.in b/core/include/gz/msgs/config.hh.in similarity index 100% rename from include/gz/msgs/config.hh.in rename to core/include/gz/msgs/config.hh.in diff --git a/core/include/gz/msgs/convert/vector2d.hh b/core/include/gz/msgs/convert/vector2d.hh new file mode 100644 index 00000000..f3a777ba --- /dev/null +++ b/core/include/gz/msgs/convert/vector2d.hh @@ -0,0 +1,24 @@ +#include +#include +#include + +namespace gz::msgs +{ + +struct Converter { + static void Convert(const gz::msgs::Vector3d &in, gz::math::Vector3d &out) + { + out.X() = in.x(); + out.Y() = in.y(); + out.Z() = in.z(); + } + + static void Convert(const gz::math::Vector3d &in, gz::msgs::Vector3d &out) + { + out.set_x(in.X()); + out.set_y(in.X()); + out.set_z(in.X()); + } +}; + +} // namespace gz::msgs diff --git a/include/gz/msgs/detail/PointCloudPackedUtils.hh b/core/include/gz/msgs/detail/PointCloudPackedUtils.hh similarity index 100% rename from include/gz/msgs/detail/PointCloudPackedUtils.hh rename to core/include/gz/msgs/detail/PointCloudPackedUtils.hh diff --git a/include/gz/msgs/detail/dynamic_message_cast.hh b/core/include/gz/msgs/detail/dynamic_message_cast.hh similarity index 100% rename from include/gz/msgs/detail/dynamic_message_cast.hh rename to core/include/gz/msgs/detail/dynamic_message_cast.hh diff --git a/src/DynamicFactory.cc b/core/src/DynamicFactory.cc similarity index 98% rename from src/DynamicFactory.cc rename to core/src/DynamicFactory.cc index a9fde499..0b0bf0bd 100644 --- a/src/DynamicFactory.cc +++ b/core/src/DynamicFactory.cc @@ -22,11 +22,9 @@ #include "DynamicFactory.hh" #include "gz/utils/Environment.hh" -using namespace gz; -using namespace msgs; - static constexpr const char * kDescriptorEnv = "GZ_DESCRIPTOR_PATH"; +namespace { ////////////////////////////////////////////////// /// \brief split at a one character delimiter to get a vector of something /// \param[in] _orig The string to split @@ -46,6 +44,9 @@ std::vector split(const std::string &_orig, char _delim) pieces.push_back(_orig.substr(pos1, _orig.size()-pos1)); return pieces; } +} // namespace + +namespace gz::msgs { ////////////////////////////////////////////////// DynamicFactory::DynamicFactory() @@ -136,3 +137,4 @@ DynamicFactory::MessagePtr DynamicFactory::New(const std::string &_msgType) return f(); } +} // namespace gz::msgs diff --git a/src/DynamicFactory.hh b/core/src/DynamicFactory.hh similarity index 100% rename from src/DynamicFactory.hh rename to core/src/DynamicFactory.hh diff --git a/src/MessageFactory.cc b/core/src/MessageFactory.cc similarity index 98% rename from src/MessageFactory.cc rename to core/src/MessageFactory.cc index 8fd637b6..a6ec028d 100644 --- a/src/MessageFactory.cc +++ b/core/src/MessageFactory.cc @@ -36,6 +36,8 @@ MessageFactory::MessageFactory(): { } +MessageFactory::~MessageFactory() = default; + ///////////////////////////////////////////////// void MessageFactory::Register(const std::string &_msgType, FactoryFn _factoryfn) diff --git a/src/PointCloudPackedUtils_TEST.cc b/core/src/PointCloudPackedUtils_TEST.cc similarity index 100% rename from src/PointCloudPackedUtils_TEST.cc rename to core/src/PointCloudPackedUtils_TEST.cc diff --git a/gz-msgs-extras.cmake.in b/gz-msgs-extras.cmake.in new file mode 100644 index 00000000..0f341472 --- /dev/null +++ b/gz-msgs-extras.cmake.in @@ -0,0 +1,100 @@ +# Copyright 2023 Open Source Robotics Foundation, Inc. +# +# 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. + +# copied from gz-msgs/gz-msgs-extras.cmake + +find_package(Python3 REQUIRED COMPONENTS Interpreter) + + +include(${@PROJECT_NAME@_DIR}/gz_msgs_protoc.cmake) + +set(@PROJECT_NAME@_INSTALL_PATH "${@PROJECT_NAME@_DIR}/../../..") +cmake_path(NORMAL_PATH @PROJECT_NAME@_INSTALL_PATH OUTPUT_VARIABLE @PROJECT_NAME@_INSTALL_PATH) +set(PROTOC_NAME "@PROJECT_NAME@_protoc_plugin") +set(PROTO_SCRIPT_NAME "@PROJECT_NAME@_generate.py") +set(FACTORY_SCRIPT_NAME "@PROJECT_NAME@_factory.py") + +set(@PROJECT_NAME@_PROTO_PATH ${@PROJECT_NAME@_INSTALL_PATH}/share/protos) +set(@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTOC_NAME}) +set(@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTO_SCRIPT_NAME}) +set(@PROJECT_NAME@_FACTORY_GENERATOR_SCRIPT ${@PROJECT_NAME@_INSTALL_PATH}/bin/${FACTORY_SCRIPT_NAME}) + +function(get_installed_messages) + set(options "") + set(oneValueArgs MESSAGES_PATH_VARIABLE MESSAGES_PROTOS_VARIABLE) + set(multiValueArgs "") + + cmake_parse_arguments(get_installed_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(@PROJECT_NAME@_INSTALL_PATH "${@PROJECT_NAME@_DIR}/../../..") + cmake_path(NORMAL_PATH @PROJECT_NAME@_INSTALL_PATH OUTPUT_VARIABLE @PROJECT_NAME@_INSTALL_PATH) + + set(@PROJECT_NAME@_PROTO_PATH ${@PROJECT_NAME@_INSTALL_PATH}/share/protos) + file (GLOB protos ${@PROJECT_NAME@_PROTO_PATH}/gz/msgs/*.proto) + set(${get_installed_messages_MESSAGES_PROTOS_VARIABLE} ${protos} PARENT_SCOPE) + set(${get_installed_messages_MESSAGES_PATH_VARIABLE} ${@PROJECT_NAME@_PROTO_PATH} PARENT_SCOPE) +endfunction() + +function(generate_messages) + set(options "") + set(oneValueArgs MSGS_PATH TARGET) + set(multiValueArgs MSGS_PROTOS) + + cmake_parse_arguments(generate_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(proto_file ${generate_messages_MSGS_PROTOS}) + gz_msgs_protoc( + MSGS_GEN_SCRIPT + ${@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT} + PROTO_PACKAGE + .gz.msgs + GENERATE_CPP + INPUT_PROTO + ${proto_file} + PROTOC_EXEC + protobuf::protoc + GZ_PROTOC_PLUGIN + ${@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN} + OUTPUT_CPP_DIR + "${PROJECT_BINARY_DIR}/include" + OUTPUT_INCLUDES + gen_includes + OUTPUT_CPP_HH_VAR + gen_headers + OUTPUT_DETAIL_CPP_HH_VAR + gen_detail_headers + OUTPUT_CPP_CC_VAR + gen_sources + PROTO_PATH + ${generate_messages_MSGS_PATH}) + endforeach() + + set_source_files_properties( + ${gen_headers} + ${gen_detail_headers} + ${gen_sources} + PROPERTIES GENERATED TRUE) + + if(WIN32) + set_source_files_properties(${gen_sources} + COMPILE_FLAGS "/wd4100 /wd4512 /wd4127 /wd4068 /wd4244 /wd4267 /wd4251 /wd4146") + endif() + + + add_library(${generate_messages_TARGET} ${gen_sources}) + target_link_libraries(${generate_messages_TARGET} PUBLIC protobuf::libprotobuf gz-msgs10::gz-msgs10) + target_include_directories(${generate_messages_TARGET} PUBLIC ${PROJECT_BINARY_DIR}/include) + + +endfunction() diff --git a/include/gz/msgs/Utility.hh b/include/gz/msgs/Utility.hh deleted file mode 100644 index b737da96..00000000 --- a/include/gz/msgs/Utility.hh +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 GZ_MSGS_UTILITY_HH_ -#define GZ_MSGS_UTILITY_HH_ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "gz/msgs/config.hh" -#include "gz/msgs/Export.hh" -#include "gz/msgs/MessageTypes.hh" - -/// \file Utility.hh -/// \brief Utility functions that support conversion between message type -/// and Gazebo Math types. - -namespace gz -{ - namespace msgs - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_MSGS_VERSION_NAMESPACE { - // - /// \brief Convert a msgs::Vector3d to a gz::math::Vector - /// \param[in] _v The vector to convert - /// \return A gz::math::Vector3d object - GZ_MSGS_VISIBLE - gz::math::Vector3d Convert(const msgs::Vector3d &_v); - - /// \brief Convert a msgs::Vector2d to a gz::math::Vector2d - /// \param[in] _v The vector2 to convert - /// \return A gz::math::Vector2d object - GZ_MSGS_VISIBLE - gz::math::Vector2d Convert(const msgs::Vector2d &_v); - - /// \brief Convert a msgs::Quaternion to a gz::math::Quaterniond - /// \param[in] _q The quaternion to convert - /// \return A gz::math::Quaterniond object - GZ_MSGS_VISIBLE - gz::math::Quaterniond Convert(const msgs::Quaternion &_q); - - /// \brief Convert a msgs::Pose to a gz::math::Pose3d - /// \param[in] _p The pose to convert - /// \return A gz::math::Pose3d object - GZ_MSGS_VISIBLE - gz::math::Pose3d Convert(const msgs::Pose &_p); - - /// \brief Convert a msgs::Color to a math::Color - /// \param[in] _c The color to convert - /// \return A math::Color object - GZ_MSGS_VISIBLE - math::Color Convert(const msgs::Color &_c); - - /// \brief Convert a msgs::PlaneGeom to a gz::math::Planed - /// \param[in] _p The plane to convert - /// \return A gz::math::Planed object - GZ_MSGS_VISIBLE - gz::math::Planed Convert(const msgs::PlaneGeom &_p); - - /// \brief Convert a msgs::Inertial to a gz::math::Inertiald - /// \param[in] _i The inertial to convert - /// \return A gz::math::Inertiald object - GZ_MSGS_VISIBLE - math::Inertiald Convert(const msgs::Inertial &_i); - - /// \brief Convert a msgs::SphericalCoordinates to an - /// gz::math::SphericalCoordinates - /// \param[in] _coord The spherical coordinates to convert - /// \return A gz::math::SphericalCoordinates object - GZ_MSGS_VISIBLE - math::SphericalCoordinates Convert( - const msgs::SphericalCoordinates &_coord); - - /// \brief Convert a msgs::AxisAlignedBox to an - /// gz::math::AxisAlignedBox - /// \param[in] _b The axis aligned box to convert - /// \return A gz::math::AxisAlignedBox object - GZ_MSGS_VISIBLE - math::AxisAlignedBox Convert(const msgs::AxisAlignedBox &_b); - - /// \brief Convert gz::math::AxisAlignedBox to - /// msgs::AxisAlignedBox. - /// \param[in] _b The axis aligned box to convert - /// \return A gz::math::AxisAlignedBox object - GZ_MSGS_VISIBLE - msgs::AxisAlignedBox Convert(const math::AxisAlignedBox &_b); - - /// \brief Convert a msgs::StringMsg to an std::string - /// \param[in] _m The message to convert - /// \return An std::string object - GZ_MSGS_VISIBLE - std::string Convert(const msgs::StringMsg &_m); - - /// \brief Convert a msgs::Boolean to a bool - /// \param[in] _m The message to convert - /// \return An bool object - GZ_MSGS_VISIBLE - bool Convert(const msgs::Boolean &_m); - - /// \brief Convert a msgs::Int32 to an int32_t - /// \param[in] _m The message to convert - /// \return An int32_t object - GZ_MSGS_VISIBLE - int32_t Convert(const msgs::Int32 &_m); - - /// \brief Convert a msgs::UInt32 to a uint32_t - /// \param[in] _m The message to convert - /// \return An uint32_t object - GZ_MSGS_VISIBLE - uint32_t Convert(const msgs::UInt32 &_m); - - /// \brief Convert a msgs::Int64 to an int64_t - /// \param[in] _m The message to convert - /// \return An int64_t object - GZ_MSGS_VISIBLE - int64_t Convert(const msgs::Int64 &_m); - - /// \brief Convert a msgs::UInt64 to a uint64_t - /// \param[in] _m The message to convert - /// \return An uint64_t object - GZ_MSGS_VISIBLE - uint64_t Convert(const msgs::UInt64 &_m); - - /// \brief Convert a msgs::Double to a double - /// \param[in] _m The message to convert - /// \return An double object - GZ_MSGS_VISIBLE - double Convert(const msgs::Double &_m); - - /// \brief Convert a msgs::Float to a float - /// \param[in] _m The message to convert - /// \return An float object - GZ_MSGS_VISIBLE - float Convert(const msgs::Float &_m); - - /// \brief Convert a msgs::Time to a std::chrono::steady_clock::duration - /// \param[in] _time The message to convert - /// \return A std::chrono::steady_clock::duration object - GZ_MSGS_VISIBLE - std::chrono::steady_clock::duration Convert(const msgs::Time &_time); - - /// \brief Convert a gz::math::Vector3d to a msgs::Vector3d - /// \param[in] _v The vector to convert - /// \return A msgs::Vector3d object - GZ_MSGS_VISIBLE - msgs::Vector3d Convert(const gz::math::Vector3d &_v); - - /// \brief Convert a gz::math::Vector2d to a msgs::Vector2d - /// \param[in] _v The vector to convert - /// \return A msgs::Vector2d object - GZ_MSGS_VISIBLE - msgs::Vector2d Convert(const gz::math::Vector2d &_v); - - /// \brief Convert a gz::math::Quaterniond to a msgs::Quaternion - /// \param[in] _q The quaternion to convert - /// \return A msgs::Quaternion object - GZ_MSGS_VISIBLE - msgs::Quaternion Convert(const gz::math::Quaterniond &_q); - - /// \brief Convert a gz::math::Pose3d to a msgs::Pose - /// \param[in] _p The pose to convert - /// \return A msgs::Pose object - GZ_MSGS_VISIBLE - msgs::Pose Convert(const gz::math::Pose3d &_p); - - /// \brief Convert a math::Color to a msgs::Color - /// \param[in] _c The color to convert - /// \return A msgs::Color object - GZ_MSGS_VISIBLE - msgs::Color Convert(const math::Color &_c); - - /// \brief Convert an math::Inertiald to a msgs::Inertial - /// \param[in] _i The Inertiald to convert - /// \return A msgs::Inertial object - GZ_MSGS_VISIBLE - msgs::Inertial Convert(const math::Inertiald &_i); - - /// \brief Convert an math::MassMatrix3d to a msgs::Inertial - /// \param[in] _m The MassMatrix3d to convert - /// \return A msgs::Inertial object - GZ_MSGS_VISIBLE - msgs::Inertial Convert(const math::MassMatrix3d &_m); - - /// \brief Convert an math::SphericalCoordinates to a - /// msgs::SphericalCoordinates - /// \param[in] _coord The SphericalCoordinates to convert - /// \return A msgs::SphericalCoordinates object - GZ_MSGS_VISIBLE - msgs::SphericalCoordinates Convert( - const math::SphericalCoordinates &_coord); - - /// \brief Convert a gz::math::Planed to a msgs::PlaneGeom - /// \param[in] _p The plane to convert - /// \return A msgs::PlaneGeom object - GZ_MSGS_VISIBLE - msgs::PlaneGeom Convert(const gz::math::Planed &_p); - - /// \brief Convert an std::string to a msgs::StringMsg - /// \param[in] _s The string to convert - /// \return A msgs::StringMsg object - GZ_MSGS_VISIBLE - msgs::StringMsg Convert(const std::string &_s); - - /// \brief Convert a bool to a msgs::Boolean - /// \param[in] _b The bool to convert - /// \return A msgs::Boolean object - GZ_MSGS_VISIBLE - msgs::Boolean Convert(const bool &_b); - - /// \brief Convert an int32_t to a msgs::Int32 - /// \param[in] _i The int32_t to convert - /// \return A msgs::Int32 object - GZ_MSGS_VISIBLE - msgs::Int32 Convert(const int32_t &_i); - - /// \brief Convert a uint32_t to a msgs::UInt32 - /// \param[in] _u The uint32_t to convert - /// \return A msgs::UInt32 object - GZ_MSGS_VISIBLE - msgs::UInt32 Convert(const uint32_t &_u); - - /// \brief Convert an int64_t to a msgs::Int64 - /// \param[in] _i The int64_t to convert - /// \return A msgs::Int64 object - GZ_MSGS_VISIBLE - msgs::Int64 Convert(const int64_t &_i); - - /// \brief Convert a uint64_t to a msgs::UInt64 - /// \param[in] _u The uint64_t to convert - /// \return A msgs::UInt64 object - GZ_MSGS_VISIBLE - msgs::UInt64 Convert(const uint64_t &_u); - - /// \brief Convert a double to a msgs::Double - /// \param[in] _d The double to convert - /// \return A msgs::Double object - GZ_MSGS_VISIBLE - msgs::Double Convert(const double &_d); - - /// \brief Convert a float to a msgs::Float - /// \param[in] _f The float to convert - /// \return A msgs::Float object - GZ_MSGS_VISIBLE - msgs::Float Convert(const float &_f); - - /// \brief Convert a std::chrono::steady_clock::duration to a msgs::Time - /// \param[in] _time_point The std::chrono::system_clock::duration to - /// convert - /// \return A msgs::Time object - GZ_MSGS_VISIBLE - msgs::Time Convert( - const std::chrono::steady_clock::duration &_time_point); - - /// \brief Convert a string to a msgs::Joint::Type enum. - /// \param[in] _str Joint type string. - /// \return A msgs::Joint::Type enum. Defaults to REVOLUTE - /// if _str is unrecognized. - GZ_MSGS_VISIBLE - msgs::Joint::Type ConvertJointType(const std::string &_str); - - /// \brief Convert a msgs::Joint::Type to a string. - /// \param[in] _type A msgs::Joint::Type enum. - /// \return Joint type string. Returns "unknown" if - /// _type is unrecognized. - GZ_MSGS_VISIBLE - std::string ConvertJointType(const msgs::Joint::Type &_type); - - /// \brief Convert a string to a msgs::Geometry::Type enum. - /// \param[in] _str Geometry type string. - /// \return A msgs::Geometry::Type enum. - GZ_MSGS_VISIBLE - msgs::Geometry::Type ConvertGeometryType(const std::string &_str); - - /// \brief Convert a msgs::Geometry::Type to a string. - /// \param[in] _type A msgs::Geometry::Type enum. - /// \return Geometry type string. - GZ_MSGS_VISIBLE - std::string ConvertGeometryType(const msgs::Geometry::Type _type); - - /// \brief Convert a string to a msgs::PixelFormatType enum. - /// \param[in] _str PixelFormatType string. - /// \return A msgs::PixelFormatType enum. - GZ_MSGS_VISIBLE - msgs::PixelFormatType ConvertPixelFormatType(const std::string &_str); - - /// \brief Convert a PixelFormatType to a string. This can be used for - /// debugging purposes. - // \param[in] _t PixelFormatType enum value. - /// \return String version of PixelFormatType. - GZ_MSGS_VISIBLE - std::string ConvertPixelFormatType(const msgs::PixelFormatType &_t); - - /// \brief Convert a string to a msgs::Material::ShaderType enum. - /// \param[in] _str Shader type string. - /// \return A msgs::Material::ShaderType enum. Defaults to VERTEX - /// if _str is unrecognized. - GZ_MSGS_VISIBLE - msgs::Material::ShaderType ConvertShaderType(const std::string &_str); - - /// \brief Convert a msgs::ShaderType to a string. - /// \param[in] _type A msgs::ShaderType enum. - /// \return Shader type string. Returns "unknown" if - /// _type is unrecognized. - GZ_MSGS_VISIBLE - std::string ConvertShaderType(const msgs::Material::ShaderType &_type); - - /// \brief Set a msgs::Vector3d from a gz::math::Vector3d - /// \param[out] _pt A msgs::Vector3d pointer - /// \param[in] _v A gz::math::Vector3d reference - GZ_MSGS_VISIBLE - void Set(msgs::Vector3d *_pt, const gz::math::Vector3d &_v); - - /// \brief Set a msgs::Vector2d from a gz::math::Vector2d - /// \param[out] _pt A msgs::Vector2d pointer - /// \param[in] _v A gz::math::Vector2d reference - GZ_MSGS_VISIBLE - void Set(msgs::Vector2d *_pt, const gz::math::Vector2d &_v); - - /// \brief Set a msgs::Quaternion from a gz::math::Quaterniond - /// \param[out] _q A msgs::Quaternion pointer - /// \param[in] _v A gz::math::Quaterniond reference - GZ_MSGS_VISIBLE - void Set(msgs::Quaternion *_q, const gz::math::Quaterniond &_v); - - /// \brief Set a msgs::Pose from a gz::math::Pose3d - /// \param[out] _p A msgs::Pose pointer - /// \param[in] _v A gz::math::Pose3d reference - GZ_MSGS_VISIBLE - void Set(msgs::Pose *_p, const gz::math::Pose3d &_v); - - /// \brief Set a msgs::Color from a math::Color - /// \param[out] _c A msgs::Color pointer - /// \param[in] _v A math::Color reference - GZ_MSGS_VISIBLE - void Set(msgs::Color *_c, const math::Color &_v); - - /// \brief Set a msgs::Inertial from an math::Inertiald - /// \param[out] _i A msgs::Inertial pointer - /// \param[in] _m An math::Inertiald reference - GZ_MSGS_VISIBLE - void Set(msgs::Inertial *_i, const math::Inertiald &_m); - - /// \brief Set a msgs::Inertial from an math::MassMatrix3d - /// \param[out] _i A msgs::Inertial pointer - /// \param[in] _m An math::MassMatrix3d reference - GZ_MSGS_VISIBLE - void Set(msgs::Inertial *_i, const math::MassMatrix3d &_m); - - /// \brief Set a msgs::SphericalCoordinates from a - /// math::SphericalCoordinates - /// \param[out] _sc A msgs::SphericalCoordinates pointer - /// \param[in] _m An math::SphericalCoordinates reference - GZ_MSGS_VISIBLE - void Set(msgs::SphericalCoordinates *_sc, - const math::SphericalCoordinates &_m); - - /// \brief Set a msgs::Plane from a gz::math::Planed - /// \param[out] _p A msgs::Plane pointer - /// \param[in] _v A gz::math::Planed reference - GZ_MSGS_VISIBLE - void Set(msgs::PlaneGeom *_p, const gz::math::Planed &_v); - - /// \brief Set a msgs::StringMsg from an std::string - /// \param[out] _p A msgs::StringMsg pointer - /// \param[in] _v An std::string reference - GZ_MSGS_VISIBLE - void Set(msgs::StringMsg *_p, const std::string &_v); - - /// \brief Set a msgs::Boolean from a bool - /// \param[out] _p A msgs::Boolean pointer - /// \param[in] _v An bool reference - GZ_MSGS_VISIBLE - void Set(msgs::Boolean *_p, const bool &_v); - - /// \brief Set a msgs::Int32 from an int32_t - /// \param[out] _p A msgs::Int32 pointer - /// \param[in] _v An int32_t reference - GZ_MSGS_VISIBLE - void Set(msgs::Int32 *_p, const int32_t &_v); - - /// \brief Set a msgs::UInt32 from a uint32_t - /// \param[out] _p A msgs::UInt32 pointer - /// \param[in] _v An uint32_t reference - GZ_MSGS_VISIBLE - void Set(msgs::UInt32 *_p, const uint32_t &_v); - - /// \brief Set a msgs::Int64 from an int64_t - /// \param[out] _p A msgs::Int64 pointer - /// \param[in] _v An int64_t reference - GZ_MSGS_VISIBLE - void Set(msgs::Int64 *_p, const int64_t &_v); - - /// \brief Set a msgs::UInt64 from an uint64_t - /// \param[out] _p A msgs::UInt64 pointer - /// \param[in] _v An uint64_t reference - GZ_MSGS_VISIBLE - void Set(msgs::UInt64 *_p, const uint64_t &_v); - - /// \brief Set a msgs::Double from a double - /// \param[out] _p A msgs::Double pointer - /// \param[in] _v An double reference - GZ_MSGS_VISIBLE - void Set(msgs::Double *_p, const double &_v); - - /// \brief Set a msgs::Float from a float - /// \param[out] _p A msgs::Float pointer - /// \param[in] _v An float reference - GZ_MSGS_VISIBLE - void Set(msgs::Float *_p, const float &_v); - - /// \brief Set a msgs::AxisAlignedBox from a math::AxisAlignedBox - /// \param[out] _b A msgs::AxisAlignedBox pointer - /// \param[in] _v An math::AxisAlignedBox reference - GZ_MSGS_VISIBLE - void Set(msgs::AxisAlignedBox *_b, const math::AxisAlignedBox &_v); - - /// \brief This function will set the header and field members of - /// a PointCloudPacked message. This will clear existing values in the - /// PointCloudPacked field and header. - /// \param[out] _msg The message to initialize. - /// \param[in] _frameId Name of the "frame_id". This will be stored as - /// key = "frame_id", value = _frameId in the message header. - /// \param[in] _memoryAligned If true, then each pair in the _fields - /// vector will be aligned at word (sizeof(size_t)) boundaries. - /// Additionally, the `point_step` of the _msg will be set to the - /// nearest word boundary. - /// \param[in] _fields The fields to add to the message. The following - /// strings are reserved, and will generate a set of fields - /// automatically. - /// - /// * "xyz" : This will add the "x", "y", and "z" fields. - GZ_MSGS_VISIBLE - void InitPointCloudPacked(msgs::PointCloudPacked &_msg, - const std::string &_frameId, bool _memoryAligned, - const std::vector> &_fields); - - /// \brief Convert a Discovery::Type to a string. This can be used for - /// debugging purposes. - // \param[in] _t Type of the discovery message. - /// \return String version of Discovery::Type. - GZ_MSGS_VISIBLE - std::string ToString(const msgs::Discovery::Type &_t); - - /// \brief Convert the contents of a model.config file, in the form of - /// an XML string, to a FuelMetadata message. - /// - /// Only the latest versioned model is added to the meta data message. - /// - /// The `` and `` tags are ignored. - /// - /// \param[in] _modelConfigStr A string containing XML data that matches - /// the model.config format. - /// \param[out] _meta The message that receives the converted data. - /// \return True if the conversion was successful. - GZ_MSGS_VISIBLE - bool ConvertFuelMetadata(const std::string &_modelConfigStr, - msgs::FuelMetadata &_meta); - - /// \brief Convert a FuelMetadata message to a string containing XML - /// data that matches the model.config format. - /// - /// The model.config format contains only a subset of the information in - /// a metadata message. The extra information in the metadata message is - /// discarded. - /// - /// \param[in] _meta The FuelMetadata message to convert. - /// \param[out] _modelConfigStr XML string containing the converted - /// message data. - /// \return True if the conversion was successful. - GZ_MSGS_VISIBLE - bool ConvertFuelMetadata(const msgs::FuelMetadata &_meta, - std::string &_modelConfigStr); - } - } -} -#endif diff --git a/proto/CMakeLists.txt b/proto/CMakeLists.txt index 86cad236..ab89ab77 100644 --- a/proto/CMakeLists.txt +++ b/proto/CMakeLists.txt @@ -1,5 +1,5 @@ install( DIRECTORY gz - DESTINATION "${GZ_INCLUDE_INSTALL_DIR_FULL}" + DESTINATION share/protos COMPONENT proto FILES_MATCHING PATTERN "*.proto") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 672c936c..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,267 +0,0 @@ -################################################## -# Build a custom protoc plugin -gz_add_executable(gz_msgs_gen Generator.cc generator_main.cc) -target_link_libraries(gz_msgs_gen - protobuf::libprotoc - protobuf::libprotobuf) -target_include_directories(gz_msgs_gen PRIVATE ${PROTOBUF_INCLUDE_DIR}) -target_compile_features(gz_msgs_gen PRIVATE ${GZ_CXX_11_FEATURES}) - -if (UNIX) - target_link_libraries(gz_msgs_gen pthread) -endif() - -if(INSTALL_GZ_MSGS_GEN_EXECUTABLE) - set_target_properties(gz_msgs_gen PROPERTIES VERSION ${PROJECT_VERSION_FULL}) - install(TARGETS gz_msgs_gen DESTINATION ${GZ_BIN_INSTALL_DIR}) - - # TODO(chapulina) Deprecated. Remove on v10. - install(FILES $ DESTINATION ${GZ_BIN_INSTALL_DIR} RENAME ign_msgs_gen PERMISSIONS OWNER_EXECUTE) -endif() - -find_package(Python3 REQUIRED COMPONENTS Interpreter) - -################################################## -# A function that calls protoc on a protobuf file -# Options: -# GENERATE_RUBY - generates ruby code for the message if specified -# GENERATE_CPP - generates c++ code for the message if specified -# One value arguments: -# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. ".gz.msgs") -# PROTOC_EXEC - Path to protoc -# INPUT_PROTO - Path to the input .proto file -# OUTPUT_CPP_DIR - Path where C++ files are saved -# OUTPUT_RUBY_DIR - Path where Ruby files are saved -# OUTPUT_INCLUDES - A CMake variable name containing a list that the C++ header path should be appended to -# OUTPUT_CPP_HH_VAR - A CMake variable name containing a list that the C++ header path should be appended to -# OUTPUT_GZ_CPP_HH_VAR - A CMake variable name containing a list that the C++ header path should be appended to -# OUTPUT_CPP_CC_VAR - A Cmake variable name containing a list that the C++ source path should be appended to -# OUTPUT_RUBY_VAR - A Cmake variable name containing a list that the ruby file should be apenned to -# Multi value arguments -# PROTO_PATH - Passed to protoc --proto_path -function(gz_msgs_protoc) - set(options GENERATE_RUBY GENERATE_CPP) - set(oneValueArgs - PROTO_PACKAGE - PROTOC_EXEC - INPUT_PROTO - OUTPUT_CPP_DIR - OUTPUT_RUBY_DIR - OUTPUT_INCLUDES - OUTPUT_CPP_HH_VAR - OUTPUT_GZ_CPP_HH_VAR - OUTPUT_DETAIL_CPP_HH_VAR - OUTPUT_CPP_CC_VAR - OUTPUT_RUBY_VAR) - set(multiValueArgs PROTO_PATH) - - cmake_parse_arguments(gz_msgs_protoc "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - - get_filename_component(ABS_FIL ${gz_msgs_protoc_INPUT_PROTO} ABSOLUTE) - get_filename_component(FIL_WE ${gz_msgs_protoc_INPUT_PROTO} NAME_WE) - - set(protoc_args) - set(output_files) - - set(proto_package_dir ".") - if(gz_msgs_protoc_PROTO_PACKAGE) - string(REPLACE "." "/" proto_package_dir ${gz_msgs_protoc_PROTO_PACKAGE}) - endif() - - if(gz_msgs_protoc_GENERATE_CPP) - # Full path to generated header (${PROJECT_BINARY_DIR}/include/gz/msgs/foo.pb.h) - set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.h") - # Full path to generated detail header (${PROJECT_BINARY_DIR}/include/gz/msgs/details/foo.pb.h) - set(output_detail_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/details/${FIL_WE}.pb.h") - # Full path to generated source (${PROJECT_BINARY_DIR}/include/foo.pb.cc) - set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.cc") - - # Generate a clean relative path (gz/msgs/foo.pb.h) - string(REPLACE "${PROJECT_BINARY_DIR}/include/" "" output_include ${output_header}) - list(APPEND ${gz_msgs_protoc_OUTPUT_INCLUDES} "${output_include}") - - list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${output_header}) - list(APPEND ${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${output_source}) - list(APPEND ${gz_msgs_protoc_OUTPUT_GZ_CPP_HH_VAR} ${output_ign_header}) - list(APPEND ${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR} ${output_detail_header}) - - list(APPEND output_files ${output_header}) - list(APPEND output_files ${output_detail_header}) - list(APPEND output_files ${output_ign_header}) - list(APPEND output_files ${output_source}) - - set(${gz_msgs_protoc_OUTPUT_INCLUDES} ${${gz_msgs_protoc_OUTPUT_INCLUDES}} PARENT_SCOPE) - set(${gz_msgs_protoc_OUTPUT_GZ_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_GZ_CPP_HH_VAR}} PARENT_SCOPE) - set(${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR}} PARENT_SCOPE) - set(${gz_msgs_protoc_OUTPUT_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_HH_VAR}} PARENT_SCOPE) - set(${gz_msgs_protoc_OUTPUT_CPP_CC_VAR} ${${gz_msgs_protoc_OUTPUT_CPP_CC_VAR}} PARENT_SCOPE) - endif() - - if(gz_msgs_protoc_GENERATE_RUBY) - file(MAKE_DIRECTORY ${gz_msgs_protoc_OUTPUT_RUBY_DIR}) - set(output_ruby "${gz_msgs_protoc_OUTPUT_RUBY_DIR}${proto_package_dir}/${FIL_WE}_pb.rb") - list(APPEND ${gz_msgs_protoc_OUTPUT_RUBY_VAR} ${output_ruby}) - list(APPEND output_files ${output_ruby}) - list(APPEND protoc_args "--ruby_out=${gz_msgs_protoc_OUTPUT_RUBY_DIR}") - set(${gz_msgs_protoc_OUTPUT_RUBY_VAR} ${${gz_msgs_protoc_OUTPUT_RUBY_VAR}} PARENT_SCOPE) - endif() - - add_custom_command( - OUTPUT ${output_files} - COMMAND Python3::Interpreter - ARGS tools/gz_msgs_generate.py - --protoc-exec "$" - --gz-generator-bin "${GZ_MSGS_GEN_EXECUTABLE}" - --generate-cpp "${gz_msgs_protoc_GENERATE_CPP}" - --generate-ruby "${gz_msgs_protoc_GENERATE_RUBY}" - --output-cpp-path "${gz_msgs_protoc_OUTPUT_CPP_DIR}" - --output-ruby-path "${gz_msgs_protoc_OUTPUT_RUBY_DIR}" - --proto-path "${gz_msgs_protoc_PROTO_PATH}" - --input-path "${ABS_FIL}" - DEPENDS - ${ABS_FIL} - gz_msgs_gen - # While the script is executed in the source directory, it does not write - # to the source tree. All outputs are stored in the build directory. - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMENT "Running protoc on ${gz_msgs_protoc_INPUT_PROTO}" - VERBATIM - ) - -endfunction() - - -################################################## -file (GLOB proto_files ${PROJECT_SOURCE_DIR}/proto/gz/msgs/*.proto) - -foreach(proto_file ${proto_files}) - gz_msgs_protoc( - PROTO_PACKAGE - .gz.msgs - GENERATE_CPP - GENERATE_RUBY - INPUT_PROTO - ${proto_file} - PROTOC_EXEC - protobuf::protoc - OUTPUT_CPP_DIR - "${PROJECT_BINARY_DIR}/include" - OUTPUT_RUBY_DIR - "${PROJECT_BINARY_DIR}/ruby" - OUTPUT_INCLUDES - gen_includes - OUTPUT_CPP_HH_VAR - gen_headers - OUTPUT_DETAIL_CPP_HH_VAR - gen_detail_headers - OUTPUT_GZ_CPP_HH_VAR - gen_ign_headers - OUTPUT_CPP_CC_VAR - gen_sources - OUTPUT_RUBY_VAR - gen_ruby_scripts - PROTO_PATH - "${PROJECT_SOURCE_DIR}/proto") -endforeach() - -if(NOT MSVC) - # -Wno-switch-default flags is required for suppressing a warning in some of - # the generated protobuf files. - set_source_files_properties(${gen_sources} COMPILE_FLAGS -Wno-switch-default) -endif() - -if(MSVC) - # Warning #4251 is the "dll-interface" warning that tells you when types used - # by a class are not being exported. These generated source files have private - # members that don't get exported, so they trigger this warning. However, the - # warning is not important since those members do not need to be interfaced - # with. - set_source_files_properties(${gen_sources} COMPILE_FLAGS "/wd4251 /wd4146") - # Fix for protobuf 3.12 - allow big object files - add_definitions(/bigobj) -endif() - -set_source_files_properties(${gen_headers} ${gen_ign_headers} ${gen_detail_headers} ${gen_sources} ${gen_ruby_scripts} - PROPERTIES GENERATED TRUE) - -message(STATUS "Installing Ruby messages to ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/gz/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}") -install(FILES ${gen_ruby_scripts} DESTINATION ${CMAKE_INSTALL_PREFIX}/${GZ_LIB_INSTALL_DIR}/ruby/gz/${GZ_DESIGNATION}${PROJECT_VERSION_MAJOR}) - -# Install gz/msgs -gz_install_includes( - "${GZ_INCLUDE_INSTALL_DIR_POSTFIX}/gz/${GZ_DESIGNATION}" - ${gen_headers}) - -# Install gz/msgs/details -gz_install_includes( - "${GZ_INCLUDE_INSTALL_DIR_POSTFIX}/gz/${IGN_DESIGNATION}/details" - ${gen_detail_headers}) - -################################################## -# Generate gz/msgs/MessageTypes.hh -foreach (hdr ${gen_includes}) - string(CONCAT gz_msgs_headers ${gz_msgs_headers} "#include <${hdr}>\n") -endforeach() - -configure_file (${CMAKE_CURRENT_SOURCE_DIR}/MessageTypes.hh.in - ${PROJECT_BINARY_DIR}/include/gz/msgs/MessageTypes.hh) - -gz_install_includes( - "${GZ_INCLUDE_INSTALL_DIR_POSTFIX}/gz/${GZ_DESIGNATION}" - "${PROJECT_BINARY_DIR}/include/gz/${GZ_DESIGNATION}/MessageTypes.hh") - -################################################## -# Build the main library -gz_create_core_library(SOURCES - ${gen_sources} - ${PROJECT_SOURCE_DIR}/src/DynamicFactory.cc - ${PROJECT_SOURCE_DIR}/src/Factory.cc - ${PROJECT_SOURCE_DIR}/src/MessageFactory.cc - ${PROJECT_SOURCE_DIR}/src/gz.cc - ${PROJECT_SOURCE_DIR}/src/Utility.cc -) - -target_link_libraries(${PROJECT_LIBRARY_TARGET_NAME} - PUBLIC - protobuf::libprotobuf - gz-math${GZ_MATH_VER}::gz-math${GZ_MATH_VER} - PRIVATE - TINYXML2::TINYXML2 -) - -if (${Protobuf_VERSION} VERSION_LESS 3.12.0) - # Older versions of protobuf (eg on focal) will throw up float-equal errors - # Fixed via: https://github.com/protocolbuffers/protobuf/pull/6000 - target_compile_options(${PROJECT_LIBRARY_TARGET_NAME} PRIVATE -Wno-float-equal) -endif() - -target_include_directories(${PROJECT_LIBRARY_TARGET_NAME} - SYSTEM PUBLIC $) - -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Disable warning in generated *.pb.cc code - target_compile_options(${PROJECT_LIBRARY_TARGET_NAME} PRIVATE -Wno-invalid-offsetof) -endif() - -target_include_directories(${PROJECT_LIBRARY_TARGET_NAME} - PUBLIC - $ - $) - -################################################## -# Build unit tests -gz_get_libsources_and_unittests(sources gtest_sources) - -# Build the unit tests. -gz_build_tests(TYPE UNIT - SOURCES - ${gtest_sources} - LIB_DEPS - TINYXML2::TINYXML2 -) - -################################################## -# gz msgs command -if(NOT WIN32) - add_subdirectory(cmd) -endif() diff --git a/src/MessageTypes.hh.in b/src/MessageTypes.hh.in deleted file mode 100644 index 081746b2..00000000 --- a/src/MessageTypes.hh.in +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2017 Open Source Robotics Foundation - * - * 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. - * -*/ - -/* This file was automatically generated via CMake. - * Do not edit this directly, instead see: - * gz-msgs/src/MessageTypes.hh.in - */ - -#ifndef GZ_MSGS_MESSAGE_TYPES_HH_ -#define GZ_MSGS_MESSAGE_TYPES_HH_ - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4100 4512 4127 4068 4244 4267 4251 4146) -#endif - -@gz_msgs_headers@ - - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/src/Utility.cc b/src/Utility.cc deleted file mode 100644 index c9cbc95a..00000000 --- a/src/Utility.cc +++ /dev/null @@ -1,1365 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 -#include "gz/msgs/Utility.hh" - -#ifdef _WIN32 - static const auto &ignstrtok = strtok_s; -#else - static const auto &ignstrtok = strtok_r; -#endif - - -namespace gz -{ - namespace msgs - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_MSGS_VERSION_NAMESPACE { - /// \brief Left and right trim a string. This was copied from Gazebo - /// common, gz-common/Util.hh, to avoid adding another dependency. - /// Remove this function if gz-common ever becomes a dependency. - /// \param[in] _s String to trim - /// \return Trimmed string - std::string trimmed(std::string _s) - { - // Left trim - _s.erase(_s.begin(), std::find_if(_s.begin(), _s.end(), - [](int c) {return !std::isspace(c);})); - - // Right trim - _s.erase(std::find_if(_s.rbegin(), _s.rend(), - [](int c) {return !std::isspace(c);}).base(), _s.end()); - - return _s; - } - - ///////////////////////////////////////////// - gz::math::Vector3d Convert(const msgs::Vector3d &_v) - { - return gz::math::Vector3d(_v.x(), _v.y(), _v.z()); - } - - ///////////////////////////////////////////// - gz::math::Vector2d Convert(const msgs::Vector2d &_v) - { - return gz::math::Vector2d(_v.x(), _v.y()); - } - - ///////////////////////////////////////////// - gz::math::Quaterniond Convert(const msgs::Quaternion &_q) - { - return gz::math::Quaterniond(_q.w(), _q.x(), _q.y(), _q.z()); - } - - ///////////////////////////////////////////// - gz::math::Pose3d Convert(const msgs::Pose &_p) - { - gz::math::Pose3d result; - - if (_p.has_position()) - result.Pos() = Convert(_p.position()); - if (_p.has_orientation()) - result.Rot() = Convert(_p.orientation()); - - return result; - } - - ///////////////////////////////////////////// - math::Inertiald Convert(const msgs::Inertial &_i) - { - auto pose = msgs::Convert(_i.pose()); - - if (_i.fluid_added_mass().empty()) - { - return math::Inertiald( - math::MassMatrix3d( - _i.mass(), - math::Vector3d(_i.ixx(), _i.iyy(), _i.izz()), - math::Vector3d(_i.ixy(), _i.ixz(), _i.iyz())), - pose); - } - - math::Matrix6d addedMass{ - _i.fluid_added_mass(0), - _i.fluid_added_mass(1), - _i.fluid_added_mass(2), - _i.fluid_added_mass(3), - _i.fluid_added_mass(4), - _i.fluid_added_mass(5), - - _i.fluid_added_mass(1), - _i.fluid_added_mass(6), - _i.fluid_added_mass(7), - _i.fluid_added_mass(8), - _i.fluid_added_mass(9), - _i.fluid_added_mass(10), - - _i.fluid_added_mass(2), - _i.fluid_added_mass(7), - _i.fluid_added_mass(11), - _i.fluid_added_mass(12), - _i.fluid_added_mass(13), - _i.fluid_added_mass(14), - - _i.fluid_added_mass(3), - _i.fluid_added_mass(8), - _i.fluid_added_mass(12), - _i.fluid_added_mass(15), - _i.fluid_added_mass(16), - _i.fluid_added_mass(17), - - _i.fluid_added_mass(4), - _i.fluid_added_mass(9), - _i.fluid_added_mass(13), - _i.fluid_added_mass(16), - _i.fluid_added_mass(18), - _i.fluid_added_mass(19), - - _i.fluid_added_mass(5), - _i.fluid_added_mass(10), - _i.fluid_added_mass(14), - _i.fluid_added_mass(17), - _i.fluid_added_mass(19), - _i.fluid_added_mass(20) - }; - - return math::Inertiald( - math::MassMatrix3d( - _i.mass(), - math::Vector3d(_i.ixx(), _i.iyy(), _i.izz()), - math::Vector3d(_i.ixy(), _i.ixz(), _i.iyz())), - pose, addedMass); - } - - ///////////////////////////////////////////// - math::SphericalCoordinates Convert(const msgs::SphericalCoordinates &_sc) - { - math::SphericalCoordinates out; - if (_sc.surface_model() == msgs::SphericalCoordinates::EARTH_WGS84) - { - out.SetSurface(math::SphericalCoordinates::EARTH_WGS84); - } - else if (_sc.surface_model() == msgs::SphericalCoordinates::MOON_SCS) - { - out.SetSurface(math::SphericalCoordinates::MOON_SCS); - } - else if (_sc.surface_model() == - msgs::SphericalCoordinates::CUSTOM_SURFACE) - { - out.SetSurface(math::SphericalCoordinates::CUSTOM_SURFACE, - _sc.surface_axis_equatorial(), _sc.surface_axis_polar()); - } - else - { - std::cerr << "Unrecognized spherical surface type [" - << _sc.surface_model() - << "]. Using default." << std::endl; - } - out.SetLatitudeReference(GZ_DTOR(_sc.latitude_deg())); - out.SetLongitudeReference(GZ_DTOR(_sc.longitude_deg())); - out.SetElevationReference(_sc.elevation()); - out.SetHeadingOffset(GZ_DTOR(_sc.heading_deg())); - return out; - } - - ///////////////////////////////////////////// - math::AxisAlignedBox Convert(const msgs::AxisAlignedBox &_b) - { - return math::AxisAlignedBox(msgs::Convert(_b.min_corner()), - msgs::Convert(_b.max_corner())); - } - - ///////////////////////////////////////////// - msgs::AxisAlignedBox Convert(const math::AxisAlignedBox &_b) - { - msgs::AxisAlignedBox result; - msgs::Set(result.mutable_min_corner(), _b.Min()); - msgs::Set(result.mutable_max_corner(), _b.Max()); - return result; - } - - ///////////////////////////////////////////// - void Set(msgs::AxisAlignedBox *_b, const math::AxisAlignedBox &_v) - { - msgs::Set(_b->mutable_min_corner(), _v.Min()); - msgs::Set(_b->mutable_max_corner(), _v.Max()); - } - - ///////////////////////////////////////////// - math::Color Convert(const msgs::Color &_c) - { - return math::Color(_c.r(), _c.g(), _c.b(), _c.a()); - } - - ///////////////////////////////////////////// - gz::math::Planed Convert(const msgs::PlaneGeom &_p) - { - return gz::math::Planed(Convert(_p.normal()), - gz::math::Vector2d(_p.size().x(), _p.size().y()), - _p.d()); - } - - ///////////////////////////////////////////// - std::string Convert(const msgs::StringMsg &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - bool Convert(const msgs::Boolean &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - int32_t Convert(const msgs::Int32 &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - uint32_t Convert(const msgs::UInt32 &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - int64_t Convert(const msgs::Int64 &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - uint64_t Convert(const msgs::UInt64 &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - double Convert(const msgs::Double &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////// - float Convert(const msgs::Float &_m) - { - return _m.data(); - } - - ///////////////////////////////////////////////// - std::chrono::steady_clock::duration Convert(const msgs::Time &_time) - { - return std::chrono::seconds(_time.sec()) + - std::chrono::nanoseconds(_time.nsec()); - } - - ///////////////////////////////////////////////// - msgs::Vector3d Convert(const gz::math::Vector3d &_v) - { - msgs::Vector3d result; - result.set_x(_v.X()); - result.set_y(_v.Y()); - result.set_z(_v.Z()); - return result; - } - - ///////////////////////////////////////////////// - msgs::Vector2d Convert(const gz::math::Vector2d &_v) - { - msgs::Vector2d result; - result.set_x(_v.X()); - result.set_y(_v.Y()); - return result; - } - - ///////////////////////////////////////////// - msgs::Quaternion Convert(const gz::math::Quaterniond &_q) - { - msgs::Quaternion result; - result.set_x(_q.X()); - result.set_y(_q.Y()); - result.set_z(_q.Z()); - result.set_w(_q.W()); - return result; - } - - ///////////////////////////////////////////// - msgs::Pose Convert(const gz::math::Pose3d &_p) - { - msgs::Pose result; - result.mutable_position()->CopyFrom(Convert(_p.Pos())); - result.mutable_orientation()->CopyFrom(Convert(_p.Rot())); - return result; - } - - ///////////////////////////////////////////// - msgs::Color Convert(const math::Color &_c) - { - msgs::Color result; - result.set_r(_c.R()); - result.set_g(_c.G()); - result.set_b(_c.B()); - result.set_a(_c.A()); - return result; - } - - ///////////////////////////////////////////// - msgs::Inertial Convert(const math::Inertiald &_i) - { - msgs::Inertial result; - msgs::Set(&result, _i); - return result; - } - - ///////////////////////////////////////////// - msgs::Inertial Convert(const math::MassMatrix3d &_m) - { - msgs::Inertial result; - msgs::Set(&result, _m); - return result; - } - - ///////////////////////////////////////////// - msgs::SphericalCoordinates Convert(const math::SphericalCoordinates &_sc) - { - msgs::SphericalCoordinates result; - msgs::Set(&result, _sc); - return result; - } - - ///////////////////////////////////////////// - msgs::PlaneGeom Convert(const gz::math::Planed &_p) - { - msgs::PlaneGeom result; - result.mutable_normal()->CopyFrom(Convert(_p.Normal())); - result.mutable_size()->set_x(_p.Size().X()); - result.mutable_size()->set_y(_p.Size().Y()); - result.set_d(_p.Offset()); - return result; - } - - ///////////////////////////////////////////// - msgs::StringMsg Convert(const std::string &_s) - { - msgs::StringMsg result; - result.set_data(_s); - return result; - } - - ///////////////////////////////////////////// - msgs::Boolean Convert(const bool &_b) - { - msgs::Boolean result; - result.set_data(_b); - return result; - } - - ///////////////////////////////////////////// - msgs::Int32 Convert(const int32_t &_i) - { - msgs::Int32 result; - result.set_data(_i); - return result; - } - - ///////////////////////////////////////////// - msgs::UInt32 Convert(const uint32_t &_u) - { - msgs::UInt32 result; - result.set_data(_u); - return result; - } - - ///////////////////////////////////////////// - msgs::Int64 Convert(const int64_t &_i) - { - msgs::Int64 result; - result.set_data(_i); - return result; - } - - ///////////////////////////////////////////// - msgs::UInt64 Convert(const uint64_t &_u) - { - msgs::UInt64 result; - result.set_data(_u); - return result; - } - - - ///////////////////////////////////////////// - msgs::Double Convert(const double &_d) - { - msgs::Double result; - result.set_data(_d); - return result; - } - - ///////////////////////////////////////////////// - msgs::Time Convert(const std::chrono::steady_clock::duration &_time_point) - { - std::pair timeSecAndNsecs = - gz::math::durationToSecNsec(_time_point); - msgs::Time msg; - msg.set_sec(timeSecAndNsecs.first); - msg.set_nsec(timeSecAndNsecs.second); - return msg; - } - - ///////////////////////////////////////////// - msgs::Float Convert(const float &_f) - { - msgs::Float result; - result.set_data(_f); - return result; - } - - ///////////////////////////////////////////// - void Set(msgs::Vector3d *_pt, const gz::math::Vector3d &_v) - { - _pt->set_x(_v.X()); - _pt->set_y(_v.Y()); - _pt->set_z(_v.Z()); - } - - ///////////////////////////////////////////// - void Set(msgs::Vector2d *_pt, const gz::math::Vector2d &_v) - { - _pt->set_x(_v.X()); - _pt->set_y(_v.Y()); - } - - ///////////////////////////////////////////// - void Set(msgs::Quaternion *_q, const gz::math::Quaterniond &_v) - { - _q->set_x(_v.X()); - _q->set_y(_v.Y()); - _q->set_z(_v.Z()); - _q->set_w(_v.W()); - } - - ///////////////////////////////////////////// - void Set(msgs::Pose *_p, const gz::math::Pose3d &_v) - { - Set(_p->mutable_position(), _v.Pos()); - Set(_p->mutable_orientation(), _v.Rot()); - } - - ///////////////////////////////////////////////// - void Set(msgs::PlaneGeom *_p, const gz::math::Planed &_v) - { - Set(_p->mutable_normal(), _v.Normal()); - _p->mutable_size()->set_x(_v.Size().X()); - _p->mutable_size()->set_y(_v.Size().Y()); - _p->set_d(_v.Offset()); - } - - ///////////////////////////////////////////// - void Set(msgs::Color *_c, const math::Color &_v) - { - _c->set_r(_v.R()); - _c->set_g(_v.G()); - _c->set_b(_v.B()); - _c->set_a(_v.A()); - } - - ///////////////////////////////////////////////// - void Set(msgs::Inertial *_i, const math::MassMatrix3d &_m) - { - _i->set_mass(_m.Mass()); - _i->set_ixx(_m.Ixx()); - _i->set_iyy(_m.Iyy()); - _i->set_izz(_m.Izz()); - _i->set_ixy(_m.Ixy()); - _i->set_ixz(_m.Ixz()); - _i->set_iyz(_m.Iyz()); - } - - ///////////////////////////////////////////////// - void Set(msgs::Inertial *_i, const math::Inertiald &_m) - { - msgs::Set(_i, _m.MassMatrix()); - msgs::Set(_i->mutable_pose(), _m.Pose()); - - if (_m.FluidAddedMass().has_value()) - { - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 0)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 1)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 2)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 3)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 4)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(0, 5)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(1, 1)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(1, 2)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(1, 3)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(1, 4)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(1, 5)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(2, 2)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(2, 3)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(2, 4)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(2, 5)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(3, 3)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(3, 4)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(3, 5)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(4, 4)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(4, 5)); - _i->add_fluid_added_mass(_m.FluidAddedMass().value()(5, 5)); - } - } - - ///////////////////////////////////////////////// - void Set(msgs::SphericalCoordinates *_sc, - const math::SphericalCoordinates &_m) - { - if (_m.Surface() == math::SphericalCoordinates::EARTH_WGS84) - { - _sc->set_surface_model(msgs::SphericalCoordinates::EARTH_WGS84); - } - else if (_m.Surface() == math::SphericalCoordinates::MOON_SCS) - { - _sc->set_surface_model(msgs::SphericalCoordinates::MOON_SCS); - } - else if (_m.Surface() == - math::SphericalCoordinates::CUSTOM_SURFACE) - { - _sc->set_surface_model( - msgs::SphericalCoordinates::CUSTOM_SURFACE); - _sc->set_surface_axis_equatorial(_m.SurfaceAxisEquatorial()); - _sc->set_surface_axis_polar(_m.SurfaceAxisPolar()); - } - else - { - std::cerr << "Unrecognized spherical surface type [" - << _m.Surface() - << "]. Not populating message field." << std::endl; - } - _sc->set_latitude_deg(_m.LatitudeReference().Degree()); - _sc->set_longitude_deg(_m.LongitudeReference().Degree()); - _sc->set_elevation(_m.ElevationReference()); - _sc->set_heading_deg(_m.HeadingOffset().Degree()); - } - - ///////////////////////////////////////////////// - void Set(msgs::StringMsg *_p, const std::string &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::Boolean *_p, const bool &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::Int32 *_p, const int32_t &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::UInt32 *_p, const uint32_t &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::Int64 *_p, const int64_t &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::UInt64 *_p, const uint64_t &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::Double *_p, const double &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////////// - void Set(msgs::Float *_p, const float &_v) - { - _p->set_data(_v); - } - - ///////////////////////////////////////////// - msgs::Joint::Type ConvertJointType(const std::string &_str) - { - msgs::Joint::Type result = msgs::Joint::REVOLUTE; - if (_str == "revolute") - { - result = msgs::Joint::REVOLUTE; - } - else if (_str == "revolute2") - { - result = msgs::Joint::REVOLUTE2; - } - else if (_str == "prismatic") - { - result = msgs::Joint::PRISMATIC; - } - else if (_str == "universal") - { - result = msgs::Joint::UNIVERSAL; - } - else if (_str == "ball") - { - result = msgs::Joint::BALL; - } - else if (_str == "screw") - { - result = msgs::Joint::SCREW; - } - else if (_str == "gearbox") - { - result = msgs::Joint::GEARBOX; - } - else if (_str == "fixed") - { - result = msgs::Joint::FIXED; - } - else if (_str == "continuous") - { - result = msgs::Joint::CONTINUOUS; - } - else - { - std::cerr << "Unrecognized JointType [" - << _str - << "], returning msgs::Joint::REVOLUTE" - << std::endl; - } - return result; - } - - ///////////////////////////////////////////// - std::string ConvertJointType(const msgs::Joint::Type &_type) - { - std::string result; - switch (_type) - { - case msgs::Joint::REVOLUTE: - { - result = "revolute"; - break; - } - case msgs::Joint::REVOLUTE2: - { - result = "revolute2"; - break; - } - case msgs::Joint::PRISMATIC: - { - result = "prismatic"; - break; - } - case msgs::Joint::UNIVERSAL: - { - result = "universal"; - break; - } - case msgs::Joint::BALL: - { - result = "ball"; - break; - } - case msgs::Joint::SCREW: - { - result = "screw"; - break; - } - case msgs::Joint::GEARBOX: - { - result = "gearbox"; - break; - } - case msgs::Joint::FIXED: - { - result = "fixed"; - break; - } - case msgs::Joint::CONTINUOUS: - { - result = "continuous"; - break; - } - default: - { - result = "unknown"; - std::cerr << "Unrecognized JointType [" - << _type - << "], returning 'unknown'" - << std::endl; - break; - } - } - return result; - } - - ///////////////////////////////////////////////// - msgs::Geometry::Type ConvertGeometryType(const std::string &_str) - { - msgs::Geometry::Type result = msgs::Geometry::BOX; - if (_str == "box") - { - result = msgs::Geometry::BOX; - } - else if (_str == "capsule") - { - result = msgs::Geometry::CAPSULE; - } - else if (_str == "cylinder") - { - result = msgs::Geometry::CYLINDER; - } - else if (_str == "ellipsoid") - { - result = msgs::Geometry::ELLIPSOID; - } - else if (_str == "sphere") - { - result = msgs::Geometry::SPHERE; - } - else if (_str == "plane") - { - result = msgs::Geometry::PLANE; - } - else if (_str == "image") - { - result = msgs::Geometry::IMAGE; - } - else if (_str == "heightmap") - { - result = msgs::Geometry::HEIGHTMAP; - } - else if (_str == "mesh") - { - result = msgs::Geometry::MESH; - } - else if (_str == "polyline") - { - result = msgs::Geometry::POLYLINE; - } - else - { - std::cerr << "Unrecognized Geometry::Type [" - << _str - << "], returning msgs::Geometry::BOX" - << std::endl; - } - - return result; - } - - ///////////////////////////////////////////////// - std::string ConvertGeometryType(const msgs::Geometry::Type _type) - { - std::string result; - switch (_type) - { - case msgs::Geometry::BOX: - { - result = "box"; - break; - } - case msgs::Geometry::CAPSULE: - { - result = "capsule"; - break; - } - case msgs::Geometry::CYLINDER: - { - result = "cylinder"; - break; - } - case msgs::Geometry::ELLIPSOID: - { - result = "ellipsoid"; - break; - } - case msgs::Geometry::SPHERE: - { - result = "sphere"; - break; - } - case msgs::Geometry::PLANE: - { - result = "plane"; - break; - } - case msgs::Geometry::IMAGE: - { - result = "image"; - break; - } - case msgs::Geometry::HEIGHTMAP: - { - result = "heightmap"; - break; - } - case msgs::Geometry::MESH: - { - result = "mesh"; - break; - } - case msgs::Geometry::POLYLINE: - { - result = "polyline"; - break; - } - default: - { - result = "unknown"; - std::cerr << "Unrecognized Geometry::Type [" - << _type - << "], returning 'unknown'" - << std::endl; - break; - } - } - return result; - } - - ///////////////////////////////////////////////// - msgs::Material::ShaderType ConvertShaderType(const std::string &_str) - { - auto result = msgs::Material::VERTEX; - if (_str == "vertex") - { - result = msgs::Material::VERTEX; - } - else if (_str == "pixel") - { - result = msgs::Material::PIXEL; - } - else if (_str == "normal_map_object_space") - { - result = msgs::Material::NORMAL_MAP_OBJECT_SPACE; - } - else if (_str == "normal_map_tangent_space") - { - result = msgs::Material::NORMAL_MAP_TANGENT_SPACE; - } - else - { - std::cerr << "Unrecognized Material::ShaderType [" - << _str - << "], returning msgs::Material::VERTEX" - << std::endl; - } - return result; - } - - ///////////////////////////////////////////////// - std::string ConvertShaderType(const msgs::Material::ShaderType &_type) - { - std::string result; - switch (_type) - { - case msgs::Material::VERTEX: - { - result = "vertex"; - break; - } - case msgs::Material::PIXEL: - { - result = "pixel"; - break; - } - case msgs::Material::NORMAL_MAP_OBJECT_SPACE: - { - result = "normal_map_object_space"; - break; - } - case msgs::Material::NORMAL_MAP_TANGENT_SPACE: - { - result = "normal_map_tangent_space"; - break; - } - default: - { - result = "unknown"; - std::cerr << "Unrecognized Material::ShaderType [" - << _type - << "], returning 'unknown'" - << std::endl; - break; - } - } - return result; - } - - ///////////////////////////////////////////////// - void InitPointCloudPacked(msgs::PointCloudPacked &_msg, - const std::string &_frameId, bool _memoryAligned, - const std::vector> &_fields) - { - uint32_t offset = 0; - - // Helper function that will set a single field. - std::function initPointCloudPackedHelper = - [&](const std::string &_name, - msgs::PointCloudPacked::Field::DataType _type) -> void - { - msgs::PointCloudPacked::Field *newField = _msg.add_field(); - newField->set_name(_name); - newField->set_count(1); - newField->set_datatype(_type); - newField->set_offset(offset); - switch (_type) - { - case msgs::PointCloudPacked::Field::INT8: - case msgs::PointCloudPacked::Field::UINT8: - offset += 1; - break; - case msgs::PointCloudPacked::Field::INT16: - case msgs::PointCloudPacked::Field::UINT16: - offset += 2; - break; - case msgs::PointCloudPacked::Field::INT32: - case msgs::PointCloudPacked::Field::UINT32: - case msgs::PointCloudPacked::Field::FLOAT32: - offset += 4; - break; - case msgs::PointCloudPacked::Field::FLOAT64: - offset += 8; - break; - // LCOV_EXCL_START - default: - std::cerr << "PointCloudPacked field datatype of [" - << _type << "] is invalid.\n"; - break; - // LCOV_EXCL_STOP - } - }; - - // Set the frame - _msg.mutable_header()->clear_data(); - msgs::Header::Map *frame = _msg.mutable_header()->add_data(); - frame->set_key("frame_id"); - frame->add_value(_frameId); - - _msg.clear_field(); - // Setup the point cloud message. - for (const std::pair &field : _fields) - { - if (field.first == "xyz") - { - initPointCloudPackedHelper("x", field.second); - initPointCloudPackedHelper("y", field.second); - initPointCloudPackedHelper("z", field.second); - } - else - { - initPointCloudPackedHelper(field.first, field.second); - } - - // Memory align the field. - if (_memoryAligned) - offset = math::roundUpMultiple(offset, sizeof(size_t)); - } - - // Set the point_step - if (_memoryAligned) - _msg.set_point_step(math::roundUpMultiple(offset, sizeof(size_t))); - else - _msg.set_point_step(offset); - } - - ///////////////////////////////////////////// - std::string ToString(const msgs::Discovery::Type &_t) - { - switch (_t) - { - default: - case msgs::Discovery::UNINITIALIZED: - return "UNINITIALIZED"; - case msgs::Discovery::ADVERTISE: - return "ADVERTISE"; - case msgs::Discovery::SUBSCRIBE: - return "SUBSCRIBE"; - case msgs::Discovery::UNADVERTISE: - return "UNADVERTISE"; - case msgs::Discovery::HEARTBEAT: - return "HEARTBEAT"; - case msgs::Discovery::BYE: - return "BYE"; - case msgs::Discovery::NEW_CONNECTION: - return "NEW_CONNECTION"; - case msgs::Discovery::END_CONNECTION: - return "END_CONNECTION"; - case msgs::Discovery::SUBSCRIBERS_REQ: - return "SUBSCRIBERS_REQ"; - case msgs::Discovery::SUBSCRIBERS_REP: - return "SUBSCRIBERS_REP"; - }; - } - - ///////////////////////////////////////////// - msgs::PixelFormatType ConvertPixelFormatType(const std::string &_str) - { - if (_str == "L_INT8") - { - return msgs::PixelFormatType::L_INT8; - } - else if (_str == "L_INT16") - { - return msgs::PixelFormatType::L_INT16; - } - else if (_str == "RGB_INT8") - { - return msgs::PixelFormatType::RGB_INT8; - } - else if (_str == "RGBA_INT8") - { - return msgs::PixelFormatType::RGBA_INT8; - } - else if (_str == "BGRA_INT8") - { - return msgs::PixelFormatType::BGRA_INT8; - } - else if (_str == "RGB_INT16") - { - return msgs::PixelFormatType::RGB_INT16; - } - else if (_str == "RGB_INT32") - { - return msgs::PixelFormatType::RGB_INT32; - } - else if (_str == "BGR_INT8") - { - return msgs::PixelFormatType::BGR_INT8; - } - else if (_str == "BGR_INT16") - { - return msgs::PixelFormatType::BGR_INT16; - } - else if (_str == "BGR_INT32") - { - return msgs::PixelFormatType::BGR_INT32; - } - else if (_str == "R_FLOAT16") - { - return msgs::PixelFormatType::R_FLOAT16; - } - else if (_str == "RGB_FLOAT16") - { - return msgs::PixelFormatType::RGB_FLOAT16; - } - else if (_str == "R_FLOAT32") - { - return msgs::PixelFormatType::R_FLOAT32; - } - else if (_str == "RGB_FLOAT32") - { - return msgs::PixelFormatType::RGB_FLOAT32; - } - else if (_str == "BAYER_RGGB8") - { - return msgs::PixelFormatType::BAYER_RGGB8; - } - else if (_str == "BAYER_BGGR8") - { - return msgs::PixelFormatType::BAYER_BGGR8; - } - else if (_str == "BAYER_GBRG8") - { - return msgs::PixelFormatType::BAYER_GBRG8; - } - else if (_str == "BAYER_GRBG8") - { - return msgs::PixelFormatType::BAYER_GRBG8; - } - - return msgs::PixelFormatType::UNKNOWN_PIXEL_FORMAT; - } - - ///////////////////////////////////////////// - std::string ConvertPixelFormatType(const msgs::PixelFormatType &_t) - { - switch (_t) - { - default: - case msgs::PixelFormatType::UNKNOWN_PIXEL_FORMAT: - return "UNKNOWN_PIXEL_FORMAT"; - case msgs::PixelFormatType::L_INT8: - return "L_INT8"; - case msgs::PixelFormatType::L_INT16: - return "L_INT16"; - case msgs::PixelFormatType::RGB_INT8: - return "RGB_INT8"; - case msgs::PixelFormatType::RGBA_INT8: - return "RGBA_INT8"; - case msgs::PixelFormatType::BGRA_INT8: - return "BGRA_INT8"; - case msgs::PixelFormatType::RGB_INT16: - return "RGB_INT16"; - case msgs::PixelFormatType::RGB_INT32: - return "RGB_INT32"; - case msgs::PixelFormatType::BGR_INT8: - return "BGR_INT8"; - case msgs::PixelFormatType::BGR_INT16: - return "BGR_INT16"; - case msgs::PixelFormatType::BGR_INT32: - return "BGR_INT32"; - case msgs::PixelFormatType::R_FLOAT16: - return "R_FLOAT16"; - case msgs::PixelFormatType::RGB_FLOAT16: - return "RGB_FLOAT16"; - case msgs::PixelFormatType::R_FLOAT32: - return "R_FLOAT32"; - case msgs::PixelFormatType::RGB_FLOAT32: - return "RGB_FLOAT32"; - case msgs::PixelFormatType::BAYER_RGGB8: - return "BAYER_RGGB8"; - case msgs::PixelFormatType::BAYER_BGGR8: - return "BAYER_BGGR8"; - case msgs::PixelFormatType::BAYER_GBRG8: - return "BAYER_GBRG8"; - case msgs::PixelFormatType::BAYER_GRBG8: - return "BAYER_GRBG8"; - }; - } - - ///////////////////////////////////////////////// - bool ConvertFuelMetadata(const std::string &_modelConfigStr, - msgs::FuelMetadata &_meta) - { - gz::msgs::FuelMetadata meta; - - // Load the model config into tinyxml - tinyxml2::XMLDocument modelConfigDoc; - if (modelConfigDoc.Parse(_modelConfigStr.c_str()) != - tinyxml2::XML_SUCCESS) - { - std::cerr << "Unable to parse model config XML string.\n"; - return false; - } - - // Get the top level or element. - tinyxml2::XMLElement *topElement = modelConfigDoc.FirstChildElement( - "model"); - bool isModel = true; - if (!topElement) - { - topElement = modelConfigDoc.FirstChildElement("world"); - if (!topElement) - { - std::cerr << "Model config string does not contain a " - << " or element\n"; - return false; - } - isModel = false; - } - - // Read the name, which is a mandatory element. - tinyxml2::XMLElement *elem = topElement->FirstChildElement("name"); - if (!elem || !elem->GetText()) - { - std::cerr << "Model config string does not contain a element\n"; - return false; - } - meta.set_name(trimmed(elem->GetText())); - - // Read the version, if present. - elem = topElement->FirstChildElement("version"); - if (elem && elem->GetText()) - { - auto version = std::stoi(trimmed(elem->GetText())); - meta.set_version(version); - } - - // Read the description, if present. - elem = topElement->FirstChildElement("description"); - if (elem && elem->GetText()) - meta.set_description(trimmed(elem->GetText())); - - // Read the dependencies, if any. - elem = topElement->FirstChildElement("depend"); - while (elem) - { - auto modelElem = elem->FirstChildElement("model"); - if (modelElem) - { - auto uriElem = modelElem->FirstChildElement("uri"); - if (uriElem) - { - auto dependency = meta.add_dependencies(); - dependency->set_uri(uriElem->GetText()); - } - } - elem = elem->NextSiblingElement("depend"); - } - - // Read the authors, if any. - elem = topElement->FirstChildElement("author"); - while (elem) - { - gz::msgs::FuelMetadata::Contact *author = meta.add_authors(); - // Get the author name and email - if (elem->FirstChildElement("name") && - elem->FirstChildElement("name")->GetText()) - { - author->set_name(trimmed(elem->FirstChildElement("name")->GetText())); - } - if (elem->FirstChildElement("email") && - elem->FirstChildElement("email")->GetText()) - { - author->set_email( - trimmed(elem->FirstChildElement("email")->GetText())); - } - - elem = elem->NextSiblingElement("author"); - } - - // Get the most recent SDF file - elem = topElement->FirstChildElement("sdf"); - math::SemanticVersion maxVer; - while (elem) - { - if (elem->GetText() && elem->Attribute("version")) - { - std::string verStr = elem->Attribute("version"); - math::SemanticVersion ver(trimmed(verStr)); - if (ver > maxVer) - { - gz::msgs::Version *verMsg; - - if (isModel) - { - meta.mutable_model()->mutable_file_format()->set_name("sdf"); - verMsg = - meta.mutable_model()->mutable_file_format()->mutable_version(); - meta.mutable_model()->set_file(trimmed(elem->GetText())); - } - else - { - meta.mutable_world()->mutable_file_format()->set_name("sdf"); - verMsg = - meta.mutable_world()->mutable_file_format()->mutable_version(); - meta.mutable_world()->set_file(trimmed(elem->GetText())); - } - - verMsg->set_major(ver.Major()); - verMsg->set_minor(ver.Minor()); - verMsg->set_patch(ver.Patch()); - verMsg->set_prerelease(ver.Prerelease()); - verMsg->set_build(ver.Build()); - } - } - - elem = elem->NextSiblingElement("sdf"); - } - if (meta.model().file().empty() && meta.world().file().empty()) - { - std::cerr << "Model config string does not contain an element\n"; - return false; - } - - _meta.CopyFrom(meta); - return true; - } - - ///////////////////////////////////////////////// - bool ConvertFuelMetadata(const msgs::FuelMetadata &_meta, - std::string &_modelConfigStr) - { - std::ostringstream out; - - // Output opening tag. - if (_meta.has_model()) - { - if (_meta.model().file_format().name() != "sdf") - { - std::cerr << "Model _metadata does not contain an SDF file.\n"; - return false; - } - - out << "\n" - << " \n" - << " " - << _meta.model().file() << "\n"; - } - else - { - if (_meta.world().file_format().name() != "sdf") - { - std::cerr << "World _metadata does not contain an SDF file.\n"; - return false; - } - - out << "\n" - << " \n" - << " " - << _meta.world().file() << "\n"; - } - - out << " " << _meta.name() << "\n" - << " " << _meta.version() << "\n" - << " " << _meta.description() << "\n"; - - // Output author information. - for (int i = 0; i < _meta.authors_size(); ++i) - { - out << " \n" - << " " << _meta.authors(i).name() << "\n" - << " " << _meta.authors(i).email() << "\n" - << " \n"; - } - - // Output dependency information. - for (int i = 0; i < _meta.dependencies_size(); ++i) - { - out << " \n" - << " \n" - << " " << _meta.dependencies(i).uri() << "\n" - << " \n" - << " \n"; - } - - // Output closing tag. - if (_meta.has_model()) - out << " \n"; - else - out << " \n"; - - _modelConfigStr = out.str(); - return true; - } - } -} -} diff --git a/src/Utility_TEST.cc b/src/Utility_TEST.cc deleted file mode 100644 index a93d5363..00000000 --- a/src/Utility_TEST.cc +++ /dev/null @@ -1,1172 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 "gz/msgs/wrench.pb.h" -#include "gz/msgs/Utility.hh" - -using namespace gz; - -///////////////////////////////////////////////// -TEST(UtilityTest, CovertMathVector3ToMsgs) -{ - msgs::Vector3d msg = msgs::Convert(math::Vector3d(1, 2, 3)); - EXPECT_DOUBLE_EQ(1, msg.x()); - EXPECT_DOUBLE_EQ(2, msg.y()); - EXPECT_DOUBLE_EQ(3, msg.z()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMsgsVector3dToMath) -{ - msgs::Vector3d msg = msgs::Convert(math::Vector3d(1, 2, 3)); - math::Vector3d v = msgs::Convert(msg); - EXPECT_DOUBLE_EQ(1, v.X()); - EXPECT_DOUBLE_EQ(2, v.Y()); - EXPECT_DOUBLE_EQ(3, v.Z()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, CovertMathVector2ToMsgs) -{ - msgs::Vector2d msg = msgs::Convert(math::Vector2d(1, 2)); - EXPECT_DOUBLE_EQ(1, msg.x()); - EXPECT_DOUBLE_EQ(2, msg.y()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMsgsVector2dToMath) -{ - msgs::Vector2d msg = msgs::Convert(math::Vector2d(1, 2)); - math::Vector2d v = msgs::Convert(msg); - EXPECT_DOUBLE_EQ(1, v.X()); - EXPECT_DOUBLE_EQ(2, v.Y()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMathQuaterionToMsgs) -{ - msgs::Quaternion msg = - msgs::Convert(math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI)); - - EXPECT_TRUE(math::equal(msg.x(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(msg.y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(msg.z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(msg.w(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMsgsQuaterionToMath) -{ - msgs::Quaternion msg = - msgs::Convert(math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI)); - math::Quaterniond v = msgs::Convert(msg); - - // TODO(anyone): to real unit test move math::equal to EXPECT_DOUBLE_EQ - EXPECT_TRUE(math::equal(v.X(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(v.Y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(v.Z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(v.W(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertPoseMathToMsgs) -{ - msgs::Pose msg = msgs::Convert(math::Pose3d( - math::Vector3d(1, 2, 3), - math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI))); - - EXPECT_DOUBLE_EQ(1, msg.position().x()); - EXPECT_DOUBLE_EQ(2, msg.position().y()); - EXPECT_DOUBLE_EQ(3, msg.position().z()); - - EXPECT_TRUE(math::equal(msg.orientation().x(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(msg.orientation().y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(msg.orientation().z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(msg.orientation().w(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMsgPoseToMath) -{ - msgs::Pose msg = msgs::Convert( - math::Pose3d(math::Vector3d(1, 2, 3), - math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI))); - math::Pose3d v = msgs::Convert(msg); - - EXPECT_DOUBLE_EQ(1, v.Pos().X()); - EXPECT_DOUBLE_EQ(2, v.Pos().Y()); - EXPECT_DOUBLE_EQ(3, v.Pos().Z()); - EXPECT_TRUE(math::equal(v.Rot().X(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(v.Rot().Y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(v.Rot().Z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(v.Rot().W(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMathColorToMsgs) -{ - msgs::Color msg = msgs::Convert(math::Color(.1f, .2f, .3f, 1.0f)); - - EXPECT_FLOAT_EQ(0.1f, msg.r()); - EXPECT_FLOAT_EQ(0.2f, msg.g()); - EXPECT_FLOAT_EQ(0.3f, msg.b()); - EXPECT_FLOAT_EQ(1.0f, msg.a()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsColorToMath) -{ - msgs::Color msg = msgs::Convert(math::Color(.1f, .2f, .3f, 1.0f)); - math::Color v = msgs::Convert(msg); - - EXPECT_FLOAT_EQ(0.1f, v.R()); - EXPECT_FLOAT_EQ(0.2f, v.G()); - EXPECT_FLOAT_EQ(0.3f, v.B()); - EXPECT_FLOAT_EQ(1.0f, v.A()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMathPlaneToMsgs) -{ - msgs::PlaneGeom msg = msgs::Convert( - math::Planed(math::Vector3d(0, 0, 1), - math::Vector2d(123, 456), 1.0)); - - EXPECT_DOUBLE_EQ(0, msg.normal().x()); - EXPECT_DOUBLE_EQ(0, msg.normal().y()); - EXPECT_DOUBLE_EQ(1, msg.normal().z()); - - EXPECT_DOUBLE_EQ(123, msg.size().x()); - EXPECT_DOUBLE_EQ(456, msg.size().y()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertMsgsPlaneToMath) -{ - msgs::PlaneGeom msg = msgs::Convert( - math::Planed(math::Vector3d(0, 0, 1), - math::Vector2d(123, 456), 1.0)); - math::Planed v = msgs::Convert(msg); - - EXPECT_DOUBLE_EQ(0, v.Normal().X()); - EXPECT_DOUBLE_EQ(0, v.Normal().Y()); - EXPECT_DOUBLE_EQ(1, v.Normal().Z()); - - EXPECT_DOUBLE_EQ(123, v.Size().X()); - EXPECT_DOUBLE_EQ(456, v.Size().Y()); - - EXPECT_TRUE(math::equal(1.0, v.Offset())); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMathInertialToMsgs) -{ - const auto pose = math::Pose3d(5, 6, 7, 0.4, 0.5, 0.6); - msgs::Inertial msg = msgs::Convert( - math::Inertiald( - math::MassMatrix3d(12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3)), - pose)); - - EXPECT_DOUBLE_EQ(12.0, msg.mass()); - EXPECT_DOUBLE_EQ(2.0, msg.ixx()); - EXPECT_DOUBLE_EQ(3.0, msg.iyy()); - EXPECT_DOUBLE_EQ(4.0, msg.izz()); - EXPECT_DOUBLE_EQ(0.1, msg.ixy()); - EXPECT_DOUBLE_EQ(0.2, msg.ixz()); - EXPECT_DOUBLE_EQ(0.3, msg.iyz()); - EXPECT_EQ(pose, msgs::Convert(msg.pose())); - EXPECT_TRUE(msg.fluid_added_mass().empty()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsInertialToMath) -{ - const auto pose = math::Pose3d(5, 6, 7, 0.4, 0.5, 0.6); - msgs::Inertial msg = msgs::Convert( - math::Inertiald( - math::MassMatrix3d(12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3)), - pose)); - auto inertial = msgs::Convert(msg); - - EXPECT_DOUBLE_EQ(12.0, inertial.MassMatrix().Mass()); - EXPECT_DOUBLE_EQ(2.0, inertial.MassMatrix().Ixx()); - EXPECT_DOUBLE_EQ(3.0, inertial.MassMatrix().Iyy()); - EXPECT_DOUBLE_EQ(4.0, inertial.MassMatrix().Izz()); - EXPECT_DOUBLE_EQ(0.1, inertial.MassMatrix().Ixy()); - EXPECT_DOUBLE_EQ(0.2, inertial.MassMatrix().Ixz()); - EXPECT_DOUBLE_EQ(0.3, inertial.MassMatrix().Iyz()); - EXPECT_EQ(pose, inertial.Pose()); - EXPECT_FALSE(inertial.FluidAddedMass().has_value()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMathInertialAddedMassToMsgs) -{ - const auto pose = math::Pose3d(5, 6, 7, 0.4, 0.5, 0.6); - math::Matrix6d addedMass{ - 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, - 0.2, 0.7, 0.8, 0.9, 1.0, 1.1, - 0.3, 0.8, 1.2, 1.3, 1.4, 1.5, - 0.4, 0.9, 1.3, 1.6, 1.7, 1.8, - 0.5, 1.0, 1.4, 1.7, 1.9, 2.0, - 0.6, 1.1, 1.5, 1.8, 2.0, 2.1}; - - auto msg = msgs::Convert( - math::Inertiald( - math::MassMatrix3d(12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3)), - pose, addedMass)); - - EXPECT_DOUBLE_EQ(12.0, msg.mass()); - EXPECT_DOUBLE_EQ(2.0, msg.ixx()); - EXPECT_DOUBLE_EQ(3.0, msg.iyy()); - EXPECT_DOUBLE_EQ(4.0, msg.izz()); - EXPECT_DOUBLE_EQ(0.1, msg.ixy()); - EXPECT_DOUBLE_EQ(0.2, msg.ixz()); - EXPECT_DOUBLE_EQ(0.3, msg.iyz()); - EXPECT_EQ(pose, msgs::Convert(msg.pose())); - ASSERT_EQ(21, msg.fluid_added_mass().size()); - EXPECT_DOUBLE_EQ(0.1, msg.fluid_added_mass(0)); - EXPECT_DOUBLE_EQ(0.2, msg.fluid_added_mass(1)); - EXPECT_DOUBLE_EQ(0.3, msg.fluid_added_mass(2)); - EXPECT_DOUBLE_EQ(0.4, msg.fluid_added_mass(3)); - EXPECT_DOUBLE_EQ(0.5, msg.fluid_added_mass(4)); - EXPECT_DOUBLE_EQ(0.6, msg.fluid_added_mass(5)); - EXPECT_DOUBLE_EQ(0.7, msg.fluid_added_mass(6)); - EXPECT_DOUBLE_EQ(0.8, msg.fluid_added_mass(7)); - EXPECT_DOUBLE_EQ(0.9, msg.fluid_added_mass(8)); - EXPECT_DOUBLE_EQ(1.0, msg.fluid_added_mass(9)); - EXPECT_DOUBLE_EQ(1.1, msg.fluid_added_mass(10)); - EXPECT_DOUBLE_EQ(1.2, msg.fluid_added_mass(11)); - EXPECT_DOUBLE_EQ(1.3, msg.fluid_added_mass(12)); - EXPECT_DOUBLE_EQ(1.4, msg.fluid_added_mass(13)); - EXPECT_DOUBLE_EQ(1.5, msg.fluid_added_mass(14)); - EXPECT_DOUBLE_EQ(1.6, msg.fluid_added_mass(15)); - EXPECT_DOUBLE_EQ(1.7, msg.fluid_added_mass(16)); - EXPECT_DOUBLE_EQ(1.8, msg.fluid_added_mass(17)); - EXPECT_DOUBLE_EQ(1.9, msg.fluid_added_mass(18)); - EXPECT_DOUBLE_EQ(2.0, msg.fluid_added_mass(19)); - EXPECT_DOUBLE_EQ(2.1, msg.fluid_added_mass(20)); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsInertialAddedMassToMath) -{ - const auto pose = math::Pose3d(5, 6, 7, 0.4, 0.5, 0.6); - math::Matrix6d addedMass{ - 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, - 0.2, 0.7, 0.8, 0.9, 1.0, 1.1, - 0.3, 0.8, 1.2, 1.3, 1.4, 1.5, - 0.4, 0.9, 1.3, 1.6, 1.7, 1.8, - 0.5, 1.0, 1.4, 1.7, 1.9, 2.0, - 0.6, 1.1, 1.5, 1.8, 2.0, 2.1}; - - auto msg = msgs::Convert( - math::Inertiald( - math::MassMatrix3d(12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3)), - pose, addedMass)); - auto inertial = msgs::Convert(msg); - - EXPECT_DOUBLE_EQ(12.0, inertial.MassMatrix().Mass()); - EXPECT_DOUBLE_EQ(2.0, inertial.MassMatrix().Ixx()); - EXPECT_DOUBLE_EQ(3.0, inertial.MassMatrix().Iyy()); - EXPECT_DOUBLE_EQ(4.0, inertial.MassMatrix().Izz()); - EXPECT_DOUBLE_EQ(0.1, inertial.MassMatrix().Ixy()); - EXPECT_DOUBLE_EQ(0.2, inertial.MassMatrix().Ixz()); - EXPECT_DOUBLE_EQ(0.3, inertial.MassMatrix().Iyz()); - EXPECT_EQ(pose, inertial.Pose()); - ASSERT_TRUE(inertial.FluidAddedMass().has_value()); - EXPECT_EQ(addedMass, inertial.FluidAddedMass().value()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMathMassMatrix3ToMsgs) -{ - msgs::Inertial msg = msgs::Convert( - math::MassMatrix3d(12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3))); - - EXPECT_DOUBLE_EQ(12.0, msg.mass()); - EXPECT_DOUBLE_EQ(2.0, msg.ixx()); - EXPECT_DOUBLE_EQ(3.0, msg.iyy()); - EXPECT_DOUBLE_EQ(4.0, msg.izz()); - EXPECT_DOUBLE_EQ(0.1, msg.ixy()); - EXPECT_DOUBLE_EQ(0.2, msg.ixz()); - EXPECT_DOUBLE_EQ(0.3, msg.iyz()); - EXPECT_EQ(math::Pose3d::Zero, msgs::Convert(msg.pose())); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, ConvertMathSphericalCoordinatesToMsgs) -{ - auto msg = msgs::Convert( - math::SphericalCoordinates( - math::SphericalCoordinates::SurfaceType::EARTH_WGS84, - GZ_DTOR(1.1), GZ_DTOR(2.2), 3.3, GZ_DTOR(0.4))); - - EXPECT_EQ(msgs::SphericalCoordinates::EARTH_WGS84, msg.surface_model()); - EXPECT_DOUBLE_EQ(1.1, msg.latitude_deg()); - EXPECT_DOUBLE_EQ(2.2, msg.longitude_deg()); - EXPECT_DOUBLE_EQ(3.3, msg.elevation()); - EXPECT_DOUBLE_EQ(0.4, msg.heading_deg()); - - auto math = msgs::Convert(msg); - - EXPECT_EQ(math::SphericalCoordinates::EARTH_WGS84, math.Surface()); - EXPECT_DOUBLE_EQ(1.1, math.LatitudeReference().Degree()); - EXPECT_DOUBLE_EQ(2.2, math.LongitudeReference().Degree()); - EXPECT_DOUBLE_EQ(3.3, math.ElevationReference()); - EXPECT_DOUBLE_EQ(0.4, math.HeadingOffset().Degree()); - - // For Moon's surface. - auto msgMoon = msgs::Convert( - math::SphericalCoordinates( - math::SphericalCoordinates::SurfaceType::MOON_SCS, - GZ_DTOR(1.1), GZ_DTOR(2.2), 3.3, GZ_DTOR(0.4))); - - EXPECT_EQ(msgs::SphericalCoordinates::MOON_SCS, - msgMoon.surface_model()); - EXPECT_DOUBLE_EQ(1.1, msgMoon.latitude_deg()); - EXPECT_DOUBLE_EQ(2.2, msgMoon.longitude_deg()); - EXPECT_DOUBLE_EQ(3.3, msgMoon.elevation()); - EXPECT_DOUBLE_EQ(0.4, msgMoon.heading_deg()); - - auto mathMoon = msgs::Convert(msgMoon); - - EXPECT_EQ(math::SphericalCoordinates::MOON_SCS, - mathMoon.Surface()); - EXPECT_DOUBLE_EQ(1.1, mathMoon.LatitudeReference().Degree()); - EXPECT_DOUBLE_EQ(2.2, mathMoon.LongitudeReference().Degree()); - EXPECT_DOUBLE_EQ(3.3, mathMoon.ElevationReference()); - EXPECT_DOUBLE_EQ(0.4, mathMoon.HeadingOffset().Degree()); - - // For custom surfaces. - auto sc = math::SphericalCoordinates( - math::SphericalCoordinates::CUSTOM_SURFACE, - 12000, 10000); - sc.SetLatitudeReference(GZ_DTOR(1.1)); - sc.SetLongitudeReference(GZ_DTOR(2.2)); - sc.SetElevationReference(3.3); - sc.SetHeadingOffset(GZ_DTOR(0.4)); - - auto msgCustom = msgs::Convert(sc); - - EXPECT_EQ(msgs::SphericalCoordinates::CUSTOM_SURFACE, - msgCustom.surface_model()); - EXPECT_DOUBLE_EQ(1.1, msgCustom.latitude_deg()); - EXPECT_DOUBLE_EQ(2.2, msgCustom.longitude_deg()); - EXPECT_DOUBLE_EQ(3.3, msgCustom.elevation()); - EXPECT_DOUBLE_EQ(0.4, msgCustom.heading_deg()); - EXPECT_DOUBLE_EQ(12000, msgCustom.surface_axis_equatorial()); - EXPECT_DOUBLE_EQ(10000, msgCustom.surface_axis_polar()); - - auto mathCustom = msgs::Convert(msgCustom); - - EXPECT_EQ(math::SphericalCoordinates::CUSTOM_SURFACE, - mathCustom.Surface()); - EXPECT_DOUBLE_EQ(1.1, mathCustom.LatitudeReference().Degree()); - EXPECT_DOUBLE_EQ(2.2, mathCustom.LongitudeReference().Degree()); - EXPECT_DOUBLE_EQ(3.3, mathCustom.ElevationReference()); - EXPECT_DOUBLE_EQ(0.4, mathCustom.HeadingOffset().Degree()); - EXPECT_DOUBLE_EQ(12000, mathCustom.SurfaceAxisEquatorial()); - EXPECT_DOUBLE_EQ(10000, mathCustom.SurfaceAxisPolar()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertStringMsg) -{ - msgs::StringMsg msg = msgs::Convert(std::string("a string msg")); - EXPECT_EQ("a string msg", msg.data()); - - std::string s = msgs::Convert(msg); - EXPECT_EQ(s, "a string msg"); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertBoolean) -{ - msgs::Boolean msg = msgs::Convert(static_cast(true)); - EXPECT_EQ(true, msg.data()); - - bool s = msgs::Convert(msg); - EXPECT_EQ(s, true); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertInt32) -{ - msgs::Int32 msg = msgs::Convert(static_cast(-543)); - EXPECT_EQ(-543, msg.data()); - - int s = msgs::Convert(msg); - EXPECT_EQ(s, -543); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertUInt32) -{ - msgs::UInt32 msg = msgs::Convert(123456u); - EXPECT_EQ(123456u, msg.data()); - - uint32_t s = msgs::Convert(msg); - EXPECT_EQ(s, 123456u); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertInt64) -{ - msgs::Int64 msg = msgs::Convert(std::numeric_limits::min()); - EXPECT_EQ(std::numeric_limits::min(), msg.data()); - - int64_t s = msgs::Convert(msg); - EXPECT_EQ(s, std::numeric_limits::min()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertUInt64) -{ - msgs::UInt64 msg = msgs::Convert(std::numeric_limits::max()); - EXPECT_EQ(std::numeric_limits::max(), msg.data()); - - uint64_t s = msgs::Convert(msg); - EXPECT_EQ(s, std::numeric_limits::max()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertDouble) -{ - msgs::Double msg = msgs::Convert(static_cast(-33.888)); - EXPECT_DOUBLE_EQ(-33.888, msg.data()); - - double s = msgs::Convert(msg); - EXPECT_DOUBLE_EQ(s, -33.888); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertFloat) -{ - msgs::Float msg = msgs::Convert(0.999f); - EXPECT_DOUBLE_EQ(0.999f, msg.data()); - - float s = msgs::Convert(msg); - EXPECT_DOUBLE_EQ(s, 0.999f); -} - - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertFuelMetadata) -{ - msgs::FuelMetadata metaMsg; - std::string modelConfigInput, worldConfigInput; - - // test ConvertFuelMetadata(string, msgs::FuelMetadata) - { - EXPECT_FALSE(msgs::ConvertFuelMetadata(modelConfigInput, metaMsg)); - - metaMsg.Clear(); - modelConfigInput = ""; - EXPECT_FALSE(msgs::ConvertFuelMetadata(modelConfigInput, metaMsg)); - - metaMsg.Clear(); - modelConfigInput = "test"; - EXPECT_FALSE(msgs::ConvertFuelMetadata(modelConfigInput, metaMsg)); - - // Test - metaMsg.Clear(); - modelConfigInput = R"( - - test_model - - )"; - EXPECT_FALSE(msgs::ConvertFuelMetadata(modelConfigInput, metaMsg)); - - metaMsg.Clear(); - modelConfigInput = R"( - - model.sdf - test_model - 3 - A model for testing - - Foo Bar - foo@bar.org - - - - model://some_model - - - -)"; - - EXPECT_TRUE(msgs::ConvertFuelMetadata(modelConfigInput, metaMsg)); - EXPECT_EQ("test_model", metaMsg.name()); - EXPECT_EQ(3, metaMsg.version()); - EXPECT_EQ("A model for testing", metaMsg.description()); - EXPECT_EQ("model.sdf", metaMsg.model().file()); - EXPECT_EQ("sdf", metaMsg.model().file_format().name()); - EXPECT_EQ(1, metaMsg.model().file_format().version().major()); - EXPECT_EQ(7, metaMsg.model().file_format().version().minor()); - EXPECT_EQ(1, metaMsg.authors().size()); - EXPECT_EQ("Foo Bar", metaMsg.authors(0).name()); - EXPECT_EQ("foo@bar.org", metaMsg.authors(0).email()); - EXPECT_EQ(1, metaMsg.dependencies().size()); - EXPECT_EQ("model://some_model", metaMsg.dependencies(0).uri()); - - // Test - metaMsg.Clear(); - worldConfigInput = R"( - - world.sdf - test_world - 2 - A world for testing - -)"; - EXPECT_TRUE(msgs::ConvertFuelMetadata(worldConfigInput, metaMsg)); - EXPECT_EQ("test_world", metaMsg.name()); - EXPECT_EQ(2, metaMsg.version()); - EXPECT_EQ("A world for testing", metaMsg.description()); - EXPECT_EQ("world.sdf", metaMsg.world().file()); - EXPECT_EQ("sdf", metaMsg.world().file_format().name()); - EXPECT_EQ(1, metaMsg.world().file_format().version().major()); - EXPECT_EQ(7, metaMsg.world().file_format().version().minor()); - EXPECT_EQ(0, metaMsg.authors().size()); - EXPECT_EQ(0, metaMsg.dependencies().size()); - } - - // test ConvertFuelMetadata(msgs::FuelMetadata, string) - { - std::string modelConfig; - - // Test - metaMsg.Clear(); - metaMsg.mutable_world()->set_file("world.sdf"); - EXPECT_FALSE(msgs::ConvertFuelMetadata(metaMsg, modelConfig)); - - metaMsg.set_name("test_world"); - metaMsg.set_description("A world for testing"); - metaMsg.set_version(2); - metaMsg.mutable_world()->mutable_file_format()->set_name("sdf"); - metaMsg.mutable_world()->mutable_file_format() - ->mutable_version()->set_major(1); - metaMsg.mutable_world()->mutable_file_format() - ->mutable_version()->set_minor(7); - EXPECT_TRUE(msgs::ConvertFuelMetadata(metaMsg, modelConfig)); - - EXPECT_EQ(worldConfigInput, modelConfig); - - // Test - metaMsg.Clear(); - metaMsg.mutable_model()->set_file("model.sdf"); - EXPECT_FALSE(msgs::ConvertFuelMetadata(metaMsg, modelConfig)); - - metaMsg.set_name("test_model"); - metaMsg.set_description("A model for testing"); - metaMsg.set_version(3); - metaMsg.mutable_model()->mutable_file_format()->set_name("sdf"); - metaMsg.mutable_model()->mutable_file_format() - ->mutable_version()->set_major(1); - metaMsg.mutable_model()->mutable_file_format() - ->mutable_version()->set_minor(7); - EXPECT_TRUE(msgs::ConvertFuelMetadata(metaMsg, modelConfig)); - - metaMsg.add_authors()->set_name("Foo Bar"); - metaMsg.mutable_authors(0)->set_email("foo@bar.org"); - metaMsg.add_dependencies()->set_uri("model://some_model"); - EXPECT_TRUE(msgs::ConvertFuelMetadata(metaMsg, modelConfig)); - EXPECT_EQ(modelConfigInput, modelConfig); - } -} - -///////////////////////////////////////////////// -TEST(UtilityTest, ConvertTimePoint) -{ - std::chrono::steady_clock::duration timePoint = - std::chrono::steady_clock::duration::zero(); - msgs::Time msg = msgs::Convert(timePoint); - EXPECT_EQ(0, msg.sec()); - EXPECT_EQ(0, msg.nsec()); - - std::chrono::steady_clock::duration s = msgs::Convert(msg); - EXPECT_EQ(s, std::chrono::steady_clock::duration::zero()); - - timePoint = std::chrono::seconds(200) + std::chrono::nanoseconds(999); - msg = msgs::Convert(timePoint); - EXPECT_EQ(200, msg.sec()); - EXPECT_EQ(999, msg.nsec()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, SetVector3) -{ - msgs::Vector3d msg; - msgs::Set(&msg, math::Vector3d(1, 2, 3)); - EXPECT_DOUBLE_EQ(1, msg.x()); - EXPECT_DOUBLE_EQ(2, msg.y()); - EXPECT_DOUBLE_EQ(3, msg.z()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, SetVector2d) -{ - msgs::Vector2d msg; - msgs::Set(&msg, math::Vector2d(1, 2)); - EXPECT_DOUBLE_EQ(1, msg.x()); - EXPECT_DOUBLE_EQ(2, msg.y()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, SetQuaternion) -{ - msgs::Quaternion msg; - msgs::Set(&msg, math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI)); - EXPECT_TRUE(math::equal(msg.x(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(msg.y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(msg.z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(msg.w(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, SetPose) -{ - msgs::Pose msg; - msgs::Set(&msg, math::Pose3d(math::Vector3d(1, 2, 3), - math::Quaterniond(GZ_PI * 0.25, GZ_PI * 0.5, GZ_PI))); - - EXPECT_DOUBLE_EQ(1, msg.position().x()); - EXPECT_DOUBLE_EQ(2, msg.position().y()); - EXPECT_DOUBLE_EQ(3, msg.position().z()); - - EXPECT_TRUE(math::equal(msg.orientation().x(), -0.65328148243818818)); - EXPECT_TRUE(math::equal(msg.orientation().y(), 0.27059805007309856)); - EXPECT_TRUE(math::equal(msg.orientation().z(), 0.65328148243818829)); - EXPECT_TRUE(math::equal(msg.orientation().w(), 0.27059805007309851)); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetColor) -{ - msgs::Color msg; - msgs::Set(&msg, math::Color(.1f, .2f, .3f, 1.0f)); - EXPECT_FLOAT_EQ(0.1f, msg.r()); - EXPECT_FLOAT_EQ(0.2f, msg.g()); - EXPECT_FLOAT_EQ(0.3f, msg.b()); - EXPECT_FLOAT_EQ(1.0f, msg.a()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, SetPlane) -{ - msgs::PlaneGeom msg; - msgs::Set(&msg, math::Planed( - math::Vector3d(0, 0, 1), - math::Vector2d(123, 456), 1.0)); - - EXPECT_DOUBLE_EQ(0, msg.normal().x()); - EXPECT_DOUBLE_EQ(0, msg.normal().y()); - EXPECT_DOUBLE_EQ(1, msg.normal().z()); - - EXPECT_DOUBLE_EQ(123, msg.size().x()); - EXPECT_DOUBLE_EQ(456, msg.size().y()); - - EXPECT_TRUE(math::equal(1.0, msg.d())); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetInertial) -{ - const auto pose = math::Pose3d(5, 6, 7, 0.4, 0.5, 0.6); - msgs::Inertial msg; - msgs::Set(&msg, math::Inertiald( - math::MassMatrix3d( - 12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3)), - pose)); - - EXPECT_DOUBLE_EQ(12.0, msg.mass()); - EXPECT_DOUBLE_EQ(2.0, msg.ixx()); - EXPECT_DOUBLE_EQ(3.0, msg.iyy()); - EXPECT_DOUBLE_EQ(4.0, msg.izz()); - EXPECT_DOUBLE_EQ(0.1, msg.ixy()); - EXPECT_DOUBLE_EQ(0.2, msg.ixz()); - EXPECT_DOUBLE_EQ(0.3, msg.iyz()); - EXPECT_EQ(pose, msgs::Convert(msg.pose())); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetMassMatrix3) -{ - msgs::Inertial msg; - msgs::Set(&msg, math::MassMatrix3d( - 12.0, - math::Vector3d(2, 3, 4), - math::Vector3d(0.1, 0.2, 0.3))); - - EXPECT_DOUBLE_EQ(12.0, msg.mass()); - EXPECT_DOUBLE_EQ(2.0, msg.ixx()); - EXPECT_DOUBLE_EQ(3.0, msg.iyy()); - EXPECT_DOUBLE_EQ(4.0, msg.izz()); - EXPECT_DOUBLE_EQ(0.1, msg.ixy()); - EXPECT_DOUBLE_EQ(0.2, msg.ixz()); - EXPECT_DOUBLE_EQ(0.3, msg.iyz()); - EXPECT_EQ(math::Pose3d::Zero, msgs::Convert(msg.pose())); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetSphericalCoordinates) -{ - msgs::SphericalCoordinates msg; - msgs::Set(&msg, math::SphericalCoordinates( - math::SphericalCoordinates::SurfaceType::EARTH_WGS84, - GZ_DTOR(1.1), GZ_DTOR(2.2), 3.3, GZ_DTOR(0.4))); - - EXPECT_EQ(msgs::SphericalCoordinates::EARTH_WGS84, msg.surface_model()); - EXPECT_DOUBLE_EQ(1.1, msg.latitude_deg()); - EXPECT_DOUBLE_EQ(2.2, msg.longitude_deg()); - EXPECT_DOUBLE_EQ(3.3, msg.elevation()); - EXPECT_DOUBLE_EQ(0.4, msg.heading_deg()); - - // For Moon's surface. - msgs::SphericalCoordinates msgMoon; - msgs::Set(&msgMoon, math::SphericalCoordinates( - math::SphericalCoordinates::SurfaceType::MOON_SCS, - GZ_DTOR(1.2), GZ_DTOR(2.3), 3.4, GZ_DTOR(0.5))); - - EXPECT_EQ(msgs::SphericalCoordinates::MOON_SCS, - msgMoon.surface_model()); - EXPECT_DOUBLE_EQ(1.2, msgMoon.latitude_deg()); - EXPECT_DOUBLE_EQ(2.3, msgMoon.longitude_deg()); - EXPECT_DOUBLE_EQ(3.4, msgMoon.elevation()); - EXPECT_DOUBLE_EQ(0.5, msgMoon.heading_deg()); - - // For a custom surface. - msgs::SphericalCoordinates msgCustom; - auto sc = math::SphericalCoordinates( - math::SphericalCoordinates::CUSTOM_SURFACE, - 12000, 10000); - sc.SetLatitudeReference(GZ_DTOR(1.9)); - sc.SetLongitudeReference(GZ_DTOR(2.8)); - sc.SetElevationReference(3.7); - sc.SetHeadingOffset(GZ_DTOR(0.6)); - - msgs::Set(&msgCustom, sc); - - EXPECT_EQ(msgs::SphericalCoordinates::CUSTOM_SURFACE, - msgCustom.surface_model()); - EXPECT_DOUBLE_EQ(1.9, msgCustom.latitude_deg()); - EXPECT_DOUBLE_EQ(2.8, msgCustom.longitude_deg()); - EXPECT_DOUBLE_EQ(3.7, msgCustom.elevation()); - EXPECT_DOUBLE_EQ(0.6, msgCustom.heading_deg()); - EXPECT_DOUBLE_EQ(12000, msgCustom.surface_axis_equatorial()); - EXPECT_DOUBLE_EQ(10000, msgCustom.surface_axis_polar()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetStringMsg) -{ - msgs::StringMsg msg; - msgs::Set(&msg, "a string msg"); - - EXPECT_EQ("a string msg", msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetBoolean) -{ - msgs::Boolean msg; - msgs::Set(&msg, false); - - EXPECT_FALSE(msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetInt32) -{ - msgs::Int32 msg; - msgs::Set(&msg, 9976); - - EXPECT_EQ(9976, msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetUInt32) -{ - msgs::UInt32 msg; - msgs::Set(&msg, 0u); - - EXPECT_EQ(0u, msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetInt64) -{ - msgs::Int64 msg; - msgs::Set(&msg, std::numeric_limits::max()); - - EXPECT_EQ(std::numeric_limits::max(), msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetUInt64) -{ - msgs::UInt64 msg; - msgs::Set(&msg, std::numeric_limits::min()); - - EXPECT_EQ(std::numeric_limits::min(), msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetDouble) -{ - msgs::Double msg; - msgs::Set(&msg, 0.123); - - EXPECT_DOUBLE_EQ(0.123, msg.data()); -} - -///////////////////////////////////////////////// -TEST(MsgsTest, SetFloat) -{ - msgs::Float msg; - msgs::Set(&msg, -367.0f); - - EXPECT_DOUBLE_EQ(-367.0f, msg.data()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, Initialization) -{ - { - msgs::Vector3d msg; - EXPECT_DOUBLE_EQ(0, msg.x()); - EXPECT_DOUBLE_EQ(0, msg.y()); - EXPECT_DOUBLE_EQ(0, msg.z()); - } - - { - msgs::Wrench msg; - EXPECT_DOUBLE_EQ(0, msg.force().x()); - EXPECT_DOUBLE_EQ(0, msg.force().y()); - EXPECT_DOUBLE_EQ(0, msg.force().z()); - EXPECT_DOUBLE_EQ(0, msg.torque().x()); - EXPECT_DOUBLE_EQ(0, msg.torque().y()); - EXPECT_DOUBLE_EQ(0, msg.torque().z()); - } -} - -////////////////////////////////////////////////// -void CompareMsgsJointTypeToString(const msgs::Joint::Type _type) -{ - EXPECT_EQ(_type, msgs::ConvertJointType(msgs::ConvertJointType(_type))); -} - -////////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsJointTypeToString) -{ - CompareMsgsJointTypeToString(msgs::Joint::REVOLUTE); - CompareMsgsJointTypeToString(msgs::Joint::REVOLUTE2); - CompareMsgsJointTypeToString(msgs::Joint::PRISMATIC); - CompareMsgsJointTypeToString(msgs::Joint::UNIVERSAL); - CompareMsgsJointTypeToString(msgs::Joint::BALL); - CompareMsgsJointTypeToString(msgs::Joint::SCREW); - CompareMsgsJointTypeToString(msgs::Joint::GEARBOX); - CompareMsgsJointTypeToString(msgs::Joint::FIXED); - CompareMsgsJointTypeToString(msgs::Joint::CONTINUOUS); - - EXPECT_EQ(msgs::ConvertJointType("bad type"), msgs::Joint::REVOLUTE); - EXPECT_EQ(msgs::ConvertJointType(msgs::Joint::Type(100)), "unknown"); -} - -////////////////////////////////////////////////// -void CompareMsgsGeometryTypeToString(const msgs::Geometry::Type _type) -{ - EXPECT_EQ(_type, msgs::ConvertGeometryType(msgs::ConvertGeometryType(_type))); -} - -////////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsGeometryTypeToString) -{ - CompareMsgsGeometryTypeToString(msgs::Geometry::BOX); - CompareMsgsGeometryTypeToString(msgs::Geometry::SPHERE); - CompareMsgsGeometryTypeToString(msgs::Geometry::CAPSULE); - CompareMsgsGeometryTypeToString(msgs::Geometry::CYLINDER); - CompareMsgsGeometryTypeToString(msgs::Geometry::ELLIPSOID); - CompareMsgsGeometryTypeToString(msgs::Geometry::PLANE); - CompareMsgsGeometryTypeToString(msgs::Geometry::IMAGE); - CompareMsgsGeometryTypeToString(msgs::Geometry::HEIGHTMAP); - CompareMsgsGeometryTypeToString(msgs::Geometry::MESH); - CompareMsgsGeometryTypeToString(msgs::Geometry::POLYLINE); - - EXPECT_EQ(msgs::ConvertGeometryType("bad type"), msgs::Geometry::BOX); - EXPECT_EQ(msgs::ConvertGeometryType(msgs::Geometry::Type(100)), "unknown"); -} - -////////////////////////////////////////////////// -void CompareMsgsShaderTypeToString(const msgs::Material::ShaderType _type) -{ - EXPECT_EQ(_type, msgs::ConvertShaderType(msgs::ConvertShaderType(_type))); -} - -////////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsShaderTypeToString) -{ - CompareMsgsShaderTypeToString(msgs::Material::NORMAL_MAP_OBJECT_SPACE); - CompareMsgsShaderTypeToString(msgs::Material::NORMAL_MAP_TANGENT_SPACE); - CompareMsgsShaderTypeToString(msgs::Material::PIXEL); - CompareMsgsShaderTypeToString(msgs::Material::VERTEX); - - EXPECT_EQ(msgs::ConvertShaderType("bad type"), msgs::Material::VERTEX); - EXPECT_EQ(msgs::ConvertShaderType(msgs::Material::ShaderType(100)), - "unknown"); -} - -////////////////////////////////////////////////// -void CompareMsgsPixelFormatTypeToString(const msgs::PixelFormatType _type) -{ - EXPECT_EQ(_type, - msgs::ConvertPixelFormatType(msgs::ConvertPixelFormatType(_type))) - << msgs::ConvertPixelFormatType(_type); -} - -////////////////////////////////////////////////// -TEST(MsgsTest, ConvertMsgsPixelFormatTypeToString) -{ - CompareMsgsPixelFormatTypeToString( - msgs::PixelFormatType::UNKNOWN_PIXEL_FORMAT); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::L_INT8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::L_INT16); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGB_INT8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGBA_INT8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BGRA_INT8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGB_INT16); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGB_INT32); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BGR_INT8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BGR_INT16); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BGR_INT32); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::R_FLOAT16); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGB_FLOAT16); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::R_FLOAT32); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::RGB_FLOAT32); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BAYER_RGGB8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BAYER_BGGR8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BAYER_GBRG8); - CompareMsgsPixelFormatTypeToString(msgs::PixelFormatType::BAYER_GRBG8); - - EXPECT_EQ(msgs::ConvertPixelFormatType("bad type"), - msgs::PixelFormatType::UNKNOWN_PIXEL_FORMAT); - EXPECT_EQ(msgs::ConvertPixelFormatType(msgs::PixelFormatType(100)), - "UNKNOWN_PIXEL_FORMAT"); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, CovertMathAxisAlignedBox) -{ - // Convert from math to msg - msgs::AxisAlignedBox msg = msgs::Convert( - math::AxisAlignedBox(-1, -2, -3, 12, 15, 20)); - EXPECT_DOUBLE_EQ(-1, msg.min_corner().x()); - EXPECT_DOUBLE_EQ(-2, msg.min_corner().y()); - EXPECT_DOUBLE_EQ(-3, msg.min_corner().z()); - - EXPECT_DOUBLE_EQ(12, msg.max_corner().x()); - EXPECT_DOUBLE_EQ(15, msg.max_corner().y()); - EXPECT_DOUBLE_EQ(20, msg.max_corner().z()); - - // Convert from msg to math - math::AxisAlignedBox aab = msgs::Convert(msg); - EXPECT_DOUBLE_EQ(-1, aab.Min().X()); - EXPECT_DOUBLE_EQ(-2, aab.Min().Y()); - EXPECT_DOUBLE_EQ(-3, aab.Min().Z()); - - EXPECT_DOUBLE_EQ(12, aab.Max().X()); - EXPECT_DOUBLE_EQ(15, aab.Max().Y()); - EXPECT_DOUBLE_EQ(20, aab.Max().Z()); - - // Set msg from math - aab = msgs::Convert(msg); - msgs::AxisAlignedBox msg2; - msgs::Set(&msg2, aab); - EXPECT_DOUBLE_EQ(-1, msg2.min_corner().x()); - EXPECT_DOUBLE_EQ(-2, msg2.min_corner().y()); - EXPECT_DOUBLE_EQ(-3, msg2.min_corner().z()); - - EXPECT_DOUBLE_EQ(12, msg2.max_corner().x()); - EXPECT_DOUBLE_EQ(15, msg2.max_corner().y()); - EXPECT_DOUBLE_EQ(20, msg2.max_corner().z()); - - // Try different values with Set - aab.Min() = math::Vector3d(-23.4, 56.2, -123.5); - aab.Max() = math::Vector3d(34.1, 92.1, -723.2); - msgs::Set(&msg2, aab); - EXPECT_DOUBLE_EQ(-23.4, msg2.min_corner().x()); - EXPECT_DOUBLE_EQ(56.2, msg2.min_corner().y()); - EXPECT_DOUBLE_EQ(-123.5, msg2.min_corner().z()); - - EXPECT_DOUBLE_EQ(34.1, msg2.max_corner().x()); - EXPECT_DOUBLE_EQ(92.1, msg2.max_corner().y()); - EXPECT_DOUBLE_EQ(-723.2, msg2.max_corner().z()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, InitPointCloudPacked) -{ - msgs::PointCloudPacked pc; - - msgs::InitPointCloudPacked(pc, "my_frame", true, - {{"xyz", msgs::PointCloudPacked::Field::FLOAT32}, - {"rgb", msgs::PointCloudPacked::Field::FLOAT32}}); - - EXPECT_EQ(4, pc.field_size()); - if (4u == sizeof(size_t)) - { - // 32-bit architecture - EXPECT_EQ(16u, pc.point_step()); - } - else - { - // otherwise assume 64-bit architecture - EXPECT_EQ(24u, pc.point_step()); - } - - EXPECT_EQ("x", pc.field(0).name()); - EXPECT_EQ(0u, pc.field(0).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(0).datatype()); - EXPECT_EQ(1u, pc.field(0).count()); - - EXPECT_EQ("y", pc.field(1).name()); - EXPECT_EQ(4u, pc.field(1).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(1).datatype()); - EXPECT_EQ(1u, pc.field(1).count()); - - EXPECT_EQ("z", pc.field(2).name()); - EXPECT_EQ(8u, pc.field(2).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(2).datatype()); - EXPECT_EQ(1u, pc.field(2).count()); - - EXPECT_EQ("rgb", pc.field(3).name()); - if (4u == sizeof(size_t)) - { - // 32-bit architecture - EXPECT_EQ(12u, pc.field(3).offset()); - } - else - { - // otherwise assume 64-bit architecture - EXPECT_EQ(16u, pc.field(3).offset()); - } - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(3).datatype()); - EXPECT_EQ(1u, pc.field(3).count()); - - // Don't align to word boundaries - msgs::InitPointCloudPacked(pc, "my_frame", false, - {{"xyz", msgs::PointCloudPacked::Field::FLOAT32}, - {"rgb", msgs::PointCloudPacked::Field::FLOAT32}}); - EXPECT_EQ(4, pc.field_size()); - EXPECT_EQ(16u, pc.point_step()); - - EXPECT_EQ("x", pc.field(0).name()); - EXPECT_EQ(0u, pc.field(0).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(0).datatype()); - EXPECT_EQ(1u, pc.field(0).count()); - - EXPECT_EQ("y", pc.field(1).name()); - EXPECT_EQ(4u, pc.field(1).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(1).datatype()); - EXPECT_EQ(1u, pc.field(1).count()); - - EXPECT_EQ("z", pc.field(2).name()); - EXPECT_EQ(8u, pc.field(2).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(2).datatype()); - EXPECT_EQ(1u, pc.field(2).count()); - - EXPECT_EQ("rgb", pc.field(3).name()); - EXPECT_EQ(12u, pc.field(3).offset()); - EXPECT_EQ(msgs::PointCloudPacked::Field::FLOAT32, pc.field(3).datatype()); - EXPECT_EQ(1u, pc.field(3).count()); - EXPECT_EQ("my_frame", pc.header().data(0).value(0)); - EXPECT_EQ("frame_id", pc.header().data(0).key()); - - // Test data types - msgs::InitPointCloudPacked(pc, "my_new_frame", false, - {{"x", msgs::PointCloudPacked::Field::INT8}, - {"y", msgs::PointCloudPacked::Field::UINT8}, - {"z", msgs::PointCloudPacked::Field::INT16}, - {"r", msgs::PointCloudPacked::Field::UINT16}, - {"s", msgs::PointCloudPacked::Field::INT32}, - {"t", msgs::PointCloudPacked::Field::UINT32}, - {"u", msgs::PointCloudPacked::Field::FLOAT64}}); - - EXPECT_EQ("frame_id", pc.header().data(0).key()); - EXPECT_EQ("my_new_frame", pc.header().data(0).value(0)); - - EXPECT_EQ(0u, pc.field(0).offset()); - EXPECT_EQ(1u, pc.field(1).offset()); - EXPECT_EQ(2u, pc.field(2).offset()); - EXPECT_EQ(4u, pc.field(3).offset()); - EXPECT_EQ(6u, pc.field(4).offset()); - EXPECT_EQ(10u, pc.field(5).offset()); - EXPECT_EQ(14u, pc.field(6).offset()); - EXPECT_EQ(22u, pc.point_step()); -} - -///////////////////////////////////////////////// -TEST(UtilityTest, DiscoveryTypeString) -{ - EXPECT_EQ("UNINITIALIZED", - msgs::ToString(msgs::Discovery::UNINITIALIZED)); - EXPECT_EQ("ADVERTISE", - msgs::ToString(msgs::Discovery::ADVERTISE)); - EXPECT_EQ("SUBSCRIBE", - msgs::ToString(msgs::Discovery::SUBSCRIBE)); - EXPECT_EQ("UNADVERTISE", - msgs::ToString(msgs::Discovery::UNADVERTISE)); - EXPECT_EQ("HEARTBEAT", - msgs::ToString(msgs::Discovery::HEARTBEAT)); - EXPECT_EQ("BYE", - msgs::ToString(msgs::Discovery::BYE)); - EXPECT_EQ("NEW_CONNECTION", - msgs::ToString(msgs::Discovery::NEW_CONNECTION)); - EXPECT_EQ("END_CONNECTION", - msgs::ToString(msgs::Discovery::END_CONNECTION)); - EXPECT_EQ("SUBSCRIBERS_REQ", - msgs::ToString(msgs::Discovery::SUBSCRIBERS_REQ)); - EXPECT_EQ("SUBSCRIBERS_REP", - msgs::ToString(msgs::Discovery::SUBSCRIBERS_REP)); - - // If any of the following fail, then make sure you have added then new - // enum values to std::string ToString(const msgs::Discovery::Type &_t). - // Then update the following tests to match the new enum values. - EXPECT_EQ(msgs::Discovery::UNINITIALIZED, - msgs::Discovery::Type_MIN); - EXPECT_EQ(msgs::Discovery::SUBSCRIBERS_REP, - msgs::Discovery::Type_MAX); - EXPECT_EQ(10, msgs::Discovery::Type_ARRAYSIZE); -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2c6bc40f..1f318446 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,7 +4,7 @@ include_directories ( ${PROJECT_BINARY_DIR}/include ) -add_subdirectory(gtest_vendor) -add_subdirectory(integration) -add_subdirectory(performance) -add_subdirectory(regression) +#add_subdirectory(gtest_vendor) +#add_subdirectory(integration) +#add_subdirectory(performance) +#add_subdirectory(regression) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index da1c4601..186e0f5d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -6,6 +6,14 @@ set (test_sources gz_TEST.cc ) +install(PROGRAMS gz_msgs_generate.py + RENAME ${PROJECT_NAME}_generate.py + DESTINATION ${GZ_BIN_INSTALL_DIR}) + +install(PROGRAMS gz_msgs_factory.py + RENAME ${PROJECT_NAME}_factory.py + DESTINATION ${GZ_BIN_INSTALL_DIR}) + # Skip command line tests for Windows, see # https://github.com/gazebosim/gz-msgs/issues/28 if (MSVC) diff --git a/tools/gz_msgs_factory.py b/tools/gz_msgs_factory.py new file mode 100755 index 00000000..bfb1e05d --- /dev/null +++ b/tools/gz_msgs_factory.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 Open Source Robotics Foundation +# +# 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 argparse +import os +import subprocess +import sys + +cc_header = """// Generated by gz-msgs. DO NOT EDIT! + +#include +#include "msgs.hh" + +void RegisterAllMessages(gz::msgs::MessageFactory & factory) +""" + + +def main(argv=sys.argv[1:]): + parser = argparse.ArgumentParser( + description='Generate protobuf factory file', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument( + '--output-cpp-path', + help='The basepath of the generated C++ files') + parser.add_argument( + '--proto-path', + required=True, + help='The location of the protos') + parser.add_argument( + '--protos', + required=True, + help='The list of protos to include' + ) + args = parser.parse_args(argv) + + print(args.output_cpp_path) + print(args.proto_path) + print(args.protos) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gz_msgs_generate.py b/tools/gz_msgs_generate.py index 10ee41ea..f9c84483 100755 --- a/tools/gz_msgs_generate.py +++ b/tools/gz_msgs_generate.py @@ -32,16 +32,11 @@ def main(argv=sys.argv[1:]): help='The path to the gz specific protobuf generator') parser.add_argument( '--generate-cpp', - help='Flag to indicate if C++ bindings should be generated') - parser.add_argument( - '--generate-ruby', - help='Flag to indicate if Ruby bindings should be generated') + help='Flag to indicate if C++ bindings should be generated', + action='store_true') parser.add_argument( '--output-cpp-path', help='The basepath of the generated C++ files') - parser.add_argument( - '--output-ruby-path', - help='The basepath of the generated C++ files') parser.add_argument( '--proto-path', required=True, @@ -52,16 +47,14 @@ def main(argv=sys.argv[1:]): help='The location of the template files') args = parser.parse_args(argv) - # First generate the base cpp and ruby files + # First generate the base cpp files cmd = [args.protoc_exec] cmd += [f'--proto_path={args.proto_path}'] if args.generate_cpp: cmd += [f'--plugin=protoc-gen-ignmsgs={args.gz_generator_bin}'] - cmd += [f'--cpp_out=dllexport_decl=GZ_MSGS_VISIBLE:{args.output_cpp_path}'] + cmd += [f'--cpp_out={args.output_cpp_path}'] cmd += [f'--ignmsgs_out={args.output_cpp_path}'] - if args.generate_ruby: - cmd += [f'--ruby_out=dllexport_decl=GZ_MSGS_VISIBLE:{args.output_ruby_path}'] cmd += [args.input_path] try: From ce3c64e290841d758ce44079e2890a131fc3749f Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Thu, 11 May 2023 19:54:13 +0000 Subject: [PATCH 5/6] New message generation pipeline for gz-msgs Signed-off-by: Michael Carroll --- cmake/gz_msgs_factory.cmake | 77 ++++++++++++ cmake/gz_msgs_protoc.cmake | 20 ++- compiled/include/gz/msgs/Factory.hh | 123 ------------------ core/generator/Generator.cc | 9 ++ core/include/gz/msgs/CMakeLists.txt | 5 +- core/include/gz/msgs/Convert.hh | 4 + core/include/gz/msgs/Factory.hh | 104 ++++++++++++++++ core/include/gz/msgs/MessageFactory.hh | 8 +- {compiled => core}/src/Factory.cc | 35 +++--- core/src/MessageFactory.cc | 40 +++--- gz-msgs-extras.cmake.in | 135 +++++++++++++++----- tools/CMakeLists.txt | 4 +- tools/gz_msgs_factory.py | 54 -------- tools/gz_msgs_generate.py | 8 ++ tools/gz_msgs_generate_factory.py | 165 +++++++++++++++++++++++++ 15 files changed, 532 insertions(+), 259 deletions(-) create mode 100644 cmake/gz_msgs_factory.cmake delete mode 100644 compiled/include/gz/msgs/Factory.hh create mode 100644 core/include/gz/msgs/Factory.hh rename {compiled => core}/src/Factory.cc (63%) delete mode 100755 tools/gz_msgs_factory.py create mode 100755 tools/gz_msgs_generate_factory.py diff --git a/cmake/gz_msgs_factory.cmake b/cmake/gz_msgs_factory.cmake new file mode 100644 index 00000000..0b3a3e9a --- /dev/null +++ b/cmake/gz_msgs_factory.cmake @@ -0,0 +1,77 @@ +################################################## +# A function that calls protoc on a protobuf file +# Options: +# One value arguments: +# FACTORY_GEN_SCRIPT - Location of the factory generator script +# PROTO_PACKAGE - Protobuf package the file belongs to (e.g. ".gz.msgs") +# PROTOC_EXEC - Path to protoc +# INPUT_PROTO - Path to the input .proto file +# OUTPUT_CPP_DIR - Path where C++ files are saved +# OUTPUT_INCLUDES - A CMake variable name containing a list that the C++ header path should be appended to +# OUTPUT_CPP_HH_VAR - A CMake variable name containing a list that the C++ header path should be appended to +# OUTPUT_CPP_CC_VAR - A Cmake variable name containing a list that the C++ source path should be appended to +# Multi value arguments +# INPUT_PROTOS - Passed to protoc --proto_path +# PROTO_PATH - Passed to protoc --proto_path +function(gz_msgs_factory) + set(options "") + set(oneValueArgs + FACTORY_GEN_SCRIPT + PROTO_PACKAGE + OUTPUT_CPP_DIR + OUTPUT_CPP_HH_VAR + OUTPUT_CPP_CC_VAR) + set(multiValueArgs INPUT_PROTOS PROTO_PATH) + + cmake_parse_arguments(gz_msgs_factory "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(proto_package_dir ".") + if(gz_msgs_factory_PROTO_PACKAGE) + string(REPLACE "." "/" proto_package_dir ${gz_msgs_factory_PROTO_PACKAGE}) + endif() + + set(output_header "${gz_msgs_factory_OUTPUT_CPP_DIR}/${proto_package_dir}/MessageTypes.hh") + set(output_source "${gz_msgs_factory_OUTPUT_CPP_DIR}/${proto_package_dir}/register.cc") + + list(APPEND ${gz_msgs_factory_OUTPUT_CPP_HH_VAR} ${output_header}) + list(APPEND ${gz_msgs_factory_OUTPUT_CPP_CC_VAR} ${output_source}) + + list(APPEND output_files ${output_header}) + list(APPEND output_files ${output_source}) + + set(${gz_msgs_factory_OUTPUT_CPP_HH_VAR} ${${gz_msgs_factory_OUTPUT_CPP_HH_VAR}} PARENT_SCOPE) + set(${gz_msgs_factory_OUTPUT_CPP_CC_VAR} ${${gz_msgs_factory_OUTPUT_CPP_CC_VAR}} PARENT_SCOPE) + + set(depends_index) + + # Full path to an index file, which contains all defined message types for that proto file + foreach(proto_file ${generate_messages_MSGS_PROTOS}) + get_filename_component(FIL_WE ${proto_file} NAME_WE) + string(REPLACE "." "_" PACKAGE_UNDER ${gz_msgs_factory_PROTO_PACKAGE}) + string(REPLACE "." "_" MESSAGE_UNDER ${FIL_WE}) + set(input_index "${gz_msgs_factory_OUTPUT_CPP_DIR}/${PACKAGE_UNDER}_${MESSAGE_UNDER}.pb_index") + list(APPEND depends_index ${input_index}) + endforeach() + + + set(GENERATE_ARGS + --output-cpp-path "${gz_msgs_factory_OUTPUT_CPP_DIR}" + --proto-package "${gz_msgs_factory_PROTO_PACKAGE}" + --proto-path "${gz_msgs_factory_PROTO_PATH}" + --protos "${gz_msgs_factory_INPUT_PROTOS}" + ) + + add_custom_command( + OUTPUT ${output_files} + COMMAND Python3::Interpreter + ARGS ${gz_msgs_factory_FACTORY_GEN_SCRIPT} ${GENERATE_ARGS} + DEPENDS + ${depends_index} + # While the script is executed in the source directory, it does not write + # to the source tree. All outputs are stored in the build directory. + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Running factory generator" + VERBATIM + ) + +endfunction() diff --git a/cmake/gz_msgs_protoc.cmake b/cmake/gz_msgs_protoc.cmake index a1043cf1..32924fbb 100644 --- a/cmake/gz_msgs_protoc.cmake +++ b/cmake/gz_msgs_protoc.cmake @@ -25,7 +25,7 @@ function(gz_msgs_protoc) OUTPUT_CPP_HH_VAR OUTPUT_DETAIL_CPP_HH_VAR OUTPUT_CPP_CC_VAR) - set(multiValueArgs PROTO_PATH) + set(multiValueArgs PROTO_PATH DEPENDENCY_PROTO_PATHS) cmake_parse_arguments(gz_msgs_protoc "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -42,11 +42,16 @@ function(gz_msgs_protoc) if(gz_msgs_protoc_GENERATE_CPP) # Full path to generated header (${PROJECT_BINARY_DIR}/include/gz/msgs/foo.pb.h) - set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.h") + set(output_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}/${proto_package_dir}/${FIL_WE}.pb.h") # Full path to generated detail header (${PROJECT_BINARY_DIR}/include/gz/msgs/details/foo.pb.h) - set(output_detail_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/details/${FIL_WE}.pb.h") + set(output_detail_header "${gz_msgs_protoc_OUTPUT_CPP_DIR}/${proto_package_dir}/details/${FIL_WE}.pb.h") # Full path to generated ignition header (${PROJECT_BINARY_DIR}/include/foo.pb.cc) - set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}${proto_package_dir}/${FIL_WE}.pb.cc") + set(output_source "${gz_msgs_protoc_OUTPUT_CPP_DIR}/${proto_package_dir}/${FIL_WE}.pb.cc") + + # Full path to an index file, which contains all defined message types for that proto file + string(REPLACE "." "_" PACKAGE_UNDER ${gz_msgs_protoc_PROTO_PACKAGE}) + string(REPLACE "." "_" MESSAGE_UNDER ${FIL_WE}) + set(output_index "${gz_msgs_protoc_OUTPUT_CPP_DIR}/${PACKAGE_UNDER}_${MESSAGE_UNDER}.pb_index") # Generate a clean relative path (gz/msgs/foo.pb.h) string(REPLACE "${PROJECT_BINARY_DIR}/include/" "" output_include ${output_header}) @@ -59,6 +64,7 @@ function(gz_msgs_protoc) list(APPEND output_files ${output_header}) list(APPEND output_files ${output_detail_header}) list(APPEND output_files ${output_source}) + list(APPEND output_files ${output_index}) set(${gz_msgs_protoc_OUTPUT_INCLUDES} ${${gz_msgs_protoc_OUTPUT_INCLUDES}} PARENT_SCOPE) set(${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR} ${${gz_msgs_protoc_OUTPUT_DETAIL_CPP_HH_VAR}} PARENT_SCOPE) @@ -73,6 +79,12 @@ function(gz_msgs_protoc) --input-path "${ABS_FIL}" ) + if(gz_msgs_protoc_DEPENDENCY_PROTO_PATHS) + list(APPEND GENERATE_ARGS + --dependency-proto-paths "${gz_msgs_protoc_DEPENDENCY_PROTO_PATHS}" + ) + endif() + if(${gz_msgs_protoc_GENERATE_CPP}) list(APPEND GENERATE_ARGS --generate-cpp diff --git a/compiled/include/gz/msgs/Factory.hh b/compiled/include/gz/msgs/Factory.hh deleted file mode 100644 index 87f7ee00..00000000 --- a/compiled/include/gz/msgs/Factory.hh +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 GZ_MSGS_FACTORY_HH_ -#define GZ_MSGS_FACTORY_HH_ - -#include -#include -#include -#include - -#include "gz/msgs/config.hh" -#include "gz/msgs/Export.hh" -#include "gz/msgs/detail/dynamic_message_cast.hh" - -namespace gz -{ - namespace msgs - { - // Inline bracket to help doxygen filtering. - inline namespace GZ_MSGS_VERSION_NAMESPACE { - /// \class Factory Factory.hh gz/msgs.hh - /// This class will also try to load all Protobuf descriptors specified - /// \brief A factory that generates protobuf message based on a string type. - /// in the GZ_DESCRIPTOR_PATH environment variable on program start. - - class GZ_MSGS_VISIBLE Factory - { - public: using Message = google::protobuf::Message; - public: using MessagePtr = std::unique_ptr; - public: using FactoryFn = - std::function; - - /// \brief Register a message. - /// \param[in] _msgType Type of message to register. - /// \param[in] _factoryfn Function that generates the message. - public: static void - Register(const std::string &_msgType, FactoryFn _factoryFn); - - /// \brief Create a new instance of a message. - /// \param[in] _msgType Type of message to create. - /// \return Pointer to a google protobuf message. Null if the message - /// type could not be handled. - public: template - static std::unique_ptr New(const std::string &_msgType) - { - return detail::dynamic_message_cast(New(_msgType)); - } - - /// \brief Create a new instance of a message. - /// \param[in] _msgType Type of message to create. - /// \param[in] _args Message arguments. This will populate the message. - /// \return Pointer to a google protobuf message. Null if the message - /// type could not be handled. - public: template - static std::unique_ptr New(const std::string &_msgType, - const std::string &_args) - { - return detail::dynamic_message_cast(New(_msgType, _args)); - } - - /// \brief Create a new instance of a message. - /// \param[in] _msgType Type of message to create. - /// \return Pointer to a google protobuf message. Null if the message - /// type could not be handled. - public: static MessagePtr - New(const std::string &_msgType); - - /// \brief Create a new instance of a message. - /// \param[in] _msgType Type of message to create. - /// \param[in] _args Message arguments. This will populate the message. - /// \return Pointer to a google protobuf message. Null if the message - /// type could not be handled. - public: static MessagePtr - New(const std::string &_msgType, const std::string &_args); - - /// \brief Get all the message types - /// \param[out] _types Vector of strings of the message types. - public: static void Types(std::vector &_types); - - /// \brief Load a collection of descriptor .desc files. - /// \param[in] _paths A set of directories containing .desc decriptor - /// files. Each directory should be separated by ":". - public: static void LoadDescriptors(const std::string &_paths); - }; - - /// \brief Static message registration macro - /// - /// Use this macro to register messages. - /// \param[in] _msgtype Message type name. - /// \param[in] _classname Class name for message. - #define GZ_REGISTER_STATIC_MSG(_msgtype, _classname) \ - GZ_MSGS_VISIBLE \ - gz::msgs::Factory::MessagePtr New##_classname() \ - { \ - return std::unique_ptr(\ - new gz::msgs::_classname); \ - } \ - class GZ_MSGS_VISIBLE GzMsg##_classname \ - { \ - public: GzMsg##_classname() \ - { \ - gz::msgs::Factory::Register(_msgtype, New##_classname);\ - } \ - }; \ - static GzMsg##_classname GzMessagesInitializer##_classname; - } - } -} -#endif diff --git a/core/generator/Generator.cc b/core/generator/Generator.cc index b4845bef..c5f78039 100644 --- a/core/generator/Generator.cc +++ b/core/generator/Generator.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,7 @@ bool Generator::Generate(const FileDescriptor *_file, auto parent_path = filePath.parent_path(); auto fileStem = filePath.stem().string(); + // protoc generates ignition/msgs/msg.pb.cc and ignition/msgs/msg.pb.hh // This generator injects code into the msg.pb.cc file, but generates // a completely new header that wraps the original protobuf header @@ -112,6 +114,10 @@ bool Generator::Generate(const FileDescriptor *_file, newHeaderFilename += part.string() + "/"; sourceFilename += part.string() + "/"; } + + auto message_type_index = _generatorContext->Open(identifier + fileStem + ".pb_index"); + io::Printer index_printer(message_type_index, '$'); + identifier += fileStem; headerFilename += fileStem + ".gz.h"; newHeaderFilename += "details/" + fileStem + ".pb.h"; @@ -149,6 +155,9 @@ bool Generator::Generate(const FileDescriptor *_file, auto desc = _file->message_type(i); std::string ptrTypes; + index_printer.PrintRaw(desc->name()); + index_printer.PrintRaw("\n"); + // Define std::unique_ptr types for our messages ptrTypes += "typedef std::unique_ptr<" + desc->name() + "> " diff --git a/core/include/gz/msgs/CMakeLists.txt b/core/include/gz/msgs/CMakeLists.txt index 812c3233..bf4411e8 100644 --- a/core/include/gz/msgs/CMakeLists.txt +++ b/core/include/gz/msgs/CMakeLists.txt @@ -1,4 +1 @@ -gz_install_all_headers( - GENERATED_HEADERS - MessageTypes.hh -) +gz_install_all_headers() diff --git a/core/include/gz/msgs/Convert.hh b/core/include/gz/msgs/Convert.hh index 200e915e..75183340 100644 --- a/core/include/gz/msgs/Convert.hh +++ b/core/include/gz/msgs/Convert.hh @@ -24,6 +24,10 @@ #include "gz/msgs/config.hh" #include "gz/msgs/Export.hh" +#if not __has_include() + static_assert(false, "something is wrong") +#endif + /// \file Utility.hh /// \brief Utility functions that support conversion between message type /// and Gazebo Math types. diff --git a/core/include/gz/msgs/Factory.hh b/core/include/gz/msgs/Factory.hh new file mode 100644 index 00000000..cb1bdc9e --- /dev/null +++ b/core/include/gz/msgs/Factory.hh @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 GZ_MSGS_FACTORY_HH_ +#define GZ_MSGS_FACTORY_HH_ + +#include +#include +#include +#include + +#include "gz/msgs/config.hh" +#include "gz/msgs/Export.hh" + +#include "gz/msgs/MessageFactory.hh" + +namespace gz::msgs +{ + // Inline bracket to help doxygen filtering. + inline namespace GZ_MSGS_VERSION_NAMESPACE { + + /// \class Factory Factory.hh gz/msgs.hh + /// \brief A factory that generates protobuf message based on a string type. + /// This class will also try to load all Protobuf descriptors specified + /// in the GZ_DESCRIPTOR_PATH environment variable on program start. + class GZ_MSGS_VISIBLE Factory + { + public: using FactoryFn = MessageFactory::FactoryFn; + public: using FactoryFnCollection = MessageFactory::FactoryFnCollection; + public: using MessagePtr = MessageFactory::MessagePtr; + + private: Factory() = default; + public: Factory(const Factory&) = delete; + public: void operator=(const Factory&) = delete; + public: Factory(Factory&&) = delete; + public: void operator=(Factory&&) = delete; + public: static MessageFactory& Instance(); + + /// \brief Register a message. + /// \param[in] _msgType Type of message to register. + /// \param[in] _factoryfn Function that generates the message. + public: static void Register(const std::string &_msgType, + FactoryFn _factoryfn); + + /// \brief Register a collection of messages. + /// \param[in] _functions message generation functions + /// \return Number of registered message types + public: static int RegisterCollection(FactoryFnCollection &_functions); + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: template + static std::unique_ptr New(const std::string &_msgType) + { + return Factory::Instance().New(_msgType); + } + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \param[in] _args Message arguments. This will populate the message. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: template + static std::unique_ptr New(const std::string &_msgType, + const std::string &_args) + { + return Factory::Instance().New(_msgType, _args); + } + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: static MessagePtr New(const std::string &_msgType); + + /// \brief Create a new instance of a message. + /// \param[in] _msgType Type of message to create. + /// \param[in] _args Message arguments. This will populate the message. + /// \return Pointer to a google protobuf message. Null if the message + /// type could not be handled. + public: static MessagePtr New(const std::string &_msgType, const std::string &_args); + + /// \brief Get all the message types + /// \param[out] _types Vector of strings of the message types. + public: static void Types(std::vector &_types); + }; +} +} // namespace gz::msgs +#endif diff --git a/core/include/gz/msgs/MessageFactory.hh b/core/include/gz/msgs/MessageFactory.hh index 07a15431..868cbe90 100644 --- a/core/include/gz/msgs/MessageFactory.hh +++ b/core/include/gz/msgs/MessageFactory.hh @@ -38,6 +38,7 @@ namespace gz::msgs { public: using Message = google::protobuf::Message; public: using MessagePtr = std::unique_ptr; public: using FactoryFn = std::function; + public: using FactoryFnCollection = std::map; /// \brief Constructor public: MessageFactory(); @@ -50,6 +51,11 @@ namespace gz::msgs { /// \param[in] _factoryfn Function that generates the message. public: void Register(const std::string &_msgType, FactoryFn _factoryFn); + /// \brief Register a collection of messages. + /// \param[in] _functions Collection of messages to register. + /// \return Number of registered message types + public: int RegisterCollection(FactoryFnCollection &_funtions); + /// \brief Create a new instance of a message. /// \param[in] _msgType Type of message to create. /// \return Pointer to a google protobuf message. Null if the message @@ -96,7 +102,7 @@ namespace gz::msgs { public: void LoadDescriptors(const std::string &_paths); /// \brief A list of registered message types - private: std::map msgMap; + private: FactoryFnCollection msgMap; /// \brief Pointer to dynamic factory implementation private: std::unique_ptr dynamicFactory; diff --git a/compiled/src/Factory.cc b/core/src/Factory.cc similarity index 63% rename from compiled/src/Factory.cc rename to core/src/Factory.cc index 0c8ca02f..2dda1df4 100644 --- a/compiled/src/Factory.cc +++ b/core/src/Factory.cc @@ -16,47 +16,46 @@ */ #include "gz/msgs/Factory.hh" -#include "gz/msgs/MessageFactory.hh" #include -using namespace gz; -using namespace msgs; - - -gz::msgs::MessageFactory& GetFactoryInstance() { +namespace gz::msgs +{ +///////////////////////////////////////////////// +MessageFactory& Factory::Instance() +{ static gz::utils::NeverDestroyed instance; return instance.Access(); } ///////////////////////////////////////////////// void Factory::Register(const std::string &_msgType, - Factory::FactoryFn _factoryfn) + FactoryFn _factoryfn) { - GetFactoryInstance().Register(_msgType, _factoryfn); + Factory::Instance().Register(_msgType, _factoryfn); } ///////////////////////////////////////////////// -std::unique_ptr Factory::New( - const std::string &_msgType) +int Factory::RegisterCollection(FactoryFnCollection &_functions) { - return GetFactoryInstance().New(_msgType); + return Factory::Instance().RegisterCollection(_functions); } ///////////////////////////////////////////////// -std::unique_ptr Factory::New( - const std::string &_msgType, const std::string &_args) +void Factory::Types(std::vector &_types) { - return GetFactoryInstance().New(_msgType, _args); + Factory::Instance().Types(_types); } ///////////////////////////////////////////////// -void Factory::Types(std::vector &_types) +Factory::MessagePtr Factory::New(const std::string &_msgType) { - GetFactoryInstance().Types(_types); + return Factory::Instance().New(_msgType); } ///////////////////////////////////////////////// -void Factory::LoadDescriptors(const std::string &_paths) +Factory::MessagePtr Factory::New(const std::string &_msgType, const std::string &_args) { - GetFactoryInstance().LoadDescriptors(_paths); + return Factory::Instance().New(_msgType, _args); } + +} // namespace gz::msgs diff --git a/core/src/MessageFactory.cc b/core/src/MessageFactory.cc index a6ec028d..19e2a5d8 100644 --- a/core/src/MessageFactory.cc +++ b/core/src/MessageFactory.cc @@ -36,6 +36,7 @@ MessageFactory::MessageFactory(): { } +///////////////////////////////////////////////// MessageFactory::~MessageFactory() = default; ///////////////////////////////////////////////// @@ -45,38 +46,31 @@ void MessageFactory::Register(const std::string &_msgType, msgMap[_msgType] = _factoryfn; } +///////////////////////////////////////////////// +int MessageFactory::RegisterCollection(FactoryFnCollection &_functions) +{ + int registered = 0; + for (auto it: _functions) { + this->Register(it.first, it.second); + registered++; + } + return registered; +} + ///////////////////////////////////////////////// MessageFactory::MessagePtr MessageFactory::New( const std::string &_msgType) { - auto msgType = _msgType; - MessagePtr msg; - - std::string type; - // Convert "gz.msgs." to "gz_msgs.". - if (msgType.find("gz.msgs.") == 0) - { - type = "gz_msgs." + msgType.substr(8); - } - // Convert ".gz.msgs." to "gz_msgs.". - else if (msgType.find(".gz.msgs.") == 0) + if (msgMap.find(_msgType) != msgMap.end()) { - type = "gz_msgs." + msgType.substr(9); + // Create a new message if a FactoryFn has been assigned to the message type + return msgMap[_msgType](); } else { - // Fix typenames that are missing "gz_msgs." at the beginning. - if (msgType.find("gz_msgs.") != 0) - type = "gz_msgs."; - type += msgType; + // Check if we have the message descriptor. + return dynamicFactory->New(_msgType); } - - // Create a new message if a FactoryFn has been assigned to the message type - if (msgMap.find(type) != msgMap.end()) - return msgMap[type](); - - // Check if we have the message descriptor. - return dynamicFactory->New(msgType); } ///////////////////////////////////////////////// diff --git a/gz-msgs-extras.cmake.in b/gz-msgs-extras.cmake.in index 0f341472..ffef37eb 100644 --- a/gz-msgs-extras.cmake.in +++ b/gz-msgs-extras.cmake.in @@ -16,14 +16,14 @@ find_package(Python3 REQUIRED COMPONENTS Interpreter) - include(${@PROJECT_NAME@_DIR}/gz_msgs_protoc.cmake) +include(${@PROJECT_NAME@_DIR}/gz_msgs_factory.cmake) set(@PROJECT_NAME@_INSTALL_PATH "${@PROJECT_NAME@_DIR}/../../..") cmake_path(NORMAL_PATH @PROJECT_NAME@_INSTALL_PATH OUTPUT_VARIABLE @PROJECT_NAME@_INSTALL_PATH) set(PROTOC_NAME "@PROJECT_NAME@_protoc_plugin") set(PROTO_SCRIPT_NAME "@PROJECT_NAME@_generate.py") -set(FACTORY_SCRIPT_NAME "@PROJECT_NAME@_factory.py") +set(FACTORY_SCRIPT_NAME "@PROJECT_NAME@_generate_factory.py") set(@PROJECT_NAME@_PROTO_PATH ${@PROJECT_NAME@_INSTALL_PATH}/share/protos) set(@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN ${@PROJECT_NAME@_INSTALL_PATH}/bin/${PROTOC_NAME}) @@ -33,7 +33,7 @@ set(@PROJECT_NAME@_FACTORY_GENERATOR_SCRIPT ${@PROJECT_NAME@_INSTALL_PATH}/bin/$ function(get_installed_messages) set(options "") set(oneValueArgs MESSAGES_PATH_VARIABLE MESSAGES_PROTOS_VARIABLE) - set(multiValueArgs "") + set(multiValueArgs DEPENDS) cmake_parse_arguments(get_installed_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -48,42 +48,74 @@ endfunction() function(generate_messages) set(options "") - set(oneValueArgs MSGS_PATH TARGET) - set(multiValueArgs MSGS_PROTOS) + set(oneValueArgs MSGS_PATH TARGET PROTO_PACKAGE) + set(multiValueArgs MSGS_PROTOS DEPENDENCIES) cmake_parse_arguments(generate_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + string(REPLACE "." "_" gen_dir ${generate_messages_PROTO_PACKAGE}) + + set(depends_proto_paths) + set(depends_includes) + foreach(dep ${generate_messages_DEPENDENCIES}) + get_target_property(dep_proto_path ${dep} PROTO_DIR) + get_target_property(dep_proto_include_path ${dep} PROTO_INCLUDE_DIR) + list(APPEND depends_proto_paths ${dep_proto_path}) + list(APPEND depends_includes ${dep_proto_include_path}) + endforeach() foreach(proto_file ${generate_messages_MSGS_PROTOS}) gz_msgs_protoc( - MSGS_GEN_SCRIPT - ${@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT} - PROTO_PACKAGE - .gz.msgs - GENERATE_CPP - INPUT_PROTO - ${proto_file} - PROTOC_EXEC - protobuf::protoc - GZ_PROTOC_PLUGIN - ${@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN} - OUTPUT_CPP_DIR - "${PROJECT_BINARY_DIR}/include" - OUTPUT_INCLUDES - gen_includes - OUTPUT_CPP_HH_VAR - gen_headers - OUTPUT_DETAIL_CPP_HH_VAR - gen_detail_headers - OUTPUT_CPP_CC_VAR - gen_sources - PROTO_PATH - ${generate_messages_MSGS_PATH}) + MSGS_GEN_SCRIPT + ${@PROJECT_NAME@_PROTO_GENERATOR_SCRIPT} + PROTO_PACKAGE + ${generate_messages_PROTO_PACKAGE} + GENERATE_CPP + INPUT_PROTO + ${proto_file} + PROTOC_EXEC + protobuf::protoc + GZ_PROTOC_PLUGIN + ${@PROJECT_NAME@_PROTO_GENERATOR_PLUGIN} + OUTPUT_CPP_DIR + "${PROJECT_BINARY_DIR}/${gen_dir}_gen" + OUTPUT_INCLUDES + gen_includes + OUTPUT_CPP_HH_VAR + gen_headers + OUTPUT_DETAIL_CPP_HH_VAR + gen_detail_headers + OUTPUT_CPP_CC_VAR + gen_sources + PROTO_PATH + ${generate_messages_MSGS_PATH} + DEPENDENCY_PROTO_PATHS + ${depends_proto_paths} + ) endforeach() + gz_msgs_factory( + FACTORY_GEN_SCRIPT + ${@PROJECT_NAME@_FACTORY_GENERATOR_SCRIPT} + PROTO_PACKAGE + ${generate_messages_PROTO_PACKAGE} + INPUT_PROTOS + ${generate_messages_MSGS_PROTOS} + OUTPUT_CPP_DIR + "${PROJECT_BINARY_DIR}/${gen_dir}_gen" + OUTPUT_CPP_HH_VAR + gen_factory_headers + OUTPUT_CPP_CC_VAR + gen_factory_sources + PROTO_PATH + ${generate_messages_MSGS_PATH} + ) + set_source_files_properties( ${gen_headers} ${gen_detail_headers} ${gen_sources} + ${gen_factory_headers} + ${gen_factory_sources} PROPERTIES GENERATED TRUE) if(WIN32) @@ -91,10 +123,53 @@ function(generate_messages) COMPILE_FLAGS "/wd4100 /wd4512 /wd4127 /wd4068 /wd4244 /wd4267 /wd4251 /wd4146") endif() + add_library(${generate_messages_TARGET} ${gen_sources} ${gen_factory_sources}) + + # Export the messages path and dependency messages paths for potential dependent message libs + set(PROTO_DIR) + list(APPEND PROTO_DIR ${generate_messages_MSGS_PATH}) + list(APPEND PROTO_DIR ${depends_proto_paths}) + + set(PROTO_INCLUDE_DIR) + list(APPEND PROTO_INCLUDE_DIR ${PROJECT_BINARY_DIR}/${gen_dir}_gen) + list(APPEND PROTO_INCLUDE_DIR ${depends_includes}) + + set_target_properties(${generate_messages_TARGET} PROPERTIES PROTO_DIR "${PROTO_DIR}") + set_target_properties(${generate_messages_TARGET} PROPERTIES PROTO_INCLUDE_DIR "${PROTO_INCLUDE_DIR}") - add_library(${generate_messages_TARGET} ${gen_sources}) target_link_libraries(${generate_messages_TARGET} PUBLIC protobuf::libprotobuf gz-msgs10::gz-msgs10) - target_include_directories(${generate_messages_TARGET} PUBLIC ${PROJECT_BINARY_DIR}/include) + target_include_directories(${generate_messages_TARGET} PUBLIC ${PROJECT_BINARY_DIR}/${gen_dir}_gen ${depends_includes}) +endfunction() + +function(target_link_messages) + set(options PUBLIC PRIVATE) + set(oneValueArgs TARGET) + set(multiValueArgs MSG_TARGETS) + + cmake_parse_arguments(target_link_messages "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (target_link_messages_PUBLIC) + set(VISIBILITY PUBLIC) + elseif (target_link_messages_PRIVATE) + set(VISIBILITY PRIVATE) + endif() + + + foreach(message_lib ${target_link_messages_MSG_TARGETS}) + if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # MSVC link flag doesn't work with generator expressions + # TODO(mjcarroll) When CMake 3.24 is genrally available, use + # linking generator expressions as described here: + # https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:LINK_LIBRARY + target_link_libraries(${target_link_messages_TARGET} ${VISIBILITY} -WHOLEARCHIVE:$) + else() + target_link_libraries(${target_link_messages_TARGET} PRIVATE + $<$:-Wl,--whole-archive> + $<$:-force_load> + $<$:-force_load> ${message_lib} + $<$:-Wl,--no-whole-archive>) + endif() + endforeach() endfunction() diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 186e0f5d..6041e89c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,8 +10,8 @@ install(PROGRAMS gz_msgs_generate.py RENAME ${PROJECT_NAME}_generate.py DESTINATION ${GZ_BIN_INSTALL_DIR}) -install(PROGRAMS gz_msgs_factory.py - RENAME ${PROJECT_NAME}_factory.py +install(PROGRAMS gz_msgs_generate_factory.py + RENAME ${PROJECT_NAME}_generate_factory.py DESTINATION ${GZ_BIN_INSTALL_DIR}) # Skip command line tests for Windows, see diff --git a/tools/gz_msgs_factory.py b/tools/gz_msgs_factory.py deleted file mode 100755 index bfb1e05d..00000000 --- a/tools/gz_msgs_factory.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2022 Open Source Robotics Foundation -# -# 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 argparse -import os -import subprocess -import sys - -cc_header = """// Generated by gz-msgs. DO NOT EDIT! - -#include -#include "msgs.hh" - -void RegisterAllMessages(gz::msgs::MessageFactory & factory) -""" - - -def main(argv=sys.argv[1:]): - parser = argparse.ArgumentParser( - description='Generate protobuf factory file', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument( - '--output-cpp-path', - help='The basepath of the generated C++ files') - parser.add_argument( - '--proto-path', - required=True, - help='The location of the protos') - parser.add_argument( - '--protos', - required=True, - help='The list of protos to include' - ) - args = parser.parse_args(argv) - - print(args.output_cpp_path) - print(args.proto_path) - print(args.protos) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/gz_msgs_generate.py b/tools/gz_msgs_generate.py index f9c84483..1e588d9e 100755 --- a/tools/gz_msgs_generate.py +++ b/tools/gz_msgs_generate.py @@ -45,12 +45,20 @@ def main(argv=sys.argv[1:]): '--input-path', required=True, help='The location of the template files') + parser.add_argument( + '--dependency-proto-paths', + nargs='*', + help='The location of the protos') args = parser.parse_args(argv) # First generate the base cpp files cmd = [args.protoc_exec] cmd += [f'--proto_path={args.proto_path}'] + if args.dependency_proto_paths: + for path in args.dependency_proto_paths: + cmd += [f'--proto_path={path}'] + if args.generate_cpp: cmd += [f'--plugin=protoc-gen-ignmsgs={args.gz_generator_bin}'] cmd += [f'--cpp_out={args.output_cpp_path}'] diff --git a/tools/gz_msgs_generate_factory.py b/tools/gz_msgs_generate_factory.py new file mode 100755 index 00000000..aaa6e40d --- /dev/null +++ b/tools/gz_msgs_generate_factory.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 Open Source Robotics Foundation +# +# 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 argparse +import os +import sys + +# Create +cc_header = """/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * 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. + * +*/ + +/* This file was automatically generated. + * Do not edit this directly + */ + +#ifndef GZ_MSGS_MESSAGE_TYPES_HH_ +#define GZ_MSGS_MESSAGE_TYPES_HH_ +{gz_msgs_headers} + +namespace {namespace} {{ +int RegisterAll(); +}} +#endif""" + +# Create factory registration bits +cc_source = """/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * 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. + * +*/ + +/* This file was automatically generated. + * Do not edit this directly + */ + +#include "gz/msgs/Factory.hh" +#include "gz/msgs/MessageFactory.hh" +#include "{package_path}/MessageTypes.hh" + +#include + +namespace {{ +gz::msgs::MessageFactory::FactoryFnCollection kFactoryFunctions = {{ +{registrations} +}}; +}} // namespace +""" + +cc_factory = """ +namespace {namespace} {{ +int RegisterAll() {{ + return gz::msgs::Factory::RegisterCollection(kFactoryFunctions); +}} + +static int kMessagesRegistered = RegisterAll(); +}} // namespace {namespace} +""" + +register_fn = """ {{"{package_str}.{message_str}", + []()->std::unique_ptr{{return std::make_unique<{message_cpp_type}>();}}}},""" + +def main(argv=sys.argv[1:]): + parser = argparse.ArgumentParser( + description='Generate protobuf factory file', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument( + '--output-cpp-path', + required=True, + help='The basepath of the generated C++ files') + parser.add_argument( + '--proto-package', + required=True, + help='The basepath of the generated C++ files') + parser.add_argument( + '--proto-path', + required=True, + help='The location of the protos') + parser.add_argument( + '--protos', + type=str, + nargs='*', + required=True, + help='The list of protos to include' + ) + + args = parser.parse_args(argv) + + headers = [] + registrations = [] + + package = [p for p in args.proto_package.split('.') if len(p)] + namespace = '::'.join(package) + package_str = '.'.join(package) + package_path = '/'.join(package) + + for proto in args.protos: + proto_file = os.path.splitext(os.path.relpath(proto, args.proto_path))[0] + header = proto_file + ".pb.h" + headers.append(f"#include <{header}>") + proto_file = proto_file.replace('/', '_') + + # The gazebo extensions to the gazebo compiler write out a series of index files + # which capture the message types + index = os.path.join(args.output_cpp_path, proto_file + ".pb_index") + with open(index, "r") as index_f: + for line in index_f.readlines(): + line = line.strip() + + message_str = line + message_cpp_type = '::'.join(package) + '::' + message_str + + registrations.append(register_fn.format( + package_str=package_str, + message_str=message_str, + message_cpp_type=message_cpp_type)) + + with open(os.path.join(args.output_cpp_path, *package, 'MessageTypes.hh'), 'w') as f: + f.write(cc_header.format(gz_msgs_headers='\n'.join(headers), namespace=namespace)) + + with open(os.path.join(args.output_cpp_path, *package, 'register.cc'), 'w') as f: + f.write((cc_source.format(registrations='\n'.join(registrations), + namespace=namespace, + package_path=package_path) + + cc_factory.format(namespace=namespace))) + +if __name__ == '__main__': + sys.exit(main()) From 792f265b0e71697d34ef70d9e6dd17916ee12092 Mon Sep 17 00:00:00 2001 From: Michael Carroll Date: Thu, 11 May 2023 20:17:13 +0000 Subject: [PATCH 6/6] Restore Utility file Signed-off-by: Michael Carroll --- core/include/gz/msgs/Convert.hh | 55 --- core/include/gz/msgs/Utility.hh | 500 +++++++++++++++++++++++ core/include/gz/msgs/convert/vector2d.hh | 24 -- 3 files changed, 500 insertions(+), 79 deletions(-) delete mode 100644 core/include/gz/msgs/Convert.hh delete mode 100644 core/include/gz/msgs/convert/vector2d.hh diff --git a/core/include/gz/msgs/Convert.hh b/core/include/gz/msgs/Convert.hh deleted file mode 100644 index 75183340..00000000 --- a/core/include/gz/msgs/Convert.hh +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2016 Open Source Robotics Foundation - * - * 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 GZ_MSGS_CONVERT_HH_ -#define GZ_MSGS_CONVERT_HH_ - -#include -#include -#include - -#include "gz/msgs/config.hh" -#include "gz/msgs/Export.hh" - -#if not __has_include() - static_assert(false, "something is wrong") -#endif - -/// \file Utility.hh -/// \brief Utility functions that support conversion between message type -/// and Gazebo Math types. - -namespace gz::msgs -{ - // Inline bracket to help doxygen filtering. - inline namespace GZ_MSGS_VERSION_NAMESPACE { - - template - struct Converter { - static void Convert(const GzMsgT& in, T& out); - static void Convert(const T& in, GzMsgT& out); - }; - - template - T Convert(const GzMsgT &_msg) { - T ret; - Converter::Convert(_msg, ret); - return ret; - } - } -} // namespace gz::msgs - -#endif diff --git a/core/include/gz/msgs/Utility.hh b/core/include/gz/msgs/Utility.hh index e69de29b..b737da96 100644 --- a/core/include/gz/msgs/Utility.hh +++ b/core/include/gz/msgs/Utility.hh @@ -0,0 +1,500 @@ +/* + * Copyright (C) 2016 Open Source Robotics Foundation + * + * 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 GZ_MSGS_UTILITY_HH_ +#define GZ_MSGS_UTILITY_HH_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gz/msgs/config.hh" +#include "gz/msgs/Export.hh" +#include "gz/msgs/MessageTypes.hh" + +/// \file Utility.hh +/// \brief Utility functions that support conversion between message type +/// and Gazebo Math types. + +namespace gz +{ + namespace msgs + { + // Inline bracket to help doxygen filtering. + inline namespace GZ_MSGS_VERSION_NAMESPACE { + // + /// \brief Convert a msgs::Vector3d to a gz::math::Vector + /// \param[in] _v The vector to convert + /// \return A gz::math::Vector3d object + GZ_MSGS_VISIBLE + gz::math::Vector3d Convert(const msgs::Vector3d &_v); + + /// \brief Convert a msgs::Vector2d to a gz::math::Vector2d + /// \param[in] _v The vector2 to convert + /// \return A gz::math::Vector2d object + GZ_MSGS_VISIBLE + gz::math::Vector2d Convert(const msgs::Vector2d &_v); + + /// \brief Convert a msgs::Quaternion to a gz::math::Quaterniond + /// \param[in] _q The quaternion to convert + /// \return A gz::math::Quaterniond object + GZ_MSGS_VISIBLE + gz::math::Quaterniond Convert(const msgs::Quaternion &_q); + + /// \brief Convert a msgs::Pose to a gz::math::Pose3d + /// \param[in] _p The pose to convert + /// \return A gz::math::Pose3d object + GZ_MSGS_VISIBLE + gz::math::Pose3d Convert(const msgs::Pose &_p); + + /// \brief Convert a msgs::Color to a math::Color + /// \param[in] _c The color to convert + /// \return A math::Color object + GZ_MSGS_VISIBLE + math::Color Convert(const msgs::Color &_c); + + /// \brief Convert a msgs::PlaneGeom to a gz::math::Planed + /// \param[in] _p The plane to convert + /// \return A gz::math::Planed object + GZ_MSGS_VISIBLE + gz::math::Planed Convert(const msgs::PlaneGeom &_p); + + /// \brief Convert a msgs::Inertial to a gz::math::Inertiald + /// \param[in] _i The inertial to convert + /// \return A gz::math::Inertiald object + GZ_MSGS_VISIBLE + math::Inertiald Convert(const msgs::Inertial &_i); + + /// \brief Convert a msgs::SphericalCoordinates to an + /// gz::math::SphericalCoordinates + /// \param[in] _coord The spherical coordinates to convert + /// \return A gz::math::SphericalCoordinates object + GZ_MSGS_VISIBLE + math::SphericalCoordinates Convert( + const msgs::SphericalCoordinates &_coord); + + /// \brief Convert a msgs::AxisAlignedBox to an + /// gz::math::AxisAlignedBox + /// \param[in] _b The axis aligned box to convert + /// \return A gz::math::AxisAlignedBox object + GZ_MSGS_VISIBLE + math::AxisAlignedBox Convert(const msgs::AxisAlignedBox &_b); + + /// \brief Convert gz::math::AxisAlignedBox to + /// msgs::AxisAlignedBox. + /// \param[in] _b The axis aligned box to convert + /// \return A gz::math::AxisAlignedBox object + GZ_MSGS_VISIBLE + msgs::AxisAlignedBox Convert(const math::AxisAlignedBox &_b); + + /// \brief Convert a msgs::StringMsg to an std::string + /// \param[in] _m The message to convert + /// \return An std::string object + GZ_MSGS_VISIBLE + std::string Convert(const msgs::StringMsg &_m); + + /// \brief Convert a msgs::Boolean to a bool + /// \param[in] _m The message to convert + /// \return An bool object + GZ_MSGS_VISIBLE + bool Convert(const msgs::Boolean &_m); + + /// \brief Convert a msgs::Int32 to an int32_t + /// \param[in] _m The message to convert + /// \return An int32_t object + GZ_MSGS_VISIBLE + int32_t Convert(const msgs::Int32 &_m); + + /// \brief Convert a msgs::UInt32 to a uint32_t + /// \param[in] _m The message to convert + /// \return An uint32_t object + GZ_MSGS_VISIBLE + uint32_t Convert(const msgs::UInt32 &_m); + + /// \brief Convert a msgs::Int64 to an int64_t + /// \param[in] _m The message to convert + /// \return An int64_t object + GZ_MSGS_VISIBLE + int64_t Convert(const msgs::Int64 &_m); + + /// \brief Convert a msgs::UInt64 to a uint64_t + /// \param[in] _m The message to convert + /// \return An uint64_t object + GZ_MSGS_VISIBLE + uint64_t Convert(const msgs::UInt64 &_m); + + /// \brief Convert a msgs::Double to a double + /// \param[in] _m The message to convert + /// \return An double object + GZ_MSGS_VISIBLE + double Convert(const msgs::Double &_m); + + /// \brief Convert a msgs::Float to a float + /// \param[in] _m The message to convert + /// \return An float object + GZ_MSGS_VISIBLE + float Convert(const msgs::Float &_m); + + /// \brief Convert a msgs::Time to a std::chrono::steady_clock::duration + /// \param[in] _time The message to convert + /// \return A std::chrono::steady_clock::duration object + GZ_MSGS_VISIBLE + std::chrono::steady_clock::duration Convert(const msgs::Time &_time); + + /// \brief Convert a gz::math::Vector3d to a msgs::Vector3d + /// \param[in] _v The vector to convert + /// \return A msgs::Vector3d object + GZ_MSGS_VISIBLE + msgs::Vector3d Convert(const gz::math::Vector3d &_v); + + /// \brief Convert a gz::math::Vector2d to a msgs::Vector2d + /// \param[in] _v The vector to convert + /// \return A msgs::Vector2d object + GZ_MSGS_VISIBLE + msgs::Vector2d Convert(const gz::math::Vector2d &_v); + + /// \brief Convert a gz::math::Quaterniond to a msgs::Quaternion + /// \param[in] _q The quaternion to convert + /// \return A msgs::Quaternion object + GZ_MSGS_VISIBLE + msgs::Quaternion Convert(const gz::math::Quaterniond &_q); + + /// \brief Convert a gz::math::Pose3d to a msgs::Pose + /// \param[in] _p The pose to convert + /// \return A msgs::Pose object + GZ_MSGS_VISIBLE + msgs::Pose Convert(const gz::math::Pose3d &_p); + + /// \brief Convert a math::Color to a msgs::Color + /// \param[in] _c The color to convert + /// \return A msgs::Color object + GZ_MSGS_VISIBLE + msgs::Color Convert(const math::Color &_c); + + /// \brief Convert an math::Inertiald to a msgs::Inertial + /// \param[in] _i The Inertiald to convert + /// \return A msgs::Inertial object + GZ_MSGS_VISIBLE + msgs::Inertial Convert(const math::Inertiald &_i); + + /// \brief Convert an math::MassMatrix3d to a msgs::Inertial + /// \param[in] _m The MassMatrix3d to convert + /// \return A msgs::Inertial object + GZ_MSGS_VISIBLE + msgs::Inertial Convert(const math::MassMatrix3d &_m); + + /// \brief Convert an math::SphericalCoordinates to a + /// msgs::SphericalCoordinates + /// \param[in] _coord The SphericalCoordinates to convert + /// \return A msgs::SphericalCoordinates object + GZ_MSGS_VISIBLE + msgs::SphericalCoordinates Convert( + const math::SphericalCoordinates &_coord); + + /// \brief Convert a gz::math::Planed to a msgs::PlaneGeom + /// \param[in] _p The plane to convert + /// \return A msgs::PlaneGeom object + GZ_MSGS_VISIBLE + msgs::PlaneGeom Convert(const gz::math::Planed &_p); + + /// \brief Convert an std::string to a msgs::StringMsg + /// \param[in] _s The string to convert + /// \return A msgs::StringMsg object + GZ_MSGS_VISIBLE + msgs::StringMsg Convert(const std::string &_s); + + /// \brief Convert a bool to a msgs::Boolean + /// \param[in] _b The bool to convert + /// \return A msgs::Boolean object + GZ_MSGS_VISIBLE + msgs::Boolean Convert(const bool &_b); + + /// \brief Convert an int32_t to a msgs::Int32 + /// \param[in] _i The int32_t to convert + /// \return A msgs::Int32 object + GZ_MSGS_VISIBLE + msgs::Int32 Convert(const int32_t &_i); + + /// \brief Convert a uint32_t to a msgs::UInt32 + /// \param[in] _u The uint32_t to convert + /// \return A msgs::UInt32 object + GZ_MSGS_VISIBLE + msgs::UInt32 Convert(const uint32_t &_u); + + /// \brief Convert an int64_t to a msgs::Int64 + /// \param[in] _i The int64_t to convert + /// \return A msgs::Int64 object + GZ_MSGS_VISIBLE + msgs::Int64 Convert(const int64_t &_i); + + /// \brief Convert a uint64_t to a msgs::UInt64 + /// \param[in] _u The uint64_t to convert + /// \return A msgs::UInt64 object + GZ_MSGS_VISIBLE + msgs::UInt64 Convert(const uint64_t &_u); + + /// \brief Convert a double to a msgs::Double + /// \param[in] _d The double to convert + /// \return A msgs::Double object + GZ_MSGS_VISIBLE + msgs::Double Convert(const double &_d); + + /// \brief Convert a float to a msgs::Float + /// \param[in] _f The float to convert + /// \return A msgs::Float object + GZ_MSGS_VISIBLE + msgs::Float Convert(const float &_f); + + /// \brief Convert a std::chrono::steady_clock::duration to a msgs::Time + /// \param[in] _time_point The std::chrono::system_clock::duration to + /// convert + /// \return A msgs::Time object + GZ_MSGS_VISIBLE + msgs::Time Convert( + const std::chrono::steady_clock::duration &_time_point); + + /// \brief Convert a string to a msgs::Joint::Type enum. + /// \param[in] _str Joint type string. + /// \return A msgs::Joint::Type enum. Defaults to REVOLUTE + /// if _str is unrecognized. + GZ_MSGS_VISIBLE + msgs::Joint::Type ConvertJointType(const std::string &_str); + + /// \brief Convert a msgs::Joint::Type to a string. + /// \param[in] _type A msgs::Joint::Type enum. + /// \return Joint type string. Returns "unknown" if + /// _type is unrecognized. + GZ_MSGS_VISIBLE + std::string ConvertJointType(const msgs::Joint::Type &_type); + + /// \brief Convert a string to a msgs::Geometry::Type enum. + /// \param[in] _str Geometry type string. + /// \return A msgs::Geometry::Type enum. + GZ_MSGS_VISIBLE + msgs::Geometry::Type ConvertGeometryType(const std::string &_str); + + /// \brief Convert a msgs::Geometry::Type to a string. + /// \param[in] _type A msgs::Geometry::Type enum. + /// \return Geometry type string. + GZ_MSGS_VISIBLE + std::string ConvertGeometryType(const msgs::Geometry::Type _type); + + /// \brief Convert a string to a msgs::PixelFormatType enum. + /// \param[in] _str PixelFormatType string. + /// \return A msgs::PixelFormatType enum. + GZ_MSGS_VISIBLE + msgs::PixelFormatType ConvertPixelFormatType(const std::string &_str); + + /// \brief Convert a PixelFormatType to a string. This can be used for + /// debugging purposes. + // \param[in] _t PixelFormatType enum value. + /// \return String version of PixelFormatType. + GZ_MSGS_VISIBLE + std::string ConvertPixelFormatType(const msgs::PixelFormatType &_t); + + /// \brief Convert a string to a msgs::Material::ShaderType enum. + /// \param[in] _str Shader type string. + /// \return A msgs::Material::ShaderType enum. Defaults to VERTEX + /// if _str is unrecognized. + GZ_MSGS_VISIBLE + msgs::Material::ShaderType ConvertShaderType(const std::string &_str); + + /// \brief Convert a msgs::ShaderType to a string. + /// \param[in] _type A msgs::ShaderType enum. + /// \return Shader type string. Returns "unknown" if + /// _type is unrecognized. + GZ_MSGS_VISIBLE + std::string ConvertShaderType(const msgs::Material::ShaderType &_type); + + /// \brief Set a msgs::Vector3d from a gz::math::Vector3d + /// \param[out] _pt A msgs::Vector3d pointer + /// \param[in] _v A gz::math::Vector3d reference + GZ_MSGS_VISIBLE + void Set(msgs::Vector3d *_pt, const gz::math::Vector3d &_v); + + /// \brief Set a msgs::Vector2d from a gz::math::Vector2d + /// \param[out] _pt A msgs::Vector2d pointer + /// \param[in] _v A gz::math::Vector2d reference + GZ_MSGS_VISIBLE + void Set(msgs::Vector2d *_pt, const gz::math::Vector2d &_v); + + /// \brief Set a msgs::Quaternion from a gz::math::Quaterniond + /// \param[out] _q A msgs::Quaternion pointer + /// \param[in] _v A gz::math::Quaterniond reference + GZ_MSGS_VISIBLE + void Set(msgs::Quaternion *_q, const gz::math::Quaterniond &_v); + + /// \brief Set a msgs::Pose from a gz::math::Pose3d + /// \param[out] _p A msgs::Pose pointer + /// \param[in] _v A gz::math::Pose3d reference + GZ_MSGS_VISIBLE + void Set(msgs::Pose *_p, const gz::math::Pose3d &_v); + + /// \brief Set a msgs::Color from a math::Color + /// \param[out] _c A msgs::Color pointer + /// \param[in] _v A math::Color reference + GZ_MSGS_VISIBLE + void Set(msgs::Color *_c, const math::Color &_v); + + /// \brief Set a msgs::Inertial from an math::Inertiald + /// \param[out] _i A msgs::Inertial pointer + /// \param[in] _m An math::Inertiald reference + GZ_MSGS_VISIBLE + void Set(msgs::Inertial *_i, const math::Inertiald &_m); + + /// \brief Set a msgs::Inertial from an math::MassMatrix3d + /// \param[out] _i A msgs::Inertial pointer + /// \param[in] _m An math::MassMatrix3d reference + GZ_MSGS_VISIBLE + void Set(msgs::Inertial *_i, const math::MassMatrix3d &_m); + + /// \brief Set a msgs::SphericalCoordinates from a + /// math::SphericalCoordinates + /// \param[out] _sc A msgs::SphericalCoordinates pointer + /// \param[in] _m An math::SphericalCoordinates reference + GZ_MSGS_VISIBLE + void Set(msgs::SphericalCoordinates *_sc, + const math::SphericalCoordinates &_m); + + /// \brief Set a msgs::Plane from a gz::math::Planed + /// \param[out] _p A msgs::Plane pointer + /// \param[in] _v A gz::math::Planed reference + GZ_MSGS_VISIBLE + void Set(msgs::PlaneGeom *_p, const gz::math::Planed &_v); + + /// \brief Set a msgs::StringMsg from an std::string + /// \param[out] _p A msgs::StringMsg pointer + /// \param[in] _v An std::string reference + GZ_MSGS_VISIBLE + void Set(msgs::StringMsg *_p, const std::string &_v); + + /// \brief Set a msgs::Boolean from a bool + /// \param[out] _p A msgs::Boolean pointer + /// \param[in] _v An bool reference + GZ_MSGS_VISIBLE + void Set(msgs::Boolean *_p, const bool &_v); + + /// \brief Set a msgs::Int32 from an int32_t + /// \param[out] _p A msgs::Int32 pointer + /// \param[in] _v An int32_t reference + GZ_MSGS_VISIBLE + void Set(msgs::Int32 *_p, const int32_t &_v); + + /// \brief Set a msgs::UInt32 from a uint32_t + /// \param[out] _p A msgs::UInt32 pointer + /// \param[in] _v An uint32_t reference + GZ_MSGS_VISIBLE + void Set(msgs::UInt32 *_p, const uint32_t &_v); + + /// \brief Set a msgs::Int64 from an int64_t + /// \param[out] _p A msgs::Int64 pointer + /// \param[in] _v An int64_t reference + GZ_MSGS_VISIBLE + void Set(msgs::Int64 *_p, const int64_t &_v); + + /// \brief Set a msgs::UInt64 from an uint64_t + /// \param[out] _p A msgs::UInt64 pointer + /// \param[in] _v An uint64_t reference + GZ_MSGS_VISIBLE + void Set(msgs::UInt64 *_p, const uint64_t &_v); + + /// \brief Set a msgs::Double from a double + /// \param[out] _p A msgs::Double pointer + /// \param[in] _v An double reference + GZ_MSGS_VISIBLE + void Set(msgs::Double *_p, const double &_v); + + /// \brief Set a msgs::Float from a float + /// \param[out] _p A msgs::Float pointer + /// \param[in] _v An float reference + GZ_MSGS_VISIBLE + void Set(msgs::Float *_p, const float &_v); + + /// \brief Set a msgs::AxisAlignedBox from a math::AxisAlignedBox + /// \param[out] _b A msgs::AxisAlignedBox pointer + /// \param[in] _v An math::AxisAlignedBox reference + GZ_MSGS_VISIBLE + void Set(msgs::AxisAlignedBox *_b, const math::AxisAlignedBox &_v); + + /// \brief This function will set the header and field members of + /// a PointCloudPacked message. This will clear existing values in the + /// PointCloudPacked field and header. + /// \param[out] _msg The message to initialize. + /// \param[in] _frameId Name of the "frame_id". This will be stored as + /// key = "frame_id", value = _frameId in the message header. + /// \param[in] _memoryAligned If true, then each pair in the _fields + /// vector will be aligned at word (sizeof(size_t)) boundaries. + /// Additionally, the `point_step` of the _msg will be set to the + /// nearest word boundary. + /// \param[in] _fields The fields to add to the message. The following + /// strings are reserved, and will generate a set of fields + /// automatically. + /// + /// * "xyz" : This will add the "x", "y", and "z" fields. + GZ_MSGS_VISIBLE + void InitPointCloudPacked(msgs::PointCloudPacked &_msg, + const std::string &_frameId, bool _memoryAligned, + const std::vector> &_fields); + + /// \brief Convert a Discovery::Type to a string. This can be used for + /// debugging purposes. + // \param[in] _t Type of the discovery message. + /// \return String version of Discovery::Type. + GZ_MSGS_VISIBLE + std::string ToString(const msgs::Discovery::Type &_t); + + /// \brief Convert the contents of a model.config file, in the form of + /// an XML string, to a FuelMetadata message. + /// + /// Only the latest versioned model is added to the meta data message. + /// + /// The `` and `` tags are ignored. + /// + /// \param[in] _modelConfigStr A string containing XML data that matches + /// the model.config format. + /// \param[out] _meta The message that receives the converted data. + /// \return True if the conversion was successful. + GZ_MSGS_VISIBLE + bool ConvertFuelMetadata(const std::string &_modelConfigStr, + msgs::FuelMetadata &_meta); + + /// \brief Convert a FuelMetadata message to a string containing XML + /// data that matches the model.config format. + /// + /// The model.config format contains only a subset of the information in + /// a metadata message. The extra information in the metadata message is + /// discarded. + /// + /// \param[in] _meta The FuelMetadata message to convert. + /// \param[out] _modelConfigStr XML string containing the converted + /// message data. + /// \return True if the conversion was successful. + GZ_MSGS_VISIBLE + bool ConvertFuelMetadata(const msgs::FuelMetadata &_meta, + std::string &_modelConfigStr); + } + } +} +#endif diff --git a/core/include/gz/msgs/convert/vector2d.hh b/core/include/gz/msgs/convert/vector2d.hh deleted file mode 100644 index f3a777ba..00000000 --- a/core/include/gz/msgs/convert/vector2d.hh +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -namespace gz::msgs -{ - -struct Converter { - static void Convert(const gz::msgs::Vector3d &in, gz::math::Vector3d &out) - { - out.X() = in.x(); - out.Y() = in.y(); - out.Z() = in.z(); - } - - static void Convert(const gz::math::Vector3d &in, gz::msgs::Vector3d &out) - { - out.set_x(in.X()); - out.set_y(in.X()); - out.set_z(in.X()); - } -}; - -} // namespace gz::msgs