diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aad00b1d..2e08a6e09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -421,18 +421,12 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${g2o_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${g2o_C_FLAGS}") find_package(Eigen3 3.3 REQUIRED) -find_package(cereal) find_package(nlohmann_json 3.2.0) # Generate config.h set(G2O_OPENGL_FOUND ${OPENGL_FOUND}) set(G2O_HAVE_CHOLMOD ${CHOLMOD_FOUND}) set(G2O_HAVE_CSPARSE ${G2O_USE_CSPARSE}) -if (TARGET cereal::cereal) - set(G2O_HAVE_CEREAL 1) -else() - set(G2O_HAVE_CEREAL 0) -endif() if (TARGET nlohmann_json::nlohmann_json) set(G2O_HAVE_JSON 1) else() diff --git a/config.h.in b/config.h.in index d1d8c8f7e..b2ca5729a 100644 --- a/config.h.in +++ b/config.h.in @@ -7,7 +7,6 @@ #cmakedefine G2O_SHARED_LIBS 1 #cmakedefine G2O_LGPL_SHARED_LIBS 1 -#cmakedefine G2O_HAVE_CEREAL 1 #cmakedefine G2O_HAVE_JSON 1 // available sparse matrix libraries diff --git a/g2o/core/io/io_binary.cpp b/g2o/core/io/io_binary.cpp index 166e12480..da39df892 100644 --- a/g2o/core/io/io_binary.cpp +++ b/g2o/core/io/io_binary.cpp @@ -30,26 +30,35 @@ #include "g2o/config.h" #include "g2o/core/abstract_graph.h" - -#ifdef G2O_HAVE_CEREAL -#include -#include - -#include "io_wrapper_cereal.h" // IWYU pragma: keep -#else #include "g2o/stuff/logger.h" -#endif // HAVE CEREAL + +#ifdef G2O_HAVE_JSON +#include "io_wrapper_json.h" +#endif // HAVE_JSON namespace g2o { -#ifdef G2O_HAVE_CEREAL +#ifdef G2O_HAVE_JSON std::optional IoBinary::load(std::istream& input) { - return io::load(input, "BINARY"); + try { + return json::fromJson(nlohmann::json::from_cbor(input)); + } catch (const std::exception& e) { + G2O_ERROR("Exception while loading: {}", e.what()); + } + return std::nullopt; } bool IoBinary::save(std::ostream& output, const AbstractGraph& graph) { - return io::save(output, graph, "BINARY"); + try { + std::vector binary = + nlohmann::json::to_cbor(json::toJson(graph)); + output.write(reinterpret_cast(binary.data()), binary.size()); + return output.good(); + } catch (const std::exception& e) { + G2O_ERROR("Exception while saving: {}", e.what()); + } + return false; } #else diff --git a/g2o/core/io/io_json.cpp b/g2o/core/io/io_json.cpp index a0ae1cd0f..7406e4862 100644 --- a/g2o/core/io/io_json.cpp +++ b/g2o/core/io/io_json.cpp @@ -35,35 +35,19 @@ #ifdef G2O_HAVE_JSON #include -#endif // HAVE CEREAL + +#include "io_wrapper_json.h" +#endif // HAVE_JSON namespace g2o { #ifdef G2O_HAVE_JSON -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractParameter, tag, id, - value); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractData, tag, data); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractVertex, tag, id, - estimate, data); -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractEdge, tag, ids, - param_ids, measurement, information, data); - std::optional IoJson::load(std::istream& input) { - nlohmann::json json; try { + nlohmann::json json; input >> json; - const nlohmann::json& json_graph = json["graph"]; - AbstractGraph graph; - graph.fixed() = json_graph["fixed"].get>(); - graph.parameters() = - json_graph["params"] - .get>(); - graph.vertices() = json_graph["vertices"] - .get>(); - graph.edges() = - json_graph["edges"].get>(); - return graph; + return json::fromJson(json); } catch (const std::exception& e) { G2O_ERROR("Exception while saving: {}", e.what()); } @@ -71,14 +55,8 @@ std::optional IoJson::load(std::istream& input) { } bool IoJson::save(std::ostream& output, const AbstractGraph& graph) { - nlohmann::json json; try { - nlohmann::json& json_graph = json["graph"]; - json_graph["fixed"] = graph.fixed(); - json_graph["params"] = graph.parameters(); - json_graph["vertices"] = graph.vertices(); - json_graph["edges"] = graph.edges(); - output << json; + output << json::toJson(graph); } catch (const std::exception& e) { G2O_ERROR("Exception while saving: {}", e.what()); return false; diff --git a/g2o/core/io/io_wrapper_cereal.h b/g2o/core/io/io_wrapper_cereal.h deleted file mode 100644 index c6dc77c3b..000000000 --- a/g2o/core/io/io_wrapper_cereal.h +++ /dev/null @@ -1,165 +0,0 @@ -// g2o - General Graph Optimization -// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef G2O_CORE_IO_WRAPPER_CEREAL_H -#define G2O_CORE_IO_WRAPPER_CEREAL_H - -#include "g2o/config.h" - -#ifdef G2O_HAVE_CEREAL - -#include -#include -#include -#include -#include -#include -#include - -#include "g2o/core/abstract_graph.h" -#include "g2o/stuff/logger.h" - -namespace g2o { - -/** - * @brief Versions of the IO API for the graph using cereal. - */ -enum class IoVersions { - kGraph = 0, - kData = 0, - kParameter = 0, - kGraphElement = 0, - kVertex = 0, - kEdge = 0, -}; - -template -void serialize(Archive& archive, AbstractGraph& graph, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp("fixed", graph.fixed()), - cereal::make_nvp("params", graph.parameters()), - cereal::make_nvp("vertices", graph.vertices()), - cereal::make_nvp("edges", graph.edges())); -} - -template -void serialize(Archive& archive, AbstractGraph::AbstractData& data, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp("tag", data.tag), - cereal::make_nvp("data", data.data)); -} - -template -void serialize(Archive& archive, AbstractGraph::AbstractParameter& param, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp("tag", param.tag), cereal::make_nvp("id", param.id), - cereal::make_nvp("value", param.value)); -} - -template -void serialize(Archive& archive, AbstractGraph::AbstractGraphElement& elem, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp("tag", elem.tag), - cereal::make_nvp("data", elem.data)); -} - -template -void serialize(Archive& archive, AbstractGraph::AbstractVertex& vertex, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp( - "elem", - cereal::base_class(&vertex)), - cereal::make_nvp("id", vertex.id), - cereal::make_nvp("estimate", vertex.estimate)); -} - -template -void serialize(Archive& archive, AbstractGraph::AbstractEdge& edge, - const std::uint32_t version) { - (void)version; - archive(cereal::make_nvp( - "elem", - cereal::base_class(&edge)), - cereal::make_nvp("ids", edge.ids), - cereal::make_nvp("param_ids", edge.param_ids), - cereal::make_nvp("measurement", edge.measurement), - cereal::make_nvp("information", edge.information)); -} - -namespace io { -template -std::optional load(std::istream& input, std::string_view name) { - try { - ArchiveType archive(input); - AbstractGraph result; - archive(cereal::make_nvp("graph", result)); - return result; - } catch (const std::exception& e) { - G2O_ERROR("Exception while loading {}: {}", name, e.what()); - } - return std::nullopt; -} - -template -bool save(std::ostream& output, const AbstractGraph& graph, - std::string_view name) { - try { - ArchiveType archive(output); - archive(cereal::make_nvp("graph", graph)); - return true; - } catch (const std::exception& e) { - G2O_ERROR("Exception while saving {}: {}", name, e.what()); - } - return false; -} - -} // namespace io - -} // namespace g2o - -// Register Version numbers -CEREAL_CLASS_VERSION(g2o::AbstractGraph, - static_cast(g2o::IoVersions::kGraph)); -CEREAL_CLASS_VERSION(g2o::AbstractGraph::AbstractData, - static_cast(g2o::IoVersions::kData)); -CEREAL_CLASS_VERSION(g2o::AbstractGraph::AbstractParameter, - static_cast(g2o::IoVersions::kParameter)); -CEREAL_CLASS_VERSION( - g2o::AbstractGraph::AbstractGraphElement, - static_cast(g2o::IoVersions::kGraphElement)); -CEREAL_CLASS_VERSION(g2o::AbstractGraph::AbstractVertex, - static_cast(g2o::IoVersions::kVertex)); -CEREAL_CLASS_VERSION(g2o::AbstractGraph::AbstractEdge, - static_cast(g2o::IoVersions::kEdge)); - -#endif // HAVE_CEREAL - -#endif diff --git a/g2o/core/io/io_wrapper_json.h b/g2o/core/io/io_wrapper_json.h new file mode 100644 index 000000000..8c3206e13 --- /dev/null +++ b/g2o/core/io/io_wrapper_json.h @@ -0,0 +1,90 @@ +// g2o - General Graph Optimization +// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef G2O_CORE_IO_WRAPPER_JSON_H +#define G2O_CORE_IO_WRAPPER_JSON_H + +#include "g2o/config.h" + +#ifdef G2O_HAVE_JSON +#include + +#include "g2o/core/abstract_graph.h" + +namespace g2o { + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractParameter, tag, id, + value); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractData, tag, data); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractVertex, tag, id, + estimate, data); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(AbstractGraph::AbstractEdge, tag, ids, + param_ids, measurement, information, data); + +namespace json { + +/** + * @brief Versions of the IO API for the graph using cereal. + */ +enum class IoVersions { + kGraph = 0, + kData = 0, + kParameter = 0, + kGraphElement = 0, + kVertex = 0, + kEdge = 0, +}; + +inline AbstractGraph fromJson(const nlohmann::json& json) { + const nlohmann::json& json_graph = json["graph"]; + AbstractGraph graph; + graph.fixed() = json_graph["fixed"].get>(); + graph.parameters() = + json_graph["params"].get>(); + graph.vertices() = + json_graph["vertices"].get>(); + graph.edges() = + json_graph["edges"].get>(); + return graph; +} + +inline nlohmann::json toJson(const AbstractGraph& graph) { + nlohmann::json json; + nlohmann::json& json_graph = json["graph"]; + json_graph["fixed"] = graph.fixed(); + json_graph["params"] = graph.parameters(); + json_graph["vertices"] = graph.vertices(); + json_graph["edges"] = graph.edges(); + return json; +} + +} // namespace json + +} // namespace g2o + +#endif // HAVE_JSON + +#endif diff --git a/todo.md b/todo.md index a397e1c9a..36d372b59 100644 --- a/todo.md +++ b/todo.md @@ -1,5 +1,6 @@ -[ ] drop cereal (replace with json directly, drop xml) +[x] drop cereal (replace with json directly, drop xml) [ ] install json on Windows CI +[ ] wrap io_format.h to python [x] wrap simulator into library [x] add config types for simulation [ ] add tests for simulator diff --git a/unit_test/general/graph_io.cpp b/unit_test/general/graph_io.cpp index f4ecae4a4..690b1ce05 100644 --- a/unit_test/general/graph_io.cpp +++ b/unit_test/general/graph_io.cpp @@ -306,7 +306,7 @@ namespace { // We can always test G2O format, others depend on libraries const auto kFileformatsToTest = Values(g2o::io::Format::kG2O -#ifdef G2O_HAVE_CEREAL +#ifdef G2O_HAVE_JSON , g2o::io::Format::kJson, g2o::io::Format::kBinary #endif diff --git a/unit_test/general/graph_io_dynamic.cpp b/unit_test/general/graph_io_dynamic.cpp index 738322744..1b34ca5ad 100644 --- a/unit_test/general/graph_io_dynamic.cpp +++ b/unit_test/general/graph_io_dynamic.cpp @@ -177,7 +177,7 @@ namespace { // We can always test G2O format, others depend on libraries const auto kFileformatsToTest = Values(std::make_tuple(g2o::io::Format::kG2O, true) -#ifdef G2O_HAVE_CEREAL +#ifdef G2O_HAVE_JSON , std::make_tuple(g2o::io::Format::kJson, true), std::make_tuple(g2o::io::Format::kBinary, true)