2b-t / myactuator_rmd

C++ and Python SDK for controlling actuators of the MyActuator RMD-X series, written in C++ with Python bindings
MIT License
15 stars 12 forks source link

Example for including in a C++ project? #1

Closed mdurrani808 closed 8 months ago

mdurrani808 commented 8 months ago

Hello! I was wondering if there were any example projects, or example CmakeLists.txt that show how to use this library. Thanks!

2b-t commented 8 months ago

Hi @mdurrani808 I don't have any examples for it yet. I can write you a quick example though. Plain CMake or ROS 2 Ament? Note though that this library was only tested under Linux as it uses SocketCAN. You might be able though to get it to work on MacOS with one of the community-ports e.g. this one and likely works under WSL in Windows.

The easiest way for testing it is through the Python bindings. For how to use the Python bindings refer to the read-me.

mdurrani808 commented 8 months ago

Plain cmake w/ C++ would be greatly appreciated. I have tested the python bindings and they worked well but my use case now requires C++. Thank you for all of your help and let me know if you need anything from me.

2b-t commented 8 months ago

I just tested it and noticed that I had installed it with an additional myactuator_rmd namespace. I just fixed it in https://github.com/2b-t/myactuator_rmd/commit/c13b35e547e06636fda0b6bfe869bab31c5b0c50, please pull the latest version.

You might either (see here for an example with a similar library):

I would recommend the second version. Here is a small example snippet for the second variant:

#include <iostream>
#include <string>

#include <myactuator_rmd/can/node.hpp>

int main(int argc, char** argv) {
  std::string const ifname {"vcan_test"};
  myactuator_rmd::can::Node node {ifname};
  std::cout << "Ran successfully" << std::endl;
  return EXIT_SUCCESS;
}
cmake_minimum_required(VERSION 3.20)
project(test_myactuator_rmd)

find_package(myactuator_rmd)

add_executable(test_node
  src/main.cpp
)
target_link_libraries(test_node PUBLIC myactuator_rmd::myactuator_rmd)

Let me know if this works for you!

mdurrani808 commented 8 months ago

Getting somewhere... I cloned the latest, made a build directory, ran cmake, make, and make install in WSL2. When going to build refresh the cmake project (I'm using CLion), I get:

CMake Error at /usr/local/share/myactuator_rmd/cmake/ament_cmake_export_dependencies-extras.cmake:5 (find_package):
  By not providing "Findament_cmake_libraries.cmake" in CMAKE_MODULE_PATH
  this project has asked CMake to find a package configuration file provided
  by "ament_cmake_libraries", but CMake did not find one.

  Could not find a package configuration file provided by
  "ament_cmake_libraries" with any of the following names:

    ament_cmake_librariesConfig.cmake
    ament_cmake_libraries-config.cmake

  Add the installation prefix of "ament_cmake_libraries" to CMAKE_PREFIX_PATH
  or set "ament_cmake_libraries_DIR" to a directory containing one of the
  above files.  If "ament_cmake_libraries" provides a separate development
  package or SDK, be sure it has been installed.
Call Stack (most recent call first):
  /usr/local/share/myactuator_rmd/cmake/myactuator_rmdConfig.cmake:41 (include)
  CMakeLists.txt:4 (find_package)

-- Configuring incomplete, errors occurred!

[Failed to reload]

When I go to build the project using

c++ /mnt/c/Users/mdurr/Code/untitled2/main.cpp -o main

I get

/usr/bin/ld: /tmp/cc0Pn8fm.o: in function `main':
main.cpp:(.text+0xe0): undefined reference to `myactuator_rmd::can::Node::Node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::chrono::duration<long, std::ratio<1l, 1000000l> > const&, std::chrono::duration<long, std::ratio<1l, 1000000l> > const&, bool)'
/usr/bin/ld: main.cpp:(.text+0x11c): undefined reference to `myactuator_rmd::can::Node::~Node()'
/usr/bin/ld: main.cpp:(.text+0x16c): undefined reference to `myactuator_rmd::can::Node::~Node()'
collect2: error: ld returned 1 exit status

My C++ file and Cmakelists.txt file matches yours exactly. Any tips? Thanks again.

Its weird that it can't find it, because when running cmake for myactuator_rmd, it seems to find ament_cmake.

cmake .. -D PYTHON_BINDINGS=off -- Found ament_cmake: 1.3.7 (/opt/ros/humble/share/ament_cmake/cmake) -- Ament CMake detected. -- Configuring done (3.6s) -- Generating done (1.1s) -- Build files have been written to: /mnt/c/Users/mdurr/Code/untitled2/myactuator_rmd/build

2b-t commented 8 months ago

Can you recompile the myactuator_rmd package with the following CMakeLists.txt (I removed all references of Ament) and then recompile your package as well to see what happens?

cmake_minimum_required(VERSION 3.20)
project(myactuator_rmd)

option(PYTHON_BINDINGS "Building Python bindings" OFF)
option(BUILD_TESTING "Build unit and integration tests" OFF)
option(SETUP_TEST_IFNAME "Set-up the test VCAN interface automatically" OFF)

if(NOT UNIX)
  message(FATAL_ERROR "Currently this driver only supports Linux!")
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)

include(ConfigExtras.cmake)

include_directories(
  include/
)
add_library(myactuator_rmd SHARED
  src/can/node.cpp
  src/can/utilities.cpp
  src/protocol/requests.cpp
  src/protocol/responses.cpp
  src/driver.cpp
)
set(MYACTUATOR_RMD_LIBRARIES "")
target_link_libraries(myactuator_rmd ${MYACTUATOR_RMD_LIBRARIES})
install(
  DIRECTORY include/
  DESTINATION include/
)
install(TARGETS myactuator_rmd
  EXPORT export_${PROJECT_NAME}
  RUNTIME DESTINATION bin
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
)

if(PYTHON_BINDINGS)
  pybind11_add_module(myactuator_rmd_py
    bindings/myactuator_rmd.cpp
  )
  target_link_libraries(myactuator_rmd_py PUBLIC
    myactuator_rmd
  )

  install(TARGETS myactuator_rmd_py
    DESTINATION ${PYTHON_INSTALL_DIR}/${PROJECT_NAME}
  )
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
  enable_testing()

  find_package(Boost 1.40.0 REQUIRED COMPONENTS program_options)
  add_executable(can_node
    test/can_node.cpp
  )
  target_link_libraries(can_node ${Boost_PROGRAM_OPTIONS_LIBRARY} myactuator_rmd)

  find_package(GTest REQUIRED)
  set(MYACTUATOR_RMD_TEST_LIBRARIES ${MYACTUATOR_RMD_LIBRARIES} myactuator_rmd GTest::gmock GTest::gtest pthread)
  add_executable(run_tests
    test/can/utilities_test.cpp
    test/protocol/requests_test.cpp
    test/protocol/responses_test.cpp
    test/mock/actuator_adaptor.cpp
    test/mock/actuator_mock.cpp
    test/mock/driver_actuator_test.cpp
    test/driver_test.cpp
    test/run_tests.cpp
  )
  target_compile_definitions(run_tests PUBLIC NDEBUG)
  gtest_discover_tests(run_tests
    TEST_SUFFIX .noArgs
    TEST_LIST noArgsTests
  )
  set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10)
  target_link_libraries(run_tests ${MYACTUATOR_RMD_TEST_LIBRARIES})
  if (SETUP_TEST_IFNAME)
    set(VCAN_IFNAME "vcan_test")
    configure_file("CTestCustom.cmake.in" ${CMAKE_BINARY_DIR}/CTestCustom.cmake)
  endif()
endif()
mdurrani808 commented 8 months ago

No more ament cmake errors but still getting the:

/usr/bin/ld: CMakeFiles/RunItBack.dir/main.cpp.o: in function `main':
/mnt/c/Users/mdurr/Code/RunItBack/main.cpp:9: undefined reference to `myactuator_rmd::can::Node::Node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::chrono::duration<long, std::ratio<1l, 1000000l> > const&, std::chrono::duration<long, std::ratio<1l, 1000000l> > const&, bool)'
/usr/bin/ld: /mnt/c/Users/mdurr/Code/RunItBack/main.cpp:12: undefined reference to `myactuator_rmd::can::Node::~Node()'
/usr/bin/ld: /mnt/c/Users/mdurr/Code/RunItBack/main.cpp:12: undefined reference to `myactuator_rmd::can::Node::~Node()'

Thank you for your continued assistance, I appreciate it.

2b-t commented 8 months ago

Ok, I see. Could you send me the output of $ cmake .., $ make and $ sudo make install of myactuator_rmd? It should tell you where the library and headers are installed to.

mdurrani808 commented 8 months ago

Could the clock skew errors be messing things up? A quick google search doesn't lead me to think so but I haven't used cmake as much.

mdurrani@MDXPS139380:/mnt/c/Users/mdurr/Code/RunItBack/myactuator_rmd/build$ cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (5.5s)
-- Generating done (0.3s)
-- Build files have been written to: /mnt/c/Users/mdurr/Code/RunItBack/myactuator_rmd/build
mdurrani@MDXPS139380:/mnt/c/Users/mdurr/Code/RunItBack/myactuator_rmd/build$ make
make: Warning: File 'Makefile' has modification time 5907 s in the future
make[1]: Warning: File 'CMakeFiles/Makefile2' has modification time 5907 s in the future
make[2]: Warning: File 'CMakeFiles/myactuator_rmd.dir/flags.make' has modification time 5906 s in the future
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File 'CMakeFiles/myactuator_rmd.dir/flags.make' has modification time 5906 s in the future
[ 16%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/can/node.cpp.o
[ 33%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/can/utilities.cpp.o
[ 50%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/requests.cpp.o
[ 66%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/protocol/responses.cpp.o
[ 83%] Building CXX object CMakeFiles/myactuator_rmd.dir/src/driver.cpp.o
[100%] Linking CXX shared library libmyactuator_rmd.so
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[100%] Built target myactuator_rmd
make[1]: warning:  Clock skew detected.  Your build may be incomplete.
make: warning:  Clock skew detected.  Your build may be incomplete.
mdurrani@MDXPS139380:/mnt/c/Users/mdurr/Code/RunItBack/myactuator_rmd/build$ sudo make install
[sudo] password for mdurrani:
make: Warning: File 'Makefile' has modification time 5834 s in the future
make[1]: Warning: File 'CMakeFiles/Makefile2' has modification time 5834 s in the future
make[2]: Warning: File 'CMakeFiles/myactuator_rmd.dir/flags.make' has modification time 5834 s in the future
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File 'CMakeFiles/myactuator_rmd.dir/flags.make' has modification time 5833 s in the future
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[100%] Built target myactuator_rmd
make[1]: warning:  Clock skew detected.  Your build may be incomplete.
make[1]: Warning: File 'CMakeFiles/Makefile2' has modification time 5833 s in the future
make[1]: warning:  Clock skew detected.  Your build may be incomplete.
Install the project...
-- Install configuration: ""
-- Up-to-date: /usr/local/include/
-- Installing: /usr/local/include//myactuator_rmd
-- Installing: /usr/local/include//myactuator_rmd/actuator_state
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/acceleration_type.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/baud_rate.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/control_mode.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/error_code.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/feedback.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/gains.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/motor_status_1.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/motor_status_2.hpp
-- Installing: /usr/local/include//myactuator_rmd/actuator_state/motor_status_3.hpp
-- Installing: /usr/local/include//myactuator_rmd/can
-- Installing: /usr/local/include//myactuator_rmd/can/exceptions.hpp
-- Installing: /usr/local/include//myactuator_rmd/can/frame.hpp
-- Installing: /usr/local/include//myactuator_rmd/can/node.hpp
-- Installing: /usr/local/include//myactuator_rmd/can/utilities.hpp
-- Installing: /usr/local/include//myactuator_rmd/driver.hpp
-- Installing: /usr/local/include//myactuator_rmd/exceptions.hpp
-- Installing: /usr/local/include//myactuator_rmd/io.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol
-- Installing: /usr/local/include//myactuator_rmd/protocol/address_offset.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/command_type.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/message.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/node.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/requests.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/responses.hpp
-- Installing: /usr/local/include//myactuator_rmd/protocol/single_motor_message.hpp
-- Installing: /usr/local/include//myactuator_rmd/version.hpp
-- Installing: /usr/local/lib/libmyactuator_rmd.so
make: warning:  Clock skew detected.  Your build may be incomplete.
mdurrani@MDXPS139380:/mnt/c/Users/mdurr/Code/RunItBack/myactuator_rmd/build$ clear
mdurrani808 commented 8 months ago

When making the myactuator_rmd package required, running cmake will give me this error:

C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "export CMAKE_COLOR_DIAGNOSTICS=ON && export CLION_IDE=TRUE && export JETBRAINS_IDE=TRUE && cd /mnt/c/Users/mdurr/Code/RunItBack/cmake-build-debug && /home/mdurrani/.local/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G 'CodeBlocks - Unix Makefiles' -S /mnt/c/Users/mdurr/Code/RunItBack -B /mnt/c/Users/mdurr/Code/RunItBack/cmake-build-debug"
CMake Error at CMakeLists.txt:4 (find_package):
  By not providing "Findmyactuator_rmd.cmake" in CMAKE_MODULE_PATH this
  project has asked CMake to find a package configuration file provided by
  "myactuator_rmd", but CMake did not find one.

  Could not find a package configuration file provided by "myactuator_rmd"
  with any of the following names:

    myactuator_rmdConfig.cmake
    myactuator_rmd-config.cmake

  Add the installation prefix of "myactuator_rmd" to CMAKE_PREFIX_PATH or set
  "myactuator_rmd_DIR" to a directory containing one of the above files.  If
  "myactuator_rmd" provides a separate development package or SDK, be sure it
  has been installed.

-- Configuring incomplete, errors occurred!

[Failed to reload]
2b-t commented 8 months ago

Oh, I see. That was a mistake from my side. Of course the myactuator_rmd package should be required. So the installation did not work correctly.

2b-t commented 8 months ago

I assume the problem you had was caused as follows: You had sourced Ament when performing the installation of myactuator_rmd with CMake but you did not source it when compiling the test_myactuator_rmd package. This results then in a problem with the export macros from Ament that are unknown to CMake (first error). When removing Ament, the CMake Config.cmake file would not be generated (as that part was missing in my CMakeLists.txt) and as a result you could not find the myactuator_rmd package from test_myactuator_rmd (second error).

I implemented some changes that allow CMake to generate the Config.cmake now (similar to other packages such as plotjuggler). Please pull the latest version. The important thing is to install the myactuator_rmd package without having sourced ROS 2 or alternatively just use it inside your ROS 2 workspace without installing it with CMake first. Just do not mix the two.

Let me know if that works for you and feel free to reopen this issue in case this does not work for you.

2b-t commented 8 months ago

If you want to just use this as a ROS 2 package without installing it with CMake a minimal example for the corresponding CMakeLists.txt would be:

cmake_minimum_required(VERSION 3.20)
project(test_myactuator_rmd)

find_package(ament_cmake REQUIRED)
find_package(myactuator_rmd REQUIRED)

add_executable(test_node
  src/main.cpp
)
ament_target_dependencies(test_node myactuator_rmd) 

install(TARGETS test_node
  DESTINATION lib/${PROJECT_NAME}
)

ament_package()
mdurrani808 commented 8 months ago

It works now! Thank you for all of your help and I really appreciate it.

Would it be possible to add that ROS2 example cmakelist.txt to the README? I believe you would have to include it in package.xml as well where its used, or just an example workspace would be really nice. I can make an example repository once I test it out if it works better for you.

2b-t commented 8 months ago

Excellent, glad to hear that.

Yes, indeed, you have to add myactuator_rmd to the package.xml as a dependency as well. I now have such a repository for testing purposes and added a few comments to the main read-me yesterday but I think there is no need to add the ROS 2 example CMakeLists.txt or a full example repository : After all it is pretty standard ROS 2 stuff (see e.g. here) that is not related to this particular package itself and now that we have this issues somebody should be able to find this information also pretty easily in case they struggled with it.

In case you find other things that do not work, feel free to open another issue. I have not had much time to work with my RMD-X8 PRO V2 actuator since writing this library and so any feedback (e.g. if it works well with other actuators from the same series) is much appreciated.