diff --git a/ci/install_magnum.sh b/ci/install_magnum.sh index c050a7a4..5da7b0ae 100755 --- a/ci/install_magnum.sh +++ b/ci/install_magnum.sh @@ -22,7 +22,7 @@ git clone https://github.com/mosra/magnum.git cd magnum mkdir build && cd build # Ubuntu -cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWITH_AUDIO=ON -DWITH_DEBUGTOOLS=ON -DWITH_GL=ON -DWITH_MESHTOOLS=ON -DWITH_PRIMITIVES=ON -DWITH_SCENEGRAPH=ON -DWITH_SHADERS=ON -DWITH_TEXT=ON -DWITH_TEXTURETOOLS=ON -DWITH_TRADE=ON -DWITH_GLFWAPPLICATION=ON -DWITH_WINDOWLESSGLXAPPLICATION=ON -DWITH_OPENGLTESTER=ON -DWITH_ANYAUDIOIMPORTER=ON -DWITH_ANYIMAGECONVERTER=ON -DWITH_ANYIMAGEIMPORTER=ON -DWITH_ANYSCENEIMPORTER=ON -DWITH_MAGNUMFONT=ON -DWITH_OBJIMPORTER=ON -DWITH_TGAIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON -DCMAKE_INSTALL_PREFIX=/usr .. +cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMAGNUM_WITH_AUDIO=ON -DMAGNUM_WITH_DEBUGTOOLS=ON -DMAGNUM_WITH_GL=ON -DMAGNUM_WITH_MESHTOOLS=ON -DMAGNUM_WITH_PRIMITIVES=ON -DMAGNUM_WITH_SCENEGRAPH=ON -DMAGNUM_WITH_SHADERS=ON -DMAGNUM_WITH_TEXT=ON -DMAGNUM_WITH_TEXTURETOOLS=ON -DMAGNUM_WITH_TRADE=ON -DMAGNUM_WITH_GLFWAPPLICATION=ON -DMAGNUM_WITH_WINDOWLESSEGLAPPLICATION=ON -DMAGNUM_WITH_OPENGLTESTER=ON -DMAGNUM_WITH_ANYAUDIOIMPORTER=ON -DMAGNUM_WITH_ANYIMAGECONVERTER=ON -DMAGNUM_WITH_ANYIMAGEIMPORTER=ON -DMAGNUM_WITH_ANYSCENEIMPORTER=ON -DMAGNUM_WITH_MAGNUMFONT=ON -DMAGNUM_WITH_OBJIMPORTER=ON -DMAGNUM_WITH_TGAIMPORTER=ON -DMAGNUM_WITH_WAVAUDIOIMPORTER=ON -DMAGNUM_TARGET_EGL=ON -DCMAKE_INSTALL_PREFIX=/usr .. make -j sudo make install cd ../.. @@ -31,7 +31,7 @@ cd ../.. git clone https://github.com/mosra/magnum-plugins.git cd magnum-plugins mkdir build && cd build -cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWITH_ASSIMPIMPORTER=ON -DWITH_DDSIMPORTER=ON -DWITH_JPEGIMPORTER=ON -DWITH_OPENGEXIMPORTER=ON -DWITH_PNGIMPORTER=ON -DWITH_TINYGLTFIMPORTER=ON -DWITH_STBTRUETYPEFONT=ON -DCMAKE_INSTALL_PREFIX=/usr .. +cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMAGNUM_WITH_ASSIMPIMPORTER=ON -DMAGNUM_WITH_DDSIMPORTER=ON -DMAGNUM_WITH_JPEGIMPORTER=ON -DMAGNUM_WITH_OPENGEXIMPORTER=ON -DMAGNUM_WITH_PNGIMPORTER=ON -DMAGNUM_WITH_TINYGLTFIMPORTER=ON -DMAGNUM_WITH_STBTRUETYPEFONT=ON -DCMAKE_INSTALL_PREFIX=/usr .. make -j sudo make install cd ../.. @@ -40,7 +40,7 @@ cd ../.. git clone https://github.com/mosra/magnum-integration.git cd magnum-integration mkdir build && cd build -cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWITH_DART=ON -DWITH_EIGEN=ON -DCMAKE_INSTALL_PREFIX=/usr -DDART_DIR=$DART_DIR .. +cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DMAGNUM_WITH_DART=ON -DMAGNUM_WITH_EIGEN=ON -DCMAKE_INSTALL_PREFIX=/usr -DDART_DIR=$DART_DIR .. make -j sudo make install cd ../.. diff --git a/cmake/FindEGL.cmake b/cmake/FindEGL.cmake new file mode 100644 index 00000000..c7a3f0f9 --- /dev/null +++ b/cmake/FindEGL.cmake @@ -0,0 +1,86 @@ +#.rst: +# Find EGL +# -------- +# +# Finds the EGL library. This module defines: +# +# EGL_FOUND - True if EGL library is found +# EGL::EGL - EGL imported target +# +# Additionally these variables are defined for internal usage: +# +# EGL_LIBRARY - EGL library +# EGL_INCLUDE_DIR - Include dir +# + +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020, 2021, 2022 Vladimír Vondruš +# +# 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. +# + +# Under Emscripten, GL is linked implicitly. With MINIMAL_RUNTIME you need to +# specify -lGL. Simply set the library name to that. +if(CORRADE_TARGET_EMSCRIPTEN) + set(EGL_LIBRARY GL CACHE STRING "Path to a library." FORCE) +else() + find_library(EGL_LIBRARY NAMES + EGL + + # ANGLE (CMake doesn't search for lib prefix on Windows) + libEGL + + # On iOS a part of OpenGLES + OpenGLES) +endif() + +# Include dir +find_path(EGL_INCLUDE_DIR NAMES + EGL/egl.h + + # iOS + EAGL.h) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(EGL DEFAULT_MSG + EGL_LIBRARY + EGL_INCLUDE_DIR) + +if(NOT TARGET EGL::EGL) + # Work around BUGGY framework support on macOS. Do this also in case of + # Emscripten, since there we don't have a location either. + # http://public.kitware.com/pipermail/cmake/2016-April/063179.html + if((APPLE AND ${EGL_LIBRARY} MATCHES "\\.framework$") OR CORRADE_TARGET_EMSCRIPTEN) + add_library(EGL::EGL INTERFACE IMPORTED) + set_property(TARGET EGL::EGL APPEND PROPERTY + INTERFACE_LINK_LIBRARIES ${EGL_LIBRARY}) + else() + add_library(EGL::EGL UNKNOWN IMPORTED) + set_property(TARGET EGL::EGL PROPERTY + IMPORTED_LOCATION ${EGL_LIBRARY}) + endif() + + set_target_properties(EGL::EGL PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${EGL_INCLUDE_DIR}) +endif() + +mark_as_advanced(EGL_LIBRARY EGL_INCLUDE_DIR) \ No newline at end of file diff --git a/cmake/FindGLFW.cmake b/cmake/FindGLFW.cmake index ed82186d..f391f96b 100644 --- a/cmake/FindGLFW.cmake +++ b/cmake/FindGLFW.cmake @@ -20,8 +20,8 @@ # # This file is part of Magnum. # -# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 -# Vladimír Vondruš +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, +# 2020, 2021, 2022 Vladimír Vondruš # Copyright © 2016 Jonathan Hale # # Permission is hereby granted, free of charge, to any person obtaining a @@ -43,11 +43,17 @@ # DEALINGS IN THE SOFTWARE. # -# GLFW installs cmake package config files to shared/ folder which handles -# dependencies in case GLFW is built statically. Try to find first, quietly, so -# it doesn't print loud messages when it's not found, since that's okay. -find_package(glfw3 CONFIG QUIET) +# GLFW installs cmake package config files which handles dependencies in case +# GLFW is built statically. Try to find first, quietly, so it doesn't print +# loud messages when it's not found, since that's okay. If the glfw target +# already exists, it means we're using it through a CMake subproject -- don't +# attempt to find the package in that case. +if(NOT TARGET glfw) + find_package(glfw3 CONFIG QUIET) +endif() +# If either a glfw config file was found or we have a subproject, point +# GLFW::GLFW to that and exit -- nothing else to do here. if(TARGET glfw) if(NOT TARGET GLFW::GLFW) # Aliases of (global) targets are only supported in CMake 3.11, so we @@ -81,6 +87,8 @@ if(CORRADE_TARGET_WINDOWS) set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2017) elseif(MSVC_VERSION VERSION_LESS 1930) set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2019) + elseif(MSVC_VERSION VERSION_LESS 1940) + set(_GLFW_LIBRARY_PATH_SUFFIX lib-vc2022) else() message(FATAL_ERROR "Unsupported MSVC version") endif() diff --git a/cmake/RobotDARTConfig.cmake.in b/cmake/RobotDARTConfig.cmake.in index d0434ce1..45798093 100644 --- a/cmake/RobotDARTConfig.cmake.in +++ b/cmake/RobotDARTConfig.cmake.in @@ -53,7 +53,7 @@ add_library(RobotDART::Simu INTERFACE IMPORTED) set_target_properties(RobotDART::Simu PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${RobotDART_INCLUDE_DIRS}" INTERFACE_LINK_DIRECTORIES "${RobotDART_LIBRARY_DIRS}" - INTERFACE_LINK_LIBRARIES "${RobotDART_LIBRARY};${RobotDART_LIBRARIES}" + INTERFACE_LINK_LIBRARIES "${RobotDART_LIBRARY};${RobotDART_LIBRARIES}@RobotDART_EXTRA_LIBS@" INTERFACE_COMPILE_OPTIONS "@RobotDART_CXX_FLAGS@") if(RobotDART_USE_MAGNUM) diff --git a/cmake/UthequeConfig.cmake.in b/cmake/UthequeConfig.cmake.in index 83955c1a..f4be2e7a 100644 --- a/cmake/UthequeConfig.cmake.in +++ b/cmake/UthequeConfig.cmake.in @@ -12,17 +12,13 @@ include(FindPackageHandleStandardArgs) # CMAKE_MODULE_PATH set(CMAKE_MODULE_PATH "@Utheque_CMAKE_MODULE_PATH@") -find_package(Boost REQUIRED filesystem) - set(Utheque_INCLUDE_DIRS "@Utheque_INCLUDE_DIRS@") -set(Utheque_LIBRARIES "Boost::filesystem") - add_library(Utheque INTERFACE IMPORTED) set_target_properties(Utheque PROPERTIES - INTERFACE_LINK_LIBRARIES "${Utheque_LIBRARIES}" INTERFACE_COMPILE_DEFINITIONS @Utheque_PREFIX@ - INTERFACE_INCLUDE_DIRECTORIES "${Utheque_INCLUDE_DIRS}") + INTERFACE_INCLUDE_DIRECTORIES "${Utheque_INCLUDE_DIRS}"@Utheque_DEPS@ + INTERFACE_COMPILE_OPTIONS "@Utheque_CXX_FLAGS@") # Handle the QUIET and REQUIRED arguments find_package_handle_standard_args( diff --git a/cmake/example_utheque/CMakeLists.txt b/cmake/example_utheque/CMakeLists.txt index a94568f3..98741b13 100644 --- a/cmake/example_utheque/CMakeLists.txt +++ b/cmake/example_utheque/CMakeLists.txt @@ -4,5 +4,5 @@ project(utheque_example) find_package(Utheque REQUIRED) add_executable(utheque_example example_utheque.cpp) -set_target_properties(utheque_example PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES) +set_target_properties(utheque_example PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES) # This is not really needed! target_link_libraries(utheque_example PUBLIC Utheque) diff --git a/src/docs/docs/install.md b/src/docs/docs/install.md index 92c96eac..ca46be67 100644 --- a/src/docs/docs/install.md +++ b/src/docs/docs/install.md @@ -129,7 +129,7 @@ git clone https://github.com/mosra/magnum.git cd magnum mkdir build && cd build # Ubuntu -cmake -DCMAKE_BUILD_TYPE=Release -DWITH_AUDIO=ON -DWITH_DEBUGTOOLS=ON -DWITH_GL=ON -DWITH_MESHTOOLS=ON -DWITH_PRIMITIVES=ON -DWITH_SCENEGRAPH=ON -DWITH_SHADERS=ON -DWITH_TEXT=ON -DWITH_TEXTURETOOLS=ON -DWITH_TRADE=ON -DWITH_GLFWAPPLICATION=ON -DWITH_WINDOWLESSGLXAPPLICATION=ON -DWITH_OPENGLTESTER=ON -DWITH_ANYAUDIOIMPORTER=ON -DWITH_ANYIMAGECONVERTER=ON -DWITH_ANYIMAGEIMPORTER=ON -DWITH_ANYSCENEIMPORTER=ON -DWITH_MAGNUMFONT=ON -DWITH_OBJIMPORTER=ON -DWITH_TGAIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON .. # this will enable almost all features of Magnum that are not necessarily needed for robot_dart (please refer to the documentation of Magnum for more details on selecting only the ones that you need) +cmake -DCMAKE_BUILD_TYPE=Release -DWITH_AUDIO=ON -DWITH_DEBUGTOOLS=ON -DWITH_GL=ON -DWITH_MESHTOOLS=ON -DWITH_PRIMITIVES=ON -DWITH_SCENEGRAPH=ON -DWITH_SHADERS=ON -DWITH_TEXT=ON -DWITH_TEXTURETOOLS=ON -DWITH_TRADE=ON -DWITH_GLFWAPPLICATION=ON -DWITH_WINDOWLESSEGLAPPLICATION=ON -DWITH_OPENGLTESTER=ON -DWITH_ANYAUDIOIMPORTER=ON -DWITH_ANYIMAGECONVERTER=ON -DWITH_ANYIMAGEIMPORTER=ON -DWITH_ANYSCENEIMPORTER=ON -DWITH_MAGNUMFONT=ON -DWITH_OBJIMPORTER=ON -DWITH_TGAIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON -DTARGET_HEADLESS=ON .. # this will enable almost all features of Magnum that are not necessarily needed for robot_dart (please refer to the documentation of Magnum for more details on selecting only the ones that you need) # Mac OSX cmake -DCMAKE_BUILD_TYPE=Release -DWITH_AUDIO=ON -DWITH_DEBUGTOOLS=ON -DWITH_GL=ON -DWITH_MESHTOOLS=ON -DWITH_PRIMITIVES=ON -DWITH_SCENEGRAPH=ON -DWITH_SHADERS=ON -DWITH_TEXT=ON -DWITH_TEXTURETOOLS=ON -DWITH_TRADE=ON -DWITH_GLFWAPPLICATION=ON -DWITH_WINDOWLESSCGLAPPLICATION=ON -DWITH_OPENGLTESTER=ON -DWITH_ANYAUDIOIMPORTER=ON -DWITH_ANYIMAGECONVERTER=ON -DWITH_ANYIMAGEIMPORTER=ON -DWITH_ANYSCENEIMPORTER=ON -DWITH_MAGNUMFONT=ON -DWITH_OBJIMPORTER=ON -DWITH_TGAIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON .. # this will enable almost all features of Magnum that are not necessarily needed for robot_dart (please refer to the documentation of Magnum for more details on selecting only the ones that you need) make -j diff --git a/src/examples/vx300.cpp b/src/examples/vx300.cpp new file mode 100644 index 00000000..0c158567 --- /dev/null +++ b/src/examples/vx300.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +#ifdef GRAPHIC +#include +#endif + +int main() +{ + auto robot = std::make_shared(); + robot->set_actuator_types("servo"); + + Eigen::VectorXd ctrl = robot_dart::make_vector({0.0, 1.0, -1.5, 1.0, 0.5, 0.}); + + auto controller = std::make_shared(ctrl); + robot->add_controller(controller); + + robot_dart::RobotDARTSimu simu; + simu.set_collision_detector("fcl"); +#ifdef GRAPHIC + simu.set_graphics(std::make_shared()); +#endif + simu.add_robot(robot); + simu.add_checkerboard_floor(); + + for (auto& n : robot->dof_names()) { + std::cout << n << std::endl; + } + + simu.run(2.5); + + ctrl << 0.0, -0.5, 0.5, -0.5, 0., 1.; + controller->set_parameters(ctrl); + controller->set_pd(20., 0.); + simu.run(2.5); + + return 0; +} diff --git a/src/external/subprocess.hpp b/src/external/subprocess.hpp new file mode 100644 index 00000000..1871d834 --- /dev/null +++ b/src/external/subprocess.hpp @@ -0,0 +1,170 @@ +// +// subprocess C++ library - https://github.com/tsaarni/cpp-subprocess +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Tero Saarni +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace subprocess +{ + +class popen +{ +public: + + popen(const std::string& cmd, std::vector argv) + : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr) + { + if (pipe(in_pipe) == -1 || + pipe(out_pipe) == -1 || + pipe(err_pipe) == -1 ) + { + throw std::system_error(errno, std::system_category()); + } + + run(cmd, argv); + } + + popen(const std::string& cmd, std::vector argv, std::ostream& pipe_stdout) + : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr) + { + auto filebuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(pipe_stdout.rdbuf()); + out_pipe[READ] = -1; + out_pipe[WRITE] = filebuf->fd(); + + if (pipe(in_pipe) == -1 || + pipe(err_pipe) == -1 ) + { + throw std::system_error(errno, std::system_category()); + } + + run(cmd, argv); + } + + ~popen() + { + delete in_filebuf; + delete in_stream; + if (out_filebuf != nullptr) delete out_filebuf; + if (out_stream != nullptr) delete out_stream; + delete err_filebuf; + delete err_stream; + } + + std::ostream& stdin() { return *in_stream; }; + + std::istream& stdout() + { + if (out_stream == nullptr) throw std::system_error(EBADF, std::system_category()); + return *out_stream; + }; + + std::istream& stderr() { return *err_stream; }; + + int wait() + { + int status = 0; + waitpid(pid, &status, 0); + return WEXITSTATUS(status); + }; + + void close() + { + in_filebuf->close(); + } + + +private: + + enum ends_of_pipe { READ = 0, WRITE = 1 }; + + struct raii_char_str + { + raii_char_str(std::string s) : buf(s.c_str(), s.c_str() + s.size() + 1) { }; + operator char*() const { return &buf[0]; }; + mutable std::vector buf; + }; + + void run(const std::string& cmd, std::vector argv) + { + argv.insert(argv.begin(), cmd); + + pid = ::fork(); + + if (pid == 0) child(argv); + + ::close(in_pipe[READ]); + ::close(out_pipe[WRITE]); + ::close(err_pipe[WRITE]); + + in_filebuf = new __gnu_cxx::stdio_filebuf(in_pipe[WRITE], std::ios_base::out, 1); + in_stream = new std::ostream(in_filebuf); + + if (out_pipe[READ] != -1) + { + out_filebuf = new __gnu_cxx::stdio_filebuf(out_pipe[READ], std::ios_base::in, 1); + out_stream = new std::istream(out_filebuf); + } + + err_filebuf = new __gnu_cxx::stdio_filebuf(err_pipe[READ], std::ios_base::in, 1); + err_stream = new std::istream(err_filebuf); + } + + void child(const std::vector& argv) + { + if (dup2(in_pipe[READ], STDIN_FILENO) == -1 || + dup2(out_pipe[WRITE], STDOUT_FILENO) == -1 || + dup2(err_pipe[WRITE], STDERR_FILENO) == -1 ) + { + std::perror("subprocess: dup2() failed"); + return; + } + + ::close(in_pipe[READ]); + ::close(in_pipe[WRITE]); + if (out_pipe[READ] != -1) ::close(out_pipe[READ]); + ::close(out_pipe[WRITE]); + ::close(err_pipe[READ]); + ::close(err_pipe[WRITE]); + + std::vector real_args(argv.begin(), argv.end()); + std::vector cargs(real_args.begin(), real_args.end()); + cargs.push_back(nullptr); + + if (execvp(cargs[0], &cargs[0]) == -1) + { + std::perror("subprocess: execvp() failed"); + return; + } + } + + pid_t pid; + + int in_pipe[2]; + int out_pipe[2]; + int err_pipe[2]; + + __gnu_cxx::stdio_filebuf* in_filebuf; + __gnu_cxx::stdio_filebuf* out_filebuf; + __gnu_cxx::stdio_filebuf* err_filebuf; + + std::ostream* in_stream; + std::istream* out_stream; + std::istream* err_stream; +}; + +} // namespace: subprocess diff --git a/src/python/robot.cpp b/src/python/robot.cpp index f3c8939b..75577bc8 100644 --- a/src/python/robot.cpp +++ b/src/python/robot.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -613,6 +614,11 @@ namespace robot_dart { py::arg("frequency") = 1000, py::arg("urdf") = "ur3e/ur3e_with_schunk_hand.urdf", py::arg("packages") = std::vector>({{"ur3e_description", "ur3e/ur3e_description"}})); + + py::class_>(m, "Vx300") + .def(py::init>&>(), + py::arg("urdf") = "vx300/vx300.urdf", + py::arg("packages") = std::vector>({{"interbotix_xsarm_descriptions", "vx300"}})); } } // namespace python } // namespace robot_dart diff --git a/src/robot_dart/gui/magnum/base_application.hpp b/src/robot_dart/gui/magnum/base_application.hpp index b0bbd597..a4c7a68d 100644 --- a/src/robot_dart/gui/magnum/base_application.hpp +++ b/src/robot_dart/gui/magnum/base_application.hpp @@ -23,7 +23,7 @@ #include #include #ifndef MAGNUM_MAC_OSX -#include +#include #else #include #endif diff --git a/src/robot_dart/gui/magnum/gs/camera.cpp b/src/robot_dart/gui/magnum/gs/camera.cpp index 8734bfe2..57262982 100644 --- a/src/robot_dart/gui/magnum/gs/camera.cpp +++ b/src/robot_dart/gui/magnum/gs/camera.cpp @@ -1,13 +1,12 @@ -#include - #include "camera.hpp" #include "robot_dart/gui/magnum/base_application.hpp" #include "robot_dart/gui_data.hpp" #include "robot_dart/robot_dart_simu.hpp" #include "robot_dart/utils.hpp" +#include + #include -#include #include #include @@ -21,11 +20,41 @@ #include #include +#include namespace robot_dart { namespace gui { namespace magnum { namespace gs { + + static fs::path search_path(const fs::path& filename) + { + std::string path = std::getenv("PATH"); + std::string delimiter = ":"; + + size_t pos = 0; + std::string token; + + std::vector all_paths; + while ((pos = path.find(delimiter)) != std::string::npos) { + token = path.substr(0, pos); + if (token.size() > 0) + all_paths.push_back(token); + path.erase(0, pos + delimiter.length()); + } + if (path.size() > 0) + all_paths.push_back(path); + + for (const fs::path& pp : all_paths) { + auto p = pp / filename; + std::error_code ec; + if (fs::is_regular_file(p, ec)) + return p; + } + + return ""; + } + Camera::Camera(Object3D& object, Magnum::Int width, Magnum::Int height) : Object3D{&object} { _yaw_object = new Object3D{this}; @@ -58,17 +87,7 @@ namespace robot_dart { Camera::~Camera() { -#ifdef ROBOT_DART_HAS_BOOST_PROCESS - if (_ffmpeg_process.id() > 0) { - // we let ffmpeg finish nicely by detaching it and sending the signal - // terminates() send a violent SIGTERM... - _ffmpeg_process.detach(); - kill(_ffmpeg_process.id(), SIGINT); - } -#else - if (_video_pid != 0) - kill(_video_pid, SIGINT); -#endif + _clean_up_subprocess(); } Camera3D& Camera::camera() const @@ -217,16 +236,16 @@ namespace robot_dart { void Camera::record_video(const std::string& video_fname, int fps) { - // we use boost process: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_process/tutorial.html -#ifdef ROBOT_DART_HAS_BOOST_PROCESS - namespace bp = boost::process; + // first clean up previous recording if necessary + _clean_up_subprocess(); + // search for ffmpeg - boost::filesystem::path ffmpeg = bp::search_path("ffmpeg"); + fs::path ffmpeg = search_path("ffmpeg"); if (ffmpeg.empty()) { ROBOT_DART_WARNING(ffmpeg.empty(), "ffmpeg not found in the PATH. RobotDART will not be able to record videos!"); return; } -#endif + // std::cout << "Found FFMPEG:" << ffmpeg << std::endl; _recording_video = true; // list our options @@ -241,36 +260,8 @@ namespace robot_dart { "-vcodec", "mpeg4", "-vb", "20M", video_fname}; -#ifdef ROBOT_DART_HAS_BOOST_PROCESS - // clang-format off - _ffmpeg_process = bp::child(ffmpeg, bp::args(args), bp::std_in < _video_pipe, bp::std_out > "/dev/null", bp::std_err > "/dev/null"); - // clang-format on - -#else - // we do it the old way - // this could should be removed in the future once boost.process is on every computer... - pipe(_video_fd); - // Data written to fd[1] appears on (i.e., can be read from) fd[0]. - _video_pid = fork(); - if (_video_pid != 0) { // main process - close(_video_fd[0]); // we close the input on this side - } - else { // ffmpeg process - args.push_back("-loglevel"); - args.push_back("quiet"); - close(_video_fd[1]); // ffmpeg does not write here - dup2(_video_fd[0], STDIN_FILENO); // ffmpeg will read the fd[0] as stdin - char** argv = (char**)calloc(args.size() + 2, sizeof(char*)); // we need the 0 at the end AND the ffffmpeg at the beginning - argv[0] = (char*)"ffmpeg"; - for (size_t i = 0; i < args.size(); ++i) - argv[i + 1] = (char*)args[i].c_str(); - int ret = execvp("ffmpeg", argv); - if (ret == -1) { - std::cerr << "Video recording: cannot execute ffmpeg! [" << strerror(errno) << "]" << std::endl; - exit(0); // we are in the fork - } - } -#endif + + _ffmpeg_process = new subprocess::popen(ffmpeg, args); } void Camera::draw(Magnum::SceneGraph::DrawableGroup3D& drawables, Magnum::GL::AbstractFramebuffer& framebuffer, Magnum::PixelFormat format, RobotDARTSimu* simu, const DebugDrawData& debug_data, bool draw_debug) @@ -380,14 +371,21 @@ namespace robot_dart { Corrade::Containers::StridedArrayView2D src = image.pixels().flipped<0>(); Corrade::Containers::StridedArrayView2D dst{Corrade::Containers::arrayCast(Corrade::Containers::arrayView(data)), {std::size_t(image.size().y()), std::size_t(image.size().x())}}; Corrade::Utility::copy(src, dst); -#ifdef ROBOT_DART_HAS_BOOST_PROCESS - _video_pipe.write(reinterpret_cast(data.data()), data.size()); - _video_pipe.flush(); -#else - write(_video_fd[1], reinterpret_cast(data.data()), data.size()); -#endif + + _ffmpeg_process->stdin().write(reinterpret_cast(data.data()), data.size()); + _ffmpeg_process->stdin().flush(); } } + + void Camera::_clean_up_subprocess() + { + if (_ffmpeg_process) { + _ffmpeg_process->close(); + delete _ffmpeg_process; + } + + _ffmpeg_process = nullptr; + } } // namespace gs } // namespace magnum } // namespace gui diff --git a/src/robot_dart/gui/magnum/gs/camera.hpp b/src/robot_dart/gui/magnum/gs/camera.hpp index 736f59d7..853aa870 100644 --- a/src/robot_dart/gui/magnum/gs/camera.hpp +++ b/src/robot_dart/gui/magnum/gs/camera.hpp @@ -5,12 +5,6 @@ #include #include -#include -#if ((BOOST_VERSION / 100000) > 1) || ((BOOST_VERSION / 100000) == 1 && ((BOOST_VERSION / 100 % 1000) >= 64)) -#include // for launching ffmpeg -#define ROBOT_DART_HAS_BOOST_PROCESS -#endif - #include #include #include @@ -18,6 +12,10 @@ #include #include +namespace subprocess { + class popen; +} + namespace robot_dart { namespace gui { namespace magnum { @@ -92,14 +90,9 @@ namespace robot_dart { bool _recording_video = false; Corrade::Containers::Optional _image, _depth_image; -#ifdef ROBOT_DART_HAS_BOOST_PROCESS - // pipe to write a video - boost::process::opstream _video_pipe; - boost::process::child _ffmpeg_process; -#else - pid_t _video_pid = 0; - int _video_fd[2]; -#endif + subprocess::popen* _ffmpeg_process = nullptr; + + void _clean_up_subprocess(); }; } // namespace gs } // namespace magnum diff --git a/src/robot_dart/gui/magnum/gs/create_compatibility_shader.hpp b/src/robot_dart/gui/magnum/gs/create_compatibility_shader.hpp index 5a627910..f6d81fd5 100644 --- a/src/robot_dart/gui/magnum/gs/create_compatibility_shader.hpp +++ b/src/robot_dart/gui/magnum/gs/create_compatibility_shader.hpp @@ -27,6 +27,8 @@ #include #include +#include + namespace robot_dart { namespace gui { namespace magnum { diff --git a/src/robot_dart/robot.cpp b/src/robot_dart/robot.cpp index 7c13733d..27a757be 100644 --- a/src/robot_dart/robot.cpp +++ b/src/robot_dart/robot.cpp @@ -1,6 +1,3 @@ - -#include -#include #include #include @@ -731,7 +728,7 @@ namespace robot_dart { #if DART_VERSION_AT_LEAST(6, 10, 0) bool force = jt->areLimitsEnforced(); #else - bool force = jt->isPositionLimitEnforced()); + bool force = jt->isPositionLimitEnforced(); #endif auto type = jt->getActuatorType(); force = force || type == dart::dynamics::Joint::SERVO || type == dart::dynamics::Joint::MIMIC; @@ -1916,8 +1913,7 @@ namespace robot_dart { _packages = packages; // std::cout << "RobotDART:: using: " << model_file << std::endl; - // in C++17 we would use std::filesystem! - boost::filesystem::path path(model_file); + fs::path path(model_file); std::string extension = path.extension().string(); if (extension == ".urdf") { #if DART_VERSION_AT_LEAST(6, 12, 0) @@ -2205,4 +2201,4 @@ namespace robot_dart { return robot; } -} // namespace robot_dart \ No newline at end of file +} // namespace robot_dart diff --git a/src/robot_dart/robots/vx300.hpp b/src/robot_dart/robots/vx300.hpp new file mode 100644 index 00000000..0b427de5 --- /dev/null +++ b/src/robot_dart/robots/vx300.hpp @@ -0,0 +1,19 @@ +#ifndef ROBOT_DART_ROBOTS_VX300_HPP +#define ROBOT_DART_ROBOTS_VX300_HPP + +#include "robot_dart/robot.hpp" + +namespace robot_dart { + namespace robots { + class Vx300 : public Robot { + public: + Vx300(const std::string& urdf = "vx300/vx300.urdf", const std::vector>& packages = {{"interbotix_xsarm_descriptions", "vx300"}}) : Robot(urdf, packages) + { + fix_to_world(); + set_position_enforced(true); + set_color_mode("aspect"); + } + }; + } // namespace robots +} // namespace robot_dart +#endif diff --git a/src/utheque/utheque.hpp b/src/utheque/utheque.hpp index a79807a6..a74f8591 100644 --- a/src/utheque/utheque.hpp +++ b/src/utheque/utheque.hpp @@ -1,17 +1,69 @@ #ifndef UTHEQUE_HPP_ #define UTHEQUE_HPP_ -#include -#include // will move to std::filesystem +#include +#include #include +#include +#include #include +#if __has_include() +#include +namespace fs = std::filesystem; +#else +#include +namespace fs = std::experimental::filesystem; +#endif + namespace utheque { #ifndef UTHEQUE_PREFIX static constexpr char* DEFAULT_PREFIX = const_cast("/usr/local"); #else static constexpr char* DEFAULT_PREFIX = const_cast(UTHEQUE_PREFIX); #endif + + // Helpers functions for string trimming + // trim from start (in place) + static inline void ltrim(std::string& s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !std::isspace(c); })); + } + + // trim from end (in place) + static inline void rtrim(std::string& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !std::isspace(c); }).base(), s.end()); + } + + // trim from both ends (in place) + static inline void trim(std::string& s) + { + ltrim(s); + rtrim(s); + } + + // trim from start (copying) + static inline std::string ltrim_copy(std::string s) + { + ltrim(s); + return s; + } + + // trim from end (copying) + static inline std::string rtrim_copy(std::string s) + { + rtrim(s); + return s; + } + + // trim from both ends (copying) + static inline std::string trim_copy(std::string s) + { + trim(s); + return s; + } + /// return the directory where to find the urdf (or urdf package) from the utheque (URDF library) /// if start by /, do nothing /// otherwise, search (in this order): @@ -27,10 +79,9 @@ namespace utheque { /// @arg prefix (default to UTHEQUE_PREFIX) /// @arg verbose print search paths /// @return the full (absolute) path where to find the URDF (e.g. /usr/local/share/utheque/) - static std::string directory(const std::string& filename, bool verbose = false, const std::string& prefix = DEFAULT_PREFIX) + static inline std::string directory(const std::string& filename, bool verbose = false, const std::string& prefix = DEFAULT_PREFIX) { - namespace fs = boost::filesystem; - fs::path model_file(boost::trim_copy(filename)); + fs::path model_file(trim_copy(filename)); if (verbose) std::cout << "utheque: searching for [" << model_file.string() << "]" << std::endl; @@ -86,11 +137,10 @@ namespace utheque { /// @arg urdf or package name (e.g. talos/talos.urdf or talos_description) /// @arg prefix /usr/local/ /// @return full path of the URDF file: (e.g. /usr/local/share/utheque/talos/talos.urdf) - static std::string path(const std::string& filename, bool verbose = false, const std::string& prefix = DEFAULT_PREFIX) + static inline std::string path(const std::string& filename, bool verbose = false, const std::string& prefix = DEFAULT_PREFIX) { - namespace fs = boost::filesystem; auto file_dir = fs::path(directory(filename, verbose, prefix)); - auto model_file = file_dir / fs::path(boost::trim_copy(filename)); + auto model_file = file_dir / fs::path(trim_copy(filename)); return model_file.string(); } } // namespace utheque diff --git a/utheque/icub/icub.urdf b/utheque/icub/icub.urdf index f9f48351..61b23e99 100644 --- a/utheque/icub/icub.urdf +++ b/utheque/icub/icub.urdf @@ -1,31 +1,31 @@ - + - + - - - - - + + + + + - - - + + + @@ -44,7 +44,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -86,7 +86,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -252,7 +252,7 @@ - + @@ -352,7 +352,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -416,7 +416,7 @@ - + @@ -439,7 +439,7 @@ - + @@ -458,7 +458,7 @@ - + @@ -496,7 +496,7 @@ - + @@ -515,7 +515,7 @@ - + @@ -534,7 +534,7 @@ - + @@ -656,7 +656,7 @@ - + @@ -675,7 +675,7 @@ - + @@ -694,7 +694,7 @@ - + @@ -819,82 +819,82 @@ - - + + - + - - + + - + - + - + - + - + - - + + - + - + - + - - + + - + - - + + - + - + - + - + @@ -902,7 +902,7 @@ - + @@ -910,39 +910,39 @@ - + - - + + - + - - + + - + - + - + - + @@ -950,7 +950,7 @@ - + @@ -958,39 +958,39 @@ - + - + - + - - + + - + - - + + - + - + - + @@ -998,39 +998,39 @@ - + - + - + - - + + - + - - + + - + - + - + @@ -1038,7 +1038,7 @@ - + @@ -1046,7 +1046,7 @@ - + @@ -1054,7 +1054,7 @@ - + @@ -1063,7 +1063,7 @@ - + @@ -1071,47 +1071,47 @@ - + - - + + - - + + - + - + - + - + - + @@ -1127,9 +1127,9 @@ - + - + @@ -1143,9 +1143,9 @@ - + - + @@ -1159,7 +1159,7 @@ - + @@ -1174,7 +1174,7 @@ - + @@ -1189,7 +1189,7 @@ - + @@ -1204,7 +1204,7 @@ - + @@ -1219,7 +1219,7 @@ - + @@ -1234,8 +1234,9 @@ - + - \ No newline at end of file + + diff --git a/utheque/vx300/vx300.urdf b/utheque/vx300/vx300.urdf new file mode 100644 index 00000000..6d7325f7 --- /dev/null +++ b/utheque/vx300/vx300.urdf @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/utheque/vx300/vx300_meshes/vx300_10_ar_tag.stl b/utheque/vx300/vx300_meshes/vx300_10_ar_tag.stl new file mode 100644 index 00000000..193014b6 Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_10_ar_tag.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_1_base.stl b/utheque/vx300/vx300_meshes/vx300_1_base.stl new file mode 100644 index 00000000..5a7efda2 Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_1_base.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_2_shoulder.stl b/utheque/vx300/vx300_meshes/vx300_2_shoulder.stl new file mode 100644 index 00000000..dc22aa7e Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_2_shoulder.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_3_upper_arm.stl b/utheque/vx300/vx300_meshes/vx300_3_upper_arm.stl new file mode 100644 index 00000000..111c586e Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_3_upper_arm.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_4_forearm.stl b/utheque/vx300/vx300_meshes/vx300_4_forearm.stl new file mode 100644 index 00000000..cbdc35cf Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_4_forearm.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_5_wrist.stl b/utheque/vx300/vx300_meshes/vx300_5_wrist.stl new file mode 100644 index 00000000..ab8423e9 Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_5_wrist.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_6_gripper.stl b/utheque/vx300/vx300_meshes/vx300_6_gripper.stl new file mode 100644 index 00000000..043db9ca Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_6_gripper.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_7_gripper_prop.stl b/utheque/vx300/vx300_meshes/vx300_7_gripper_prop.stl new file mode 100644 index 00000000..36099b42 Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_7_gripper_prop.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_8_gripper_bar.stl b/utheque/vx300/vx300_meshes/vx300_8_gripper_bar.stl new file mode 100644 index 00000000..eba3caa2 Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_8_gripper_bar.stl differ diff --git a/utheque/vx300/vx300_meshes/vx300_9_gripper_finger.stl b/utheque/vx300/vx300_meshes/vx300_9_gripper_finger.stl new file mode 100644 index 00000000..d6df86be Binary files /dev/null and b/utheque/vx300/vx300_meshes/vx300_9_gripper_finger.stl differ diff --git a/waf_tools/dart.py b/waf_tools/dart.py index 2418370c..0af310d9 100644 --- a/waf_tools/dart.py +++ b/waf_tools/dart.py @@ -174,11 +174,9 @@ def get_directory(filename, dirs): raise Exception('We need DART version at least 6.0.0') if dart_major > 6: dart_load_prefix = 'io' - dart_cxx_flags = '' - if dart_major == 6 and dart_minor >= 9: - dart_cxx_flags = '-std=c++14' - if dart_major > 6 or (dart_major == 6 and dart_minor >= 13): - dart_cxx_flags = '-std=c++17' + conf.env['DART_REQUIRES_BOOST'] = False + if dart_major < 6 or (dart_major == 6 and dart_minor <= 12): + conf.env['DART_REQUIRES_BOOST'] = True dart_include = [] if urdfdom_found: @@ -201,8 +199,6 @@ def get_directory(filename, dirs): conf.env.INCLUDES_DART = dart_include conf.env.LIBPATH_DART = dart_lib conf.env.LIB_DART = ['dart', 'dart-'+dart_load_prefix, 'dart-'+dart_load_prefix+'-urdf'] - if len(dart_cxx_flags) > 0: - conf.env.CXXFLAGS_DART = [dart_cxx_flags] conf.end_msg(conf.env.LIB_DART) diff --git a/waf_tools/magnum.py b/waf_tools/magnum.py index 16b4d8f3..b5204083 100644 --- a/waf_tools/magnum.py +++ b/waf_tools/magnum.py @@ -162,7 +162,7 @@ def fatal(required, msg): magnum_var = kw.get('uselib_store', 'Magnum') # to-do: enforce C++11/14 - magnum_possible_configs = ["BUILD_DEPRECATED", "BUILD_STATIC", "BUILD_MULTITHREADED", "TARGET_GL", "TARGET_GLES", "TARGET_GLES2", "TARGET_GLES3", "TARGET_DESKTOP_GLES", "TARGET_WEBGL", "TARGET_HEADLESS"] + magnum_possible_configs = ["BUILD_DEPRECATED", "BUILD_STATIC", "BUILD_MULTITHREADED", "TARGET_GL", "TARGET_GLES", "TARGET_GLES2", "TARGET_GLES3", "TARGET_DESKTOP_GLES", "TARGET_WEBGL", "TARGET_HEADLESS", "TARGET_EGL"] magnum_config = [] magnum_components, magnum_component_type, magnum_dependencies = get_magnum_components() @@ -193,6 +193,10 @@ def fatal(required, msg): index = find_in_string(config_content, '#define MAGNUM_' + config) if index > -1: magnum_config.append(config) + else: + index = find_in_string(config_content, '#define MAGNUM_' + config) + if index > -1: + magnum_config.append(config) conf.end_msg(magnum_config) if 'TARGET_GL' in magnum_config: @@ -218,10 +222,10 @@ def fatal(required, msg): conf.end_msg(opengl_include_dir) conf.start_msg('Magnum: Checking for OpenGL lib') - opengl_lib_dir = get_directory('libGL.'+suffix, libs_check) + opengl_lib_dir = get_directory('libOpenGL.'+suffix, libs_check) magnum_libpaths = magnum_libpaths + [opengl_lib_dir] - magnum_libs = magnum_libs + ['GL'] - conf.end_msg(['GL']) + magnum_libs = magnum_libs + ['OpenGL'] + conf.end_msg(['OpenGL']) conf.start_msg('Magnum: Checking for MagnumGL lib') gl_lib_dir = get_directory('libMagnumGL.'+suffix, libs_check) @@ -232,6 +236,50 @@ def fatal(required, msg): fatal(required, 'At the moment only desktop OpenGL is supported by WAF') return + egl_found = False + glx_found = False + if 'TARGET_HEADLESS' in magnum_config or 'TARGET_EGL' in magnum_config: + # TARGET_HEADLESS requires EGL + egl_inc = get_directory('EGL/egl.h', includes_check) + + magnum_includes = magnum_includes + [egl_inc] + + libs_egl = ['EGL'] + for lib_egl in libs_egl: + try: + lib_dir = get_directory('lib'+lib_egl+'.so', libs_check) + egl_found = True + + magnum_libpaths = magnum_libpaths + [lib_dir] + magnum_libs.append(lib_egl) + break + except: + egl_found = False + + if not egl_found: + fatal(required, 'Not found') + return + else: # we need GLX + glx_inc = get_directory('GL/glx.h', includes_check) + + magnum_includes = magnum_includes + [glx_inc] + + libs_glx = ['GLX', 'X11'] + for lib_glx in libs_glx: + try: + lib_dir = get_directory('lib'+lib_glx+'.so', libs_check) + glx_found = True + + magnum_libpaths = magnum_libpaths + [lib_dir] + magnum_libs.append(lib_glx) + # break + except: + glx_found = False + + if not glx_found: + fatal(required, 'Not found') + return + conf.start_msg('Checking for Magnum components') # only check for components that can exist requested_components = list(set(requested_components).intersection(magnum_components)) @@ -293,6 +341,7 @@ def fatal(required, msg): try: lib_dir = get_directory('lib'+lib_glfw+'.'+suffix, libs_check) glfw_found = True + magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] magnum_component_libs[component].append(lib_glfw) break @@ -301,12 +350,17 @@ def fatal(required, msg): # GlfwApplication needs the libdl.so library (except on mac) if conf.env['DEST_OS'] != 'darwin': - try: - lib_dir = get_directory('libdl.'+suffix, libs_check) - magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] - magnum_component_libs[component].append('dl') - except: - glfw_found = False + libdl_libs = ['libdl.'+suffix, 'libdl.'+suffix+'.2'] + for libdl_lib in libdl_libs: + try: + lib_dir = get_directory(libdl_lib, libs_check) + magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] + magnum_component_libs[component].append('dl') + + glfw_found = True + break + except: + glfw_found = False if not glfw_found: fatal(required, 'Not found') @@ -343,58 +397,63 @@ def fatal(required, msg): magnum_component_libpaths[component] = magnum_component_libpaths[component] + conf.env['LIBPATH_MAGNUM_SDL'] magnum_component_libs[component] = magnum_component_libs[component] + conf.env['LIB_MAGNUM_SDL'] # Sdl2Application needs the libdl.so library - try: - lib_dir = get_directory('libdl.'+suffix, libs_check) - magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] - magnum_component_libs[component].append('dl') - except: - fatal(required, 'Not found') - return + if conf.env['DEST_OS'] != 'darwin': + libdl_libs = ['libdl.'+suffix, 'libdl.'+suffix+'.2'] + for libdl_lib in libdl_libs: + try: + lib_dir = get_directory(libdl_lib, libs_check) + magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] + magnum_component_libs[component].append('dl') + except: + fatal(required, 'Not found') + return # to-do: maybe copy flags? elif component == 'WindowlessEglApplication': - # WindowlessEglApplication requires EGL - egl_inc = get_directory('EGL/egl.h', includes_check) - - magnum_component_includes[component] = magnum_component_includes[component] + [egl_inc] - - libs_egl = ['EGL'] - egl_found = False - for lib_egl in libs_egl: - try: - lib_dir = get_directory('lib'+lib_egl+'.so', libs_check) - egl_found = True - - magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] - magnum_component_libs[component].append(lib_egl) - break - except: - egl_found = False - if not egl_found: - fatal(required, 'Not found') - return + # WindowlessEglApplication requires EGL + egl_inc = get_directory('EGL/egl.h', includes_check) + + magnum_component_includes[component] = magnum_component_includes[component] + [egl_inc] + + libs_egl = ['EGL'] + egl_found = False + for lib_egl in libs_egl: + try: + lib_dir = get_directory('lib'+lib_egl+'.so', libs_check) + egl_found = True + + magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] + magnum_component_libs[component].append(lib_egl) + break + except: + egl_found = False + + if not egl_found: + fatal(required, 'Not found') + return elif component == 'WindowlessGlxApplication' or component == 'GlxApplication': - # [Windowless]GlxApplication requires GLX. X11 - glx_inc = get_directory('GL/glx.h', includes_check) - - magnum_component_includes[component] = magnum_component_includes[component] + [glx_inc] - - libs_glx = ['GLX', 'X11'] - glx_found = False - for lib_glx in libs_glx: - try: - lib_dir = get_directory('lib'+lib_glx+'.so', libs_check) - glx_found = True - - magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] - magnum_component_libs[component].append(lib_glx) - # break - except: - glx_found = False - if not glx_found: - fatal(required, 'Not found') - return + # [Windowless]GlxApplication requires GLX. X11 + glx_inc = get_directory('GL/glx.h', includes_check) + + magnum_component_includes[component] = magnum_component_includes[component] + [glx_inc] + + libs_glx = ['GLX', 'X11'] + glx_found = False + for lib_glx in libs_glx: + try: + lib_dir = get_directory('lib'+lib_glx+'.so', libs_check) + glx_found = True + + magnum_component_libpaths[component] = magnum_component_libpaths[component] + [lib_dir] + magnum_component_libs[component].append(lib_glx) + # break + except: + glx_found = False + + if not glx_found: + fatal(required, 'Not found') + return elif component not in ['WindowlessCglApplication', 'WindowlessWglApplication']: # to-do: support all other applications msg = 'Component ' + component + ' is not yet supported by WAF' diff --git a/wscript b/wscript index 00a709a1..1b497d63 100644 --- a/wscript +++ b/wscript @@ -71,6 +71,17 @@ def configure(conf): conf.msg("Build/install RobotDart", "no", color="YELLOW") conf.msg("Install Utheque (URDF library)", "yes") +def test_filesystem(bld, experimental = False): + fl_node = bld.srcnode.make_node('fl.cpp') + fl_node.parent.mkdir() + lflags = [] + if experimental: + fl_node.write('#include \nint main(void) { return 0;}\n', 'w') + lflags = ['-lstdc++fs'] + else: + fl_node.write('#include \nint main(void) { return 0;}\n', 'w') + bld(features='cxx cxxprogram', source=[fl_node], linkflags=lflags, cxxflags=['-std=c++17'], target='fl') + def configure_robot_dart(conf): conf.get_env()['BUILD_GRAPHIC'] = False @@ -89,17 +100,18 @@ def configure_robot_dart(conf): conf.load('python') conf.load('pybind') - conf.check_boost(lib='regex system filesystem unit_test_framework', min_version='1.58') # we need pthread for video saving conf.check(features='cxx cxxprogram', lib=['pthread'], uselib_store='PTHREAD') conf.check_eigen(required=True, min_version=(3,2,92)) conf.check_dart(required=True) + if conf.env['DART_REQUIRES_BOOST']: + conf.check_boost(lib='regex system filesystem unit_test_framework', min_version='1.58') conf.check_corrade(components='Utility PluginManager', required=False) conf.env['magnum_dep_libs'] = 'MeshTools Primitives Shaders SceneGraph GlfwApplication Text MagnumFont' if conf.env['DEST_OS'] == 'darwin': conf.env['magnum_dep_libs'] += ' WindowlessCglApplication' else: - conf.env['magnum_dep_libs'] += ' WindowlessGlxApplication' + conf.env['magnum_dep_libs'] += ' WindowlessEglApplication' if len(conf.env.INCLUDES_Corrade): conf.check_magnum(components=conf.env['magnum_dep_libs'], required=False) if len(conf.env.INCLUDES_Magnum): @@ -138,19 +150,20 @@ def configure_robot_dart(conf): if conf.options.build_shared: conf.env['lib_type'] = 'cxxshlib' + # We require C++17 if conf.env.CXX_NAME in ["icc", "icpc"]: - common_flags = "-Wall -std=c++11" + common_flags = "-Wall -std=c++17" opt_flags = " -O3 -xHost -unroll -g " + native_icc elif conf.env.CXX_NAME in ["clang"]: - common_flags = "-Wall -std=c++11" + common_flags = "-Wall -std=c++17" # no-stack-check required for Catalina opt_flags = " -O3 -g -faligned-new -fno-stack-check -Wno-narrowing" + native else: gcc_version = int(conf.env['CC_VERSION'][0]+conf.env['CC_VERSION'][1]) - if gcc_version < 47: - common_flags = "-Wall -std=c++0x" + if gcc_version < 50: + conf.fatal('We need C++17 features. Your compiler does not support them!') else: - common_flags = "-Wall -std=c++11" + common_flags = "-Wall -std=c++17" opt_flags = " -O3 -g" + native if gcc_version >= 71: opt_flags = opt_flags + " -faligned-new" @@ -158,6 +171,15 @@ def configure_robot_dart(conf): if (not conf.options.build_shared) and (not conf.options.no_pic): common_flags += ' -fPIC' + has_filesystem = conf.check(build_fun=test_filesystem, msg='Checking support for ', mandatory=False) + has_experimental_filesystem = None + if has_filesystem is None: + has_experimental_filesystem = conf.check(build_fun=lambda c : test_filesystem(c, True), msg='Checking support for ', mandatory=False) + + if has_filesystem is None and has_experimental_filesystem is None: + conf.fatal('We need std::filesystem or std::experimental::filesystem') + elif has_filesystem is None: + conf.env.LIB_CPPFS = ['stdc++fs'] all_flags = common_flags + conf.env['py_flags'] + opt_flags conf.env['CXXFLAGS'] = conf.env['CXXFLAGS'] + all_flags.split(' ') @@ -167,13 +189,8 @@ def configure_robot_dart(conf): conf.env['PUBLIC_CXXFLAGS'] = ("-faligned-new -fno-stack-check" + native).split(' ') else: conf.env['PUBLIC_CXXFLAGS'] = ("-faligned-new" + native).split(' ') - - if len(conf.env.CXXFLAGS_DART) > 0: - if '-std=c++11' in conf.env['CXXFLAGS']: - conf.env['CXXFLAGS'].remove('-std=c++11') - if '-std=c++0x' in conf.env['CXXFLAGS']: - conf.env['CXXFLAGS'].remove('-std=c++0x') - conf.env['CXXFLAGS'] = conf.env['CXXFLAGS'] + conf.env.CXXFLAGS_DART + # We require C++17 + conf.env['PUBLIC_CXXFLAGS'] += ['-std=c++17'] # add strict flags for warnings corrade.corrade_enable_pedantic_flags(conf) @@ -216,11 +233,17 @@ def build_utheque(bld): cwd=bld.path.find_dir('src/utheque/'), relative_trick=True) #### CMake + cxx_flags = ''.join(x + ';' for x in bld.env['PUBLIC_CXXFLAGS']) + cmake_deps = '' + if 'LIB_CPPFS' in bld.env and len(bld.env.LIB_CPPFS) > 0: + cmake_deps = '\nINTERFACE_LINK_LIBRARIES "stdc++fs"' with open('cmake/UthequeConfig.cmake.in') as f: newText=f.read() \ - .replace('@Utheque_INCLUDE_DIRS@', prefix + "/include")\ - .replace('@Utheque_CMAKE_MODULE_PATH@', prefix + "/lib/cmake/Utheque/")\ - .replace('@Utheque_PREFIX@', "UTHEQUE_PREFIX=\"" + prefix + "\"") + .replace('@Utheque_INCLUDE_DIRS@', prefix + "/include") \ + .replace('@Utheque_CMAKE_MODULE_PATH@', prefix + "/lib/cmake/Utheque/") \ + .replace('@Utheque_PREFIX@', "UTHEQUE_PREFIX=\"" + prefix + "\"") \ + .replace('@Utheque_CXX_FLAGS@', cxx_flags) \ + .replace('@Utheque_DEPS@', cmake_deps) with open(blddir + '/UthequeConfig.cmake', "w") as f: f.write(newText) @@ -236,7 +259,7 @@ def build_utheque(bld): def build_robot_dart(bld): prefix = bld.get_env()['PREFIX'] - if len(bld.env.INCLUDES_DART) == 0 or len(bld.env.INCLUDES_EIGEN) == 0 or len(bld.env.INCLUDES_BOOST) == 0: + if len(bld.env.INCLUDES_DART) == 0 or len(bld.env.INCLUDES_EIGEN) == 0 or (bld.env['DART_REQUIRES_BOOST'] and len(bld.env.INCLUDES_BOOST) == 0): bld.fatal('Some libraries were not found! Cannot proceed!') if bld.options.tests: @@ -259,8 +282,9 @@ def build_robot_dart(bld): magnum_files = [f[len(bld.path.abspath())+1:] for f in magnum_files] robot_dart_magnum_srcs = " ".join(magnum_files) - libs = 'BOOST EIGEN DART PTHREAD' + libs = 'BOOST EIGEN DART PTHREAD CPPFS' defines = ["ROBOT_DART_PREFIX=\"" + bld.env['PREFIX'] + "\""] + defines += ["UTHEQUE_PREFIX=\"" + bld.env['PREFIX'] + "\""] bld.program(features = 'cxx ' + bld.env['lib_type'], source = robot_dart_srcs, @@ -312,6 +336,10 @@ def build_robot_dart(bld): py_files = [f[len(bld.path.abspath())+1:] for f in py_files] py_srcs = " ".join(py_files) + # Read suffix to be sure! Do not rely on waf! + if len(bld.env['PYTHON_CONFIG']) > 0 and len(bld.env['PYTHON_CONFIG'][0]) > 0: + py_suffix = bld.cmd_and_log('%s --extension-suffix' % bld.env['PYTHON_CONFIG'][0], quiet=True)[:-1] # ignore end of line! + bld.env['pyext_PATTERN'] = "%s" + py_suffix bld.program(features = 'c cshlib pyext', source = './src/python/robot_dart.cc ' + py_srcs, includes = './src', @@ -361,6 +389,9 @@ def build_robot_dart(bld): bld.install_files('${PREFIX}/lib', blddir + '/libRobotDARTMagnum.' + suffix) #### installation of the cmake config (waf install) + cmake_deps = '' + if 'LIB_CPPFS' in bld.env and len(bld.env.LIB_CPPFS) > 0: + cmake_deps = ';stdc++fs' # CMAKE config with open('cmake/RobotDARTConfig.cmake.in') as f: magnum_dep_libs = bld.get_env()['magnum_dep_libs'] @@ -392,7 +423,8 @@ def build_robot_dart(bld): .replace('@RobotDART_MAGNUM_DEP_LIBS@', magnum_dep_libs) \ .replace('@RobotDART_MAGNUM_DEFINITIONS@', defines_magnum) \ .replace('@RobotDART_MAGNUM_LIBS@', magnum_libs) \ - .replace('@RobotDART_CMAKE_MODULE_PATH@', prefix + "/lib/cmake/RobotDART/") + .replace('@RobotDART_CMAKE_MODULE_PATH@', prefix + "/lib/cmake/RobotDART/") \ + .replace('@RobotDART_EXTRA_LIBS@', cmake_deps) with open(blddir + '/RobotDARTConfig.cmake', "w") as f: f.write(newText) # CMAKE configVersion @@ -404,14 +436,14 @@ def build_robot_dart(bld): bld.install_files('${PREFIX}/lib/cmake/RobotDART/', blddir + '/RobotDARTConfig.cmake') bld.install_files('${PREFIX}/lib/cmake/RobotDART/', blddir + '/RobotDARTConfigVersion.cmake') bld.install_files('${PREFIX}/lib/cmake/RobotDART/', 'cmake/FindGLFW.cmake') + bld.install_files('${PREFIX}/lib/cmake/RobotDART/', 'cmake/FindEGL.cmake') def build_examples(bld): # we first build the library build(bld) print("Bulding examples...") - libs = 'BOOST EIGEN DART PTHREAD' + libs = 'BOOST EIGEN DART PTHREAD CPPFS' path = bld.path.abspath() + '/res' - bld.env.LIB_PTHREAD = ['pthread'] # these examples should not be compiled without magnum magnum_only = ['magnum_contexts.cpp', 'cameras.cpp', 'transparent.cpp', 'graphics_tutorial.cpp', 'sensors_tutorial.cpp']