Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create autoware_auto_msgs_adapter node #3876

Merged
merged 28 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a0878b3
feat: create autoware_auto_msgs_adapter node
Jun 5, 2023
b4a2ddb
test wip
Jun 5, 2023
97ad36b
context is already init
Jun 5, 2023
14ab27b
make it modular
Jun 12, 2023
cac08e4
style(pre-commit): autofix
pre-commit-ci[bot] Jun 12, 2023
1bcb59b
create the test for ackerman control command
Jun 12, 2023
052dfe5
add missing header
Jun 12, 2023
5db44ab
use RCLCPP_SHARED_PTR_DEFINITIONS
Jun 13, 2023
19b5188
move the virtual destructor to the base class
Jun 13, 2023
8e2881a
make members private
Jun 13, 2023
25fa0f1
remove unnecessary explicit
Jun 13, 2023
a4e98e0
refactor SharedPtrInterface to just SharedPtr for the base interface …
Jun 13, 2023
f90c0b7
use static_pointer_cast
Jun 13, 2023
a3f9ff9
const vars
Jun 13, 2023
5c2cc5d
add readme
Jun 14, 2023
86b5914
style(pre-commit): autofix
pre-commit-ci[bot] Jun 14, 2023
40ed42e
fix header/library visibility and directories
Jun 19, 2023
14fa392
style(pre-commit): autofix
pre-commit-ci[bot] Jun 19, 2023
66edca2
use slash instead, fix test name
Jun 19, 2023
4ba25b3
move to system directory
Jun 19, 2023
38a4085
rewrite parameter management
Jun 19, 2023
8de3079
style(pre-commit): autofix
pre-commit-ci[bot] Jun 19, 2023
2c5a965
remove redundant target_include_directories
Jun 19, 2023
d29afb6
put headers back in include/autoware_auto_msgs_adapter/*
Jun 19, 2023
14ce34f
style(pre-commit): autofix
pre-commit-ci[bot] Jun 19, 2023
361dea5
add missing header
Jun 19, 2023
6f2319e
reorganize header paths
Jun 19, 2023
9e4e50d
style(pre-commit): autofix
pre-commit-ci[bot] Jun 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions system/autoware_auto_msgs_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.14)
project(autoware_auto_msgs_adapter)

find_package(autoware_cmake REQUIRED)
autoware_package()

set(NODE_NAME ${PROJECT_NAME}_node)
set(EXEC_NAME ${PROJECT_NAME}_exe)
set(TEST_NAME test_${PROJECT_NAME})

ament_auto_add_library(${NODE_NAME}
src/include/adapter_base.hpp
src/include/adapter_base_interface.hpp
src/include/adapter_control.hpp
src/include/autoware_auto_msgs_adapter_core.hpp
src/autoware_auto_msgs_adapter_core.cpp)

rclcpp_components_register_node(${NODE_NAME}
PLUGIN "autoware_auto_msgs_adapter::AutowareAutoMsgsAdapterNode"
EXECUTABLE ${EXEC_NAME})

if(BUILD_TESTING)
file(GLOB_RECURSE TEST_SOURCES test/*.cpp)
ament_add_ros_isolated_gtest(${TEST_NAME} ${TEST_SOURCES})
target_include_directories(${TEST_NAME} PRIVATE src/include)
target_link_libraries(${TEST_NAME} ${NODE_NAME})
endif()

ament_auto_package(INSTALL_TO_SHARE
launch
config)
102 changes: 102 additions & 0 deletions system/autoware_auto_msgs_adapter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# autoware_auto_msgs_adapter

This package is used to convert `autoware_msgs` to `autoware_auto_msgs`.

## Purpose

As we transition from `autoware_auto_msgs` to `autoware_msgs`, we wanted to provide flexibility and compatibility for
users who are still using `autoware_auto_msgs`.

This adapter package allows users to easily convert messages between the two formats.

## Capabilities

The `autoware_auto_msgs_adapter` package provides the following capabilities:

- Conversion of supported `autoware_msgs` messages to `autoware_auto_msgs` messages.
- Can be extended to support conversion for any message type pairs.
- Each instance is designed to convert from a single source message type to a single target message type.
- Multiple instances can be launched to convert multiple message types.
- Can be launched as a standalone node or as a component.

## Usage

Customize the adapter configuration by replicating and editing the `adapter_control.param.yaml` file located
in the `autoware_auto_msgs_adapter/config` directory. Example configuration:

```yaml
/**:
ros__parameters:
msg_type_target: "autoware_auto_control_msgs/msg/AckermannControlCommand"
topic_name_source: "/control/command/control_cmd"
topic_name_target: "/control/command/control_cmd_auto"
```

Set the `msg_type_target` parameter to the desired target message type from `autoware_auto_msgs`.

Make sure that the `msg_type_target` has the correspondence in either:

- [schema/autoware_auto_msgs_adapter.schema.json](schema/autoware_auto_msgs_adapter.schema.json)
- OR [src/autoware_auto_msgs_adapter_core.cpp](src/autoware_auto_msgs_adapter_core.cpp) `AutowareAutoMsgsAdapterNode::create_adapter_map()` method.

(If this package is maintained correctly, they should match each other.)

Launch the adapter node by any of the following methods:

### `ros2 launch`

```bash
ros2 launch autoware_auto_msgs_adapter autoware_auto_msgs_adapter.launch.xml param_path:='full_path_to_param_file'
```

Make sure to set the `param_path` argument to the full path of the parameter file.

Alternatively,

- You can replicate and edit the launch file to suit to your needs.
- You can make use of the existing launch file in another launch file by providing the parameter file path as an
argument.

### `ros2 run`

```bash
ros2 run autoware_auto_msgs_adapter autoware_auto_msgs_adapter_exe --ros-args --params-file 'full_path_to_param_file'
```

Make sure to set the `param_path` argument to the full path of the parameter file.

## Contributing

### Current implementation details

The entry point for the adapter executable is created with `RCLCPP_COMPONENTS_REGISTER_NODE` the [autoware_auto_msgs_adapter_core.cpp](src/Fautoware_auto_msgs_adapter_core.cpp).

This allows it to be launched as a component or as a standalone node.

In the `AutowareAutoMsgsAdapterNode` constructor, the adapter is selected by the type string provided in the
configuration file. The adapter is then initialized with the topic names provided.

The constructors of the adapters are responsible for creating the publisher and subscriber (which makes use of the conversion method).

### Adding a new message pair

To add a new message pair,

- Replicate and edit:
- [adapter_control.hpp](include/autoware_auto_msgs_adapter/adapter_control.hpp).
- Add the new header file to the [CMakeLists.txt](CMakeLists.txt).
- Add a new entry to the returned map instance in the `AutowareAutoMsgsAdapterNode::create_adapter_map()` method of the adapter node:
- [autoware_auto_msgs_adapter_core.cpp](src/autoware_auto_msgs_adapter_core.cpp)
- Add a new entry to the [schema/autoware_auto_msgs_adapter.schema.json](schema/autoware_auto_msgs_adapter.schema.json) file in the `definitions:autoware_auto_msgs_adapter:properties:msg_type_target:enum` section.
- Learn more about JSON schema usage in [here](https://autowarefoundation.github.io/autoware-documentation/main/contributing/coding-guidelines/ros-nodes/parameters/#json-schema).
- Create a new config file by replicating and editing:
- [adapter_control.param.yaml](config/adapter_control.param.yaml)
- Add a new test file by replicating and editing:
- [test_msg_ackermann_control_command.cpp](test/test_msg_ackermann_control_command.cpp)
- No need to edit the `CMakeLists.txt` file as it will automatically detect the new test file.

Also make sure to test the new adapter with:

```bash
colcon test --event-handlers console_cohesion+ --packages-select autoware_auto_msgs_adapter
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**:
ros__parameters:
msg_type_target: "autoware_auto_control_msgs/msg/AckermannControlCommand"
topic_name_source: "/control/command/control_cmd"
topic_name_target: "/control/command/control_cmd_auto"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="param_path" default="$(find-pkg-share autoware_auto_msgs_adapter)/config/adapter_control.param.yaml"/>

<node pkg="autoware_auto_msgs_adapter" exec="autoware_auto_msgs_adapter_exe" name="autoware_auto_msgs_adapter" output="screen">
<param from="$(var param_path)"/>
</node>
</launch>
27 changes: 27 additions & 0 deletions system/autoware_auto_msgs_adapter/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>autoware_auto_msgs_adapter</name>
<version>1.0.0</version>
<description>Converts an autoware_msgs message to autoware_auto_msgs version and publishes it.</description>
<maintainer email="mfc@leodrive.ai">M. Fatih Cırıt</maintainer>
<license>Apache License 2.0</license>

<buildtool_depend>ament_cmake_auto</buildtool_depend>
<buildtool_depend>autoware_cmake</buildtool_depend>

<build_depend>rosidl_default_generators</build_depend>

<test_depend>ament_cmake_ros</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>autoware_lint_common</test_depend>

<depend>autoware_auto_control_msgs</depend>
<depend>autoware_control_msgs</depend>
<depend>rclcpp</depend>
<depend>rclcpp_components</depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Parameters for autoware_auto_msg_adapter",
"type": "object",
"definitions": {
"autoware_auto_msgs_adapter": {
"type": "object",
"properties": {
"msg_type_target": {
"type": "string",
"description": "Target message type",
"enum": ["autoware_auto_control_msgs/msg/AckermannControlCommand"],
"default": "autoware_auto_control_msgs/msg/AckermannControlCommand"
},
"topic_name_source": {
"type": "string",
"description": "Topic name of the message to be converted.",
"default": "/control/command/control_cmd"
},
"topic_name_target": {
"type": "string",
"description": "Target topic name which the message will be converted into.",
"default": "/control/command/control_cmd_auto"
}
},
"required": ["msg_type_target", "topic_name_source", "topic_name_target"]
}
},
"properties": {
"/**": {
"type": "object",
"properties": {
"ros__parameters": {
"$ref": "#/definitions/autoware_auto_msgs_adapter"
}
},
"required": ["ros__parameters"]
}
},
"required": ["/**"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2023 The Autoware Foundation
//
// 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.

#include "include/autoware_auto_msgs_adapter_core.hpp"

#include "include/adapter_control.hpp"

#include <rclcpp/rclcpp.hpp>

#include <map>

namespace autoware_auto_msgs_adapter
{

using autoware_auto_control_msgs::msg::AckermannControlCommand;
using autoware_control_msgs::msg::Control;

using MapStringAdapter = AutowareAutoMsgsAdapterNode::MapStringAdapter;

AutowareAutoMsgsAdapterNode::AutowareAutoMsgsAdapterNode(const rclcpp::NodeOptions & node_options)
: rclcpp::Node("autoware_auto_msgs_adapter", node_options)
{
const std::string msg_type_target = declare_parameter<std::string>("msg_type_target");
const std::string topic_name_source = declare_parameter<std::string>("topic_name_source");
const std::string topic_name_target = declare_parameter<std::string>("topic_name_target");

// Map of available adapters
auto map_adapter = create_adapter_map(topic_name_source, topic_name_target);

print_adapter_options(map_adapter);

// Initialize the adapter with the selected option
if (!initialize_adapter(map_adapter, msg_type_target)) {
RCLCPP_ERROR(
get_logger(), "Unknown msg type: %s. Please refer to previous log for available options.",
msg_type_target.c_str());
}
}

MapStringAdapter AutowareAutoMsgsAdapterNode::create_adapter_map(
const std::string & topic_name_source, const std::string & topic_name_target)
{
return {
{"autoware_auto_control_msgs/msg/AckermannControlCommand",
[&] {
return std::static_pointer_cast<AdapterBaseInterface>(
std::make_shared<AdapterControl>(*this, topic_name_source, topic_name_target));
}},
};
}

void AutowareAutoMsgsAdapterNode::print_adapter_options(const MapStringAdapter & map_adapter)
{
std::string std_options_available;
for (const auto & entry : map_adapter) {
std_options_available += entry.first + "\n";
}
RCLCPP_INFO(
get_logger(), "Available msg_type_target options:\n%s", std_options_available.c_str());
}

bool AutowareAutoMsgsAdapterNode::initialize_adapter(
const MapStringAdapter & map_adapter, const std::string & msg_type_target)
{
auto it = map_adapter.find(msg_type_target);
adapter_ = (it != map_adapter.end()) ? it->second() : nullptr;
return adapter_ != nullptr;
}

} // namespace autoware_auto_msgs_adapter

#include <rclcpp_components/register_node_macro.hpp>
RCLCPP_COMPONENTS_REGISTER_NODE(autoware_auto_msgs_adapter::AutowareAutoMsgsAdapterNode)
57 changes: 57 additions & 0 deletions system/autoware_auto_msgs_adapter/src/include/adapter_base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2023 The Autoware Foundation
//
// 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 ADAPTER_BASE_HPP_
#define ADAPTER_BASE_HPP_

#include "adapter_base_interface.hpp"

#include <rclcpp/rclcpp.hpp>

#include <memory>
#include <string>

namespace autoware_auto_msgs_adapter
{

template <typename SourceT, typename TargetT>
class AdapterBase : public AdapterBaseInterface
{
public:
RCLCPP_SHARED_PTR_DEFINITIONS(AdapterBase<SourceT, TargetT>)

AdapterBase(
rclcpp::Node & node, const std::string & topic_name_source,
const std::string & topic_name_target, const rclcpp::QoS & qos = rclcpp::QoS{1})
{
pub_target_ = node.create_publisher<TargetT>(topic_name_target, qos);
sub_source_ = node.create_subscription<SourceT>(
topic_name_source, qos, std::bind(&AdapterBase::callback, this, std::placeholders::_1));
}

protected:
virtual TargetT convert(const SourceT & msg_source) = 0;

private:
typename rclcpp::Publisher<TargetT>::SharedPtr pub_target_;
typename rclcpp::Subscription<SourceT>::SharedPtr sub_source_;

void callback(const typename SourceT::SharedPtr msg_source)
{
pub_target_->publish(convert(*msg_source));
}
};

} // namespace autoware_auto_msgs_adapter

#endif // ADAPTER_BASE_HPP_
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 The Autoware Foundation
//
// 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 ADAPTER_BASE_INTERFACE_HPP_
#define ADAPTER_BASE_INTERFACE_HPP_

#include <rclcpp/rclcpp.hpp>

#include <memory>

namespace autoware_auto_msgs_adapter
{

class AdapterBaseInterface
{
public:
RCLCPP_SHARED_PTR_DEFINITIONS(AdapterBaseInterface)

virtual ~AdapterBaseInterface() = default;
};

} // namespace autoware_auto_msgs_adapter

#endif // ADAPTER_BASE_INTERFACE_HPP_
Loading