ROS(ROS2) - インタフェース - 基本


 クラウディア


1. 概要
2. 一覧
3. 複数の変数を取得する方法
4. 配列の書き方
5. 定数
6. 備考

1. 概要

 基本的な事柄を記述します。

2. 一覧

 参考サイト、まんま、丸写しします。  下記の型が定義できるようです。  (「DDT」ってなんじゃろか?)
C++ Python DDT  備考 
bool bool builtins.bool boolean
byte uint8_t builtins.bytes* octet
char char builtins.str* char
float32 float builtins.float* float
float64 double builtins.float* double
int8 int8_t builtins.int* octet
uint8 uint8_t builtins.int* octet
int16 int16_t builtins.int* short
uint16 uint16_t builtins.int* unsigned short
int32 int32_t builtins.int* long
uint32 uint32_t builtins.int* unsigned long
int64 int64_t builtins.int* long long
uint64 uint64_t builtins.int* unsigned long long
string std::string builtins.str string
wstring std::u16string builtins.str wstring

 配列。

C++ Python DDT  備考 
static array std::array<T, N> builtins.list* T[N]
unbounded dynamic arraystd::vector builtins.list* sequence
bounded dynamic array custom_class<T, N> builtins.list* sequence<T, N>
bounded string std::string builtins.str* string

3. 複数の変数を取得する方法

 「ros2」のシンプルなソースでは、単純なサービスで、複数の変数を取得する方法が、わからなかったのです。  「.srv」をこんな風に定義しています。

# request fields
uint8 code
---
# response fields
uint8 code
uint8 status
 応答に複数の変数があるわけです。  これを、クライアント側のソースで。

		auto request = std::make_shared<my_interfaces::srv::MyInstruction::Request>();
		request->code = input;

		while (!client->wait_for_service(1s))
		{
			if (!rclcpp::ok())
			{
				RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
				return 0;
			}

			RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
		}

		auto result = client->async_send_request(request);

		// Wait for the result.
		if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS)
		{
			RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "code: 0x%02x  status: %d", result.get()->code, result.get()->status);
		}
		else
		{
			RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service MyInstruction");
		}
 てな感じで、コーディングしてたら、55行でこけます。  どうも、「result.get()->」を複数回呼ぶと、2回目でこけるようです。  「ros」がわかってないというより、「C++」がわかってないと思うのですが。  とりあえず、下記の方法でなんとかなりました。

		auto result = client->async_send_request(request);

		// Wait for the result.
		if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS)
		{
			std::shared_ptr<my_interfaces::srv::MyInstruction_Response_<std::allocator<void> >> myResult = result.get();
			uint8_t code   = myResult->code;
			uint8_t status = myResult->status;

			RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "code: 0x%02x  status: %d", code, status);
		}
		else
		{
			RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service MyInstruction");
		}

4. 配列の書き方

 配列の書き方が、ドキュメントだけでは、理解できなかったのです。  固定長と可変長の配列を。

uint16[4] array1
uint16[]  array2
 てな感じで定義します。  出来上がった、ヘッダファイルを見ると、下記のように記述されていました。

  using _array1_type = std::array<uint16_t, 4>;
  _array1_type array1;
  using _array2_type = std::vector<uint16_t, typename std::allocator_traits<ContainerAllocator>::template rebind_alloc<uint16_t>>;
  _array2_type array2;

5. 定数

 「.srv」に。

uint8 CONST=1
 てな記述をすることで、定数を定義できます。  型によって「=」の後ろの記述も異なります。  「---」より、上に書けば、要求側の定数になりますし、下に書けば、応答側の定数になります。  冒頭の書き方をしたものが、要求側の定数だとして、ソースに記述する場合。  下記のように記述します。  「cpp」

変数 = パッケージ::srv::SRVソース名::Request::CONST
 「python」

変数 = Request.CONST

6. 備考

 本ページは、下記のサイトを参考にさせていただきました。
About ROS 2 interfaces — ROS 2 Documentation: Foxy documentation

AbemaTV 無料体験