8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ROS2における共有ライブラリ

Last updated at Posted at 2020-06-29

ROS2関係トップページへ

【次:ROS2の共有ライブラリを使用したプログラムの作成

Eloquentまではこちら
ROS2における共有ライブラリ:--library-nodeオプションを使用しない方法はこちら
更新履歴:
2021/08/27:--library-nameオプションを使ったやり方に変更


ROS2の共有ライブラリを作成する.

共有ライブラリはクラスで作成するので,これまでのようにROS1風のものはない.
また,共有ライブラリは色々なところで使用されるのでnamespaceを用いている.
本当はこれまででもnamespaceを使用した方がよかったのだが,自分が使用するターゲットのみの場合必須でないので省略してきた.
namespaceに関してはROS2関係トップページへの「知っといてほしい知識」などを参考に.

共通ライブラリ概要

ここで作成する共有ライブラリの概要は以下のとおり.
ちなみに作成したライブラリを使用したターゲットはここで作成せず共有ライブラリのみの作成とする.
また作成するクラスは一つでも良かったが,後々のために二つ作成する(MinimalCompNode1, MinimalCompNode2).基本的には一つのライブラリに複数の機能が収められる.
一つ目(MinimalCompNode1)を作成し,二つ目(MinimalCompNode2)は後ほど追加することで,追加方法も述べる.

  • 共有ライブラリのパッケージ名
    • minimal_comp
  • 共有ライブラリ名
    • minimal_comp_node
  • 共有ライブラリで使用できる機能・クラスを収めたソースファイル
    • minimal_comp_node1.hppと.cpp
      • クラス名:MinimalCompNode1
    • minimal_comp_node2.hppと.cpp
      • クラス名:MinimalCompNode2
  • パッケージ共通のnamespace
    • minimal_comp

準備

terminal
$ cd ~/ros2_studies_ws/
$ ros2 pkg create minimal_comp --dependencies rclcpp --library-name minimal_comp_node1

共有ライブラリ

対象ファイル

  • include/visibility_control.h
  • include/minimal_comp_node1.hpp
  • src/minimal_comp_node1.cpp
  • CMakeLists.txt
  • package.xml

後で追加

  • include/minimal_comp_node2.hpp
  • src/minimal_comp_node2.cpp

--library-name オプションを使用しない場合,visibility_control.hが自動的に作成されない.そのため以下の手順が必要となる.

手動での共有ライブラリ作成

共有ライブラリ独特の手順

  1. visibility.hを作成する
    • 公式からDLして自分のパッケージ用にアレンジするのが楽
    • visibility_control.hとして保存
  2. 普通にクラスを作成する
    • 外部に公開するのでsrc/以下にヘッダファイルを置くのではなくinclude/[パッケージ名]/以下にヘッダファイルを置く.

visibility.hの用意

自分で以下のファイルを用意するのでもよいが,公式のexamplesにあるminimal_compositionからvisibility.hをDLして自分用に改変することを推奨.

terminal
$ curl https://raw.githubusercontent.com/ros2/examples/master/rclcpp/composition/minimal_composition/include/minimal_composition/visibility.h > visibility.h
$ sed s/MINIMAL_COMPOSITION/MINIMAL_COMP/g visibility.h > visibility_control.h

一度にやるなら以下のとおり.

terminal
$ curl https://raw.githubusercontent.com/ros2/examples/master/rclcpp/composition/minimal_composition/include/minimal_composition/visibility.h | sed s/MINIMAL_COMPOSITION/MINIMAL_COMP/g > visibility_control.h

今回はパッケージ名がminimal_compであったので上記のようにsedを使用した.ここは自分のパッケージ名に合わせて変更すること.

$ sed s/MINIMAL_COMPOSITION/[自分のパッケージ名]/g visibility.h > my_visibility.h

自分で作成する場合は以下の通り.
ここでもパッケージ名minimal_compで作成しているので,自分のパッケージ名に合わせて適宜変更

visibility.h
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef MINIMAL_COMP__VISIBILITY_H_
#define MINIMAL_COMP__VISIBILITY_H_

#ifdef __cplusplus
extern "C"
{
#endif

// This logic was borrowed (then namespaced) from the examples on the gcc wiki:
//     https://gcc.gnu.org/wiki/Visibility

#if defined _WIN32 || defined __CYGWIN__

  #ifdef __GNUC__
    #define MINIMAL_COMP_EXPORT __attribute__ ((dllexport))
    #define MINIMAL_COMP_IMPORT __attribute__ ((dllimport))
  #else
    #define MINIMAL_COMP_EXPORT __declspec(dllexport)
    #define MINIMAL_COMP_IMPORT __declspec(dllimport)
  #endif

  #ifdef MINIMAL_COMP_DLL
    #define MINIMAL_COMP_PUBLIC MINIMAL_COMP_EXPORT
  #else
    #define MINIMAL_COMP_PUBLIC MINIMAL_COMP_IMPORT
  #endif

  #define MINIMAL_COMP_PUBLIC_TYPE MINIMAL_COMP_PUBLIC

  #define MINIMAL_COMP_LOCAL

#else

  #define MINIMAL_COMP_EXPORT __attribute__ ((visibility("default")))
  #define MINIMAL_COMP_IMPORT

  #if __GNUC__ >= 4
    #define MINIMAL_COMP_PUBLIC __attribute__ ((visibility("default")))
    #define MINIMAL_COMP_LOCAL  __attribute__ ((visibility("hidden")))
  #else
    #define MINIMAL_COMP_PUBLIC
    #define MINIMAL_COMP_LOCAL
  #endif

  #define MINIMAL_COMP_PUBLIC_TYPE
#endif

#ifdef __cplusplus
}
#endif

#endif  // MINIMAL_COMP__VISIBILITY_H_

共有ライブラリ化するMinimalCompNode1

以下のひな形が出来ているので利用して作成.

ソースコード

  • include/minimal_comp_node1.hpp
  • src/minimal_comp_node1.cpp
minimal_comp_node1.hpp
#include <rclcpp/rclcpp.hpp>
#include "visibility_control.h"

namespace minimal_comp {

class MinimalCompNode1 : public rclcpp::Node{
public:
  MINIMAL_COMP_PUBLIC
  MinimalCompNode1(
    const std::string &node_name="",
    const rclcpp::NodeOptions& options=rclcpp::NodeOptions()
  );
};

}

MINIMAL_COMP_PUBLICはWindows用ライブラリを作成するのに必要?Building libraries on Windows参考.

minimal_comp_node1.cpp
#include <rclcpp/rclcpp.hpp>
#include "minimal_comp/minimal_comp_node1.hpp"

namespace minimal_comp {

MinimalCompNode1::MinimalCompNode1(
  const std::string &node_name,
  const rclcpp::NodeOptions& options
): Node("minimal_comp1", node_name, options)
{
  RCLCPP_INFO(this->get_logger(),"minimal comp 1 test");
}

}

package.xmlとCMakeLists.txt

以下は追加した・重要な部分のみ抜粋.
詳しくはament_cmake User Documentationを参照.

package.xml

package.xml
<package format="3">
  <depend>rclcpp</depend>

build_dependタグからdependタグへの変更についてはROS2 package.xmlとCMakeLists.txtのチートシートを参照のこと.

CMakeLists.txt

CMakeLists.txt
find_package(rclcpp REQUIRED)

add_library(minimal_comp_node SHARED
  src/minimal_comp_node1.cpp
)
target_compile_definitions(minimal_comp_node
  PRIVATE "MY_LIBRARY_BUILDING_LIBRARY"
)
target_compile_options(minimal_comp_node PUBLIC -Wall)
ament_target_dependencies(minimal_comp_node
  rclcpp
)
target_include_directories(minimal_comp_node
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

if(NOT WIN32)
  ament_environment_hooks(
    "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}"
  )
endif()

ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(
  rclcpp
)

install(
  DIRECTORY include/
  DESTINATION include
)
install(TARGETS
  minimal_comp_node
  EXPORT export_${PROJECT_NAME}
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

概要

簡単なメッセージを出力するだけのもの
target_compile_definitions(minimal_comp_node PRIVATE "MY_LIBRARY_BUILDING_LIBRARY")はWindows用ライブラリを作成するのに必要?Building libraries on Windowsを参照.

ament_export_*に関するFoxy Fitzroyからの変更について
Eloquent Elusorまでは共有ライブラリのエクスポートに関するコマンドは以下の~~4つ~~3つであった.
  • ament_export_interfaces
  • ament_export_libraries
  • ament_export_inclujde_directories
  • ament_export_dependencies
    • これは必要だった!

これがament_export_targetsの一つになった.使い方としては,ament_export_interfacesの代わりにament_export_targetsを使うような感じらしい.

詳しくは公式のDistributionのニュースのうち,Foxy Fitzroyでの変更:Classic CMake vs. modern CMakeを参照のこと.

共有ライブラリ化するMinimalCompNode2

二つ目は手動で作成してみる.

ソースコード

  • include/minimal_comp_node2.hpp
  • src/minimal_comp_node2.cpp
minimal_comp_node2.hpp
#include <rclcpp/rclcpp.hpp>
#include "visibility_control.h"

namespace minimal_comp {

class MinimalCompNode2 : public rclcpp::Node{
public:
  MINIMAL_COMP_PUBLIC
  MinimalCompNode2(
    const std::string &node_name="",
    const rclcpp::NodeOptions& options=rclcpp::NodeOptions()
  );
};

}
minimal_comp_node2.cpp
#include <rclcpp/rclcpp.hpp>
#include "minimal_comp/minimal_comp_node2.hpp"

namespace minimal_comp {

MinimalCompNode2::MinimalCompNode2(
  const std::string &node_name,
  const rclcpp::NodeOptions& options
): Node("minimal_comp2", node_name, options)
{
  RCLCPP_INFO(this->get_logger(),"minimal comp 2 test");
}

}

CMakeLists.txt

以下は追加した・重要な部分のみ抜粋.
詳しくはament_cmake User Documentationを参照.

CMakeLists.txt

CMakeLists.txt
add_library(minimal_comp_node SHARED
  src/minimal_comp_node1.cpp
  src/minimal_comp_node2.cpp
)

もろもろ

通常のfind_package,ament_target_dependencies以外に以下の要素がある.

  • add_library
  • target_compile_definitions
  • target_compile_options
  • target_include_directories
  • ament_environment_hooks
  • ament_export_interfaces
  • ament_export_dependencies
  • ament_export_libraries
  • ament_export_include_directories
  • install 2種類

説明:add_library

add_executableと同じように他で使用するライブラリ名を付けつつコンパイルに必要なソースファイルを記述.
ライブラリ名を使用するのは以下の要素.

  • target_compile_definitions
  • target_compile_options
  • ament_target_dependencies
  • target_include_directories
  • ament_export_libraries
  • install

説明:target_compile_*

コンパイル時の設定.他でもそのまま使用.

説明:target_include_directories

include/[パッケージ名]/以下のヘッダファイルは外部に公開するものである.他のパッケージはtarget_include_directoriesによって外部公開用のヘッダファイルにアクセスできる.共有ライブラリ自身にとってもinclude/[パッケージ名]/以下にヘッダファイルがあるので(src/以下にはないので),target_include_directoriesを指定する必要がある.

説明:ament_environment_hooks

OS依存の処理っぽい.他でもそのまま使用.

説明:install

最初のinstallは共有ライブラリを使用するパッケージ用にヘッダファイルをインストールするためのコマンド.

install(
  DIRECTORY include/
  DESTINATION include
)

二つ目のinstallは作成したライブラリをインストールするためのコマンド.
特にEXPORTはament_export_interfacesで使うためのもの.
名前はなんでもよいがライブラリ名にexport_を付けたものが用いられる.
理由はament_cmake User DocumentationのBuilding a Libraryを参照のこと.

install(TARGETS
  minimal_comp_node
  EXPORT export_minimal_comp_node
  ARCHIVE DESTINATION lib
  LIBRARY DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

説明:ament_export_targets

ament_export_targetsは,installのEXPORTで指定したものにHAS_LIBRARY_TARGETを.

説明:ament_export_dependencies

共有ライブラリを使う側に依存関係を知らせ,使う側で改めて依存関係処理しなくて済むようにするもの.

ビルド

$ cd ~/ros2_studies_ws/
$ colcon build --symlink-install --packages-up-to minimal_comp
$ . install/setup.bash

複数のライブラリを作成する場合

一つのライブラリの中に複数の機能(クラス)を詰め込むのではなく,複数のライブラリ自体を一つのパッケージで作成する場合.

一つのライブラリのやり方の中で,以下に注目・変更

  • ament_export_targets
  • install

概要

作成したライブラリをインストールするためのinstallにて.

  • TARGETS
    • add_libraryのライブラリ名を複数記述
  • EXPORT
    • この項は全体で一つ.
    • よって,例えばexport_[package名]などに.
  • ament_export_targets
    • EXPORTで名づけしたものを記述
    • よって上記の例ではexport_[package名]

抜粋

CMakeLists.txt
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)

install(TARGETS
  model1
  model2
  EXPORT export_${PROJECT_NAME}
...
)

参考

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?