Skip to content

Commit

Permalink
[wip] UrdfImporter: new plugin.
Browse files Browse the repository at this point in the history
The main purpose is two-fold -- being able to visualize the URDF
hierarchy using standard tools, and as a showcase of the flexibility of
SceneData custom fields, which preserve everything including the
URDF-specific physics properties.

TODO: finish the data import (inertia matrices, etc.), make it more
  robust
TODO: mesh & material import -- delegating to AnySceneImporter for
  these, joining the nested hierarchies somehow (needs a utility in
  SceneTools, ideally)
TODO: ability to not import nested models but instead expose them as
  custom SceneData (string) fields -- needs ability to store strings
  there; what about the color overrides then? have a MeshMaterial field
  alone, without any mesh?
TODO: explicitly mark what's a joint and what's a link via a custom
  SceneData bit field, ideally -- needs bitfields in Corrade first
TODO: docs about custom fields
TODO: CI setup
TODO: tests, look for constraints in the URDF itself
TODO: expose in all packages
TODO: expose in FindMagnumPlugins
  • Loading branch information
mosra committed Feb 21, 2023
1 parent eb08051 commit c12a4c7
Show file tree
Hide file tree
Showing 11 changed files with 1,015 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ if(MAGNUM_BUILD_DEPRECATED)
option(MAGNUM_WITH_TINYGLTFIMPORTER "Build TinyGltfImporter plugin" OFF)
endif()
option(MAGNUM_WITH_UFBXIMPORTER "Build UfbxImporter plugin" OFF)
option(MAGNUM_WITH_URDFIMPORTER "Build UrdfImporter plugin" OFF)
option(MAGNUM_WITH_WEBPIMPORTER "Build WebPImporter plugin" OFF)

option(MAGNUM_BUILD_TESTS "Build unit tests" OFF)
Expand Down
4 changes: 4 additions & 0 deletions src/MagnumPlugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ if(MAGNUM_WITH_UFBXIMPORTER)
add_subdirectory(UfbxImporter)
endif()

if(MAGNUM_WITH_URDFIMPORTER)
add_subdirectory(UrdfImporter)
endif()

if(MAGNUM_WITH_WEBPIMPORTER)
add_subdirectory(WebPImporter)
endif()
68 changes: 68 additions & 0 deletions src/MagnumPlugins/UrdfImporter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022 Vladimír Vondruš <[email protected]>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# 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 AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#

find_package(Magnum REQUIRED Trade)
find_package(pugixml CONFIG REQUIRED)

if(MAGNUM_BUILD_PLUGINS_STATIC AND NOT DEFINED MAGNUM_URDFIMPORTER_BUILD_STATIC)
set(MAGNUM_URDFIMPORTER_BUILD_STATIC 1)
endif()

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/configure.h)

# UrdfImporter plugin
add_plugin(UrdfImporter
importers
"${MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR}"
"${MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR};${MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR}"
UrdfImporter.conf
UrdfImporter.cpp
UrdfImporter.h)
if(MAGNUM_URDFIMPORTER_BUILD_STATIC AND MAGNUM_BUILD_STATIC_PIC)
set_target_properties(UrdfImporter PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
target_include_directories(UrdfImporter PUBLIC
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src)
target_link_libraries(UrdfImporter PUBLIC
Magnum::Trade
pugixml::pugixml)

install(FILES UrdfImporter.h ${CMAKE_CURRENT_BINARY_DIR}/configure.h
DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/UrdfImporter)

# Automatic static plugin import
if(MAGNUM_URDFIMPORTER_BUILD_STATIC)
install(FILES importStaticPlugin.cpp DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/UrdfImporter)
target_sources(UrdfImporter INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/importStaticPlugin.cpp)
endif()

if(MAGNUM_BUILD_TESTS)
add_subdirectory(Test)
endif()

# MagnumPlugins UrdfImporter target alias for superprojects
add_library(MagnumPlugins::UrdfImporter ALIAS UrdfImporter)
65 changes: 65 additions & 0 deletions src/MagnumPlugins/UrdfImporter/Test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020, 2021, 2022 Vladimír Vondruš <[email protected]>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# 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 AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#

# IDE folder in VS, Xcode etc. CMake 3.12+, older versions have only the FOLDER
# property that would have to be set on each target separately.
set(CMAKE_FOLDER "MagnumPlugins/UrdfImporter/Test")

if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID)
set(URDFIMPORTER_TEST_DIR ".")
else()
set(URDFIMPORTER_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR})
endif()

# CMake before 3.8 has broken $<TARGET_FILE*> expressions for iOS (see
# https://gitlab.kitware.com/cmake/cmake/merge_requests/404) and since Corrade
# doesn't support dynamic plugins on iOS, this sorta works around that. Should
# be revisited when updating Travis to newer Xcode (xcode7.3 has CMake 3.6).
if(NOT MAGNUM_URDFIMPORTER_BUILD_STATIC)
set(URDFIMPORTER_PLUGIN_FILENAME $<TARGET_FILE:UrdfImporter>)
endif()

# First replace ${} variables, then $<> generator expressions
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/configure.h.in)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/configure.h
INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in)

corrade_add_test(UrdfImporterTest UrdfImporterTest.cpp
LIBRARIES Magnum::Trade)
target_include_directories(UrdfImporterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>)
if(MAGNUM_URDFIMPORTER_BUILD_STATIC)
target_link_libraries(UrdfImporterTest PRIVATE UrdfImporter)
else()
# So the plugins get properly built when building the test
add_dependencies(UrdfImporterTest UrdfImporter)
endif()
if(CORRADE_BUILD_STATIC AND NOT MAGNUM_URDFIMPORTER_BUILD_STATIC)
# CMake < 3.4 does this implicitly, but 3.4+ not anymore (see CMP0065).
# That's generally okay, *except if* the build is static, the executable
# uses a plugin manager and needs to share globals with the plugins (such
# as output redirection and so on).
set_target_properties(UrdfImporterTest PROPERTIES ENABLE_EXPORTS ON)
endif()
104 changes: 104 additions & 0 deletions src/MagnumPlugins/UrdfImporter/Test/UrdfImporterTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
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 AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/Containers/ArrayView.h>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/Utility/Algorithms.h>
#include <Magnum/Trade/AbstractImporter.h>

#include "configure.h"

namespace Magnum { namespace Trade { namespace Test { namespace {

struct UrdfImporterTest: TestSuite::Tester {
explicit UrdfImporterTest();

void openMemory();
void openTwice();
void importTwice();

/* Explicitly forbid system-wide plugin dependencies */
PluginManager::Manager<AbstractImporter> _manager{"nonexistent"};
};

/* Shared among all plugins that implement data copying optimizations */
const struct {
const char* name;
bool(*open)(AbstractImporter&, Containers::ArrayView<const void>);
} OpenMemoryData[]{
{"data", [](AbstractImporter& importer, Containers::ArrayView<const void> data) {
/* Copy to ensure the original memory isn't referenced */
Containers::Array<char> copy{NoInit, data.size()};
Utility::copy(Containers::arrayCast<const char>(data), copy);
return importer.openData(copy);
}},
{"memory", [](AbstractImporter& importer, Containers::ArrayView<const void> data) {
return importer.openMemory(data);
}},
};

UrdfImporterTest::UrdfImporterTest() {
addInstancedTests({&UrdfImporterTest::openMemory},
Containers::arraySize(OpenMemoryData));

addTests({&UrdfImporterTest::openTwice,
&UrdfImporterTest::importTwice});

/* Load the plugin directly from the build tree. Otherwise it's static and
already loaded. */
#ifdef URDFIMPORTER_PLUGIN_FILENAME
CORRADE_INTERNAL_ASSERT_OUTPUT(_manager.load(URDFIMPORTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded);
#endif
}

void UrdfImporterTest::openMemory() {
/* Same as (a subset of) binary() except that it uses openData() &
openMemory() instead of openFile() to test data copying on import */

auto&& data = OpenMemoryData[testCaseInstanceId()];
setTestCaseDescription(data.name);

Containers::Pointer<AbstractImporter> importer = _manager.instantiate("UrdfImporter");
// TODO
}

void UrdfImporterTest::openTwice() {
Containers::Pointer<AbstractImporter> importer = _manager.instantiate("UrdfImporter");

// TODO

/* Shouldn't crash, leak or anything */
}

void UrdfImporterTest::importTwice() {
Containers::Pointer<AbstractImporter> importer = _manager.instantiate("UrdfImporter");

/* Verify that everything is working the same way on second use */
// TODO
}

}}}}

CORRADE_TEST_MAIN(Magnum::Trade::Test::UrdfImporterTest)
27 changes: 27 additions & 0 deletions src/MagnumPlugins/UrdfImporter/Test/configure.h.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
This file is part of Magnum.

Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

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 AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

#cmakedefine URDFIMPORTER_PLUGIN_FILENAME "${URDFIMPORTER_PLUGIN_FILENAME}"
#define URDFIMPORTER_TEST_DIR "${URDFIMPORTER_TEST_DIR}"
Empty file.
Loading

0 comments on commit c12a4c7

Please sign in to comment.