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(default_ad_api): add operation mode api #1569

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
23982c2
feat(autoware_ad_api_msgs): define operation mode interface
isamu-takagi Aug 10, 2022
00e7952
feat(default_ad_api): add operation mode api
isamu-takagi Aug 10, 2022
3772e2c
fix: add message
isamu-takagi Aug 10, 2022
10a2c23
Merge branch 'feature/ad-api/operation-mode-interface' into feature/a…
isamu-takagi Aug 10, 2022
c27f603
Update common/autoware_ad_api_msgs/operation_mode/msg/OperationModeSt…
isamu-takagi Aug 11, 2022
3ab7ff0
Update common/autoware_ad_api_msgs/operation_mode/msg/OperationModeSt…
isamu-takagi Aug 11, 2022
325dfab
fix: add message callback
isamu-takagi Aug 12, 2022
053f249
feat: add topic monitoring
isamu-takagi Aug 12, 2022
a2b8233
Merge branch 'feature/ad-api/operation-mode-interface' into feature/a…
isamu-takagi Aug 12, 2022
1c79563
feat: use topic monitoring
isamu-takagi Aug 12, 2022
92a1eb3
feat: modify topic monitoring config
isamu-takagi Aug 15, 2022
4cd3726
fix: config name
isamu-takagi Aug 15, 2022
dc55a9e
feat: modify diag name
isamu-takagi Aug 16, 2022
d81ea85
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Aug 26, 2022
b6939a1
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Sep 1, 2022
fd6fd97
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Sep 6, 2022
9532405
feat: move adapi message
isamu-takagi Sep 21, 2022
c849d6f
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Sep 21, 2022
8112121
Merge branch 'feature/ad-api/operation-mode-interface' into feature/a…
isamu-takagi Sep 21, 2022
871bdc4
feat: change message type
isamu-takagi Sep 21, 2022
d47929b
Merge branch 'feature/ad-api/operation-mode-interface' into feature/a…
isamu-takagi Sep 21, 2022
a5d329e
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Oct 4, 2022
012fe63
Merge branch 'main' into feature/ad-api/operation-mode-interface
isamu-takagi Oct 5, 2022
b4760e6
Merge branch 'feature/ad-api/operation-mode-interface' into feature/a…
isamu-takagi Oct 5, 2022
5ddbd5b
fix: merge
isamu-takagi Oct 5, 2022
b932bac
WIP
isamu-takagi Oct 5, 2022
e76439b
Merge branch 'main' into feature/ad-api/operation-mode
isamu-takagi Oct 6, 2022
cee50d2
fix: fix build error
isamu-takagi Oct 7, 2022
f3885fb
feat: move diagnostics
isamu-takagi Oct 18, 2022
7ef40f8
Merge branch 'main' into feature/ad-api/operation-mode
isamu-takagi Nov 8, 2022
3e0e5b1
feat: remove diagnostics
isamu-takagi Nov 8, 2022
bfe1b38
Merge branch 'main' into feature/ad-api/operation-mode
isamu-takagi Nov 10, 2022
51c9ddd
feat: modify error message
isamu-takagi Nov 10, 2022
0afa8ad
feat: remove unused code
isamu-takagi Nov 10, 2022
4064b33
Merge branch 'main' into feature/ad-api/operation-mode
isamu-takagi Nov 15, 2022
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
2 changes: 2 additions & 0 deletions system/default_ad_api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ament_auto_add_library(${PROJECT_NAME} SHARED
src/interface.cpp
src/localization.cpp
src/motion.cpp
src/operation_mode.cpp
src/routing.cpp
src/utils/route_conversion.cpp
)
Expand All @@ -16,6 +17,7 @@ rclcpp_components_register_nodes(${PROJECT_NAME}
"default_ad_api::InterfaceNode"
"default_ad_api::LocalizationNode"
"default_ad_api::MotionNode"
"default_ad_api::OperationModeNode"
"default_ad_api::RoutingNode"
)

Expand Down
13 changes: 7 additions & 6 deletions system/default_ad_api/launch/default_ad_api.launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@
from launch_ros.descriptions import ComposableNode


def _create_api_node(node_name, class_name, **kwargs):
def create_api_node(node_name, class_name, **kwargs):
return ComposableNode(
namespace="default_ad_api/node",
name=node_name,
package="default_ad_api",
plugin="default_ad_api::" + class_name,
**kwargs
**kwargs,
)


def generate_launch_description():
components = [
_create_api_node("interface", "InterfaceNode"),
_create_api_node("localization", "LocalizationNode"),
_create_api_node("motion", "MotionNode", parameters=[{"require_accept_start": False}]),
_create_api_node("routing", "RoutingNode"),
create_api_node("interface", "InterfaceNode"),
create_api_node("localization", "LocalizationNode"),
create_api_node("motion", "MotionNode", parameters=[{"require_accept_start": False}]),
create_api_node("operation_mode", "OperationModeNode"),
create_api_node("routing", "RoutingNode"),
]
container = ComposableNodeContainer(
namespace="default_ad_api",
Expand Down
1 change: 1 addition & 0 deletions system/default_ad_api/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<depend>rclcpp</depend>
<depend>rclcpp_components</depend>
<depend>tier4_control_msgs</depend>
<depend>tier4_system_msgs</depend>

<exec_depend>python3-flask</exec_depend>

Expand Down
1 change: 0 additions & 1 deletion system/default_ad_api/src/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#define INTERFACE_HPP_

#include <autoware_ad_api_specs/interface.hpp>
#include <component_interface_utils/rclcpp.hpp>
#include <rclcpp/rclcpp.hpp>

// This file should be included after messages.
Expand Down
1 change: 0 additions & 1 deletion system/default_ad_api/src/localization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

#include <autoware_ad_api_specs/localization.hpp>
#include <component_interface_specs/localization.hpp>
#include <component_interface_utils/rclcpp.hpp>
#include <rclcpp/rclcpp.hpp>

// This file should be included after messages.
Expand Down
168 changes: 168 additions & 0 deletions system/default_ad_api/src/operation_mode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright 2022 TIER IV, 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.

#include "operation_mode.hpp"

#include <memory>
#include <string>
#include <vector>

namespace default_ad_api
{

using ServiceResponse = autoware_adapi_v1_msgs::srv::ChangeOperationMode::Response;

OperationModeNode::OperationModeNode(const rclcpp::NodeOptions & options)
: Node("operation_mode", options)
{
const auto adaptor = component_interface_utils::NodeAdaptor(this);
group_cli_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
adaptor.init_sub(sub_state_, this, &OperationModeNode::on_state);
adaptor.init_pub(pub_state_);
adaptor.init_srv(srv_stop_mode_, this, &OperationModeNode::on_change_to_stop);
adaptor.init_srv(srv_autonomous_mode_, this, &OperationModeNode::on_change_to_autonomous);
adaptor.init_srv(srv_local_mode_, this, &OperationModeNode::on_change_to_local);
adaptor.init_srv(srv_remote_mode_, this, &OperationModeNode::on_change_to_remote);
adaptor.init_srv(srv_enable_control_, this, &OperationModeNode::on_enable_autoware_control);
adaptor.init_srv(srv_disable_control_, this, &OperationModeNode::on_disable_autoware_control);
adaptor.init_cli(cli_mode_, group_cli_);
adaptor.init_cli(cli_control_, group_cli_);

const std::vector<std::string> module_names = {
"sensing", "perception", "map", "localization", "planning", "control", "vehicle", "system",
};

for (size_t i = 0; i < module_names.size(); ++i) {
const auto name = "/system/component_state_monitor/component/autonomous/" + module_names[i];
const auto qos = rclcpp::QoS(1).transient_local();
const auto callback = [this, i](const ModeChangeAvailable::ConstSharedPtr msg) {
module_states_[i] = msg->available;
};
sub_module_states_.push_back(create_subscription<ModeChangeAvailable>(name, qos, callback));
}
module_states_.resize(module_names.size());

timer_ = rclcpp::create_timer(
this, get_clock(), rclcpp::Rate(5.0).period(), std::bind(&OperationModeNode::on_timer, this));

curr_state_.mode = OperationModeState::Message::UNKNOWN;
prev_state_.mode = OperationModeState::Message::UNKNOWN;
mode_available_[OperationModeState::Message::UNKNOWN] = false;
mode_available_[OperationModeState::Message::STOP] = true;
mode_available_[OperationModeState::Message::AUTONOMOUS] = false;
mode_available_[OperationModeState::Message::LOCAL] = true;
mode_available_[OperationModeState::Message::REMOTE] = true;
}

template <class ResponseT>
void OperationModeNode::change_mode(
const ResponseT res, const OperationModeRequest::_mode_type mode)
{
if (!mode_available_[mode]) {
throw component_interface_utils::ServiceException(
ServiceResponse::ERROR_NOT_AVAILABLE, "The mode change is blocked by the system.");
}
const auto req = std::make_shared<OperationModeRequest>();
req->mode = mode;
component_interface_utils::status::copy(cli_mode_->call(req), res); // NOLINT
}

void OperationModeNode::on_change_to_stop(
const ChangeToStop::Service::Request::SharedPtr,
const ChangeToStop::Service::Response::SharedPtr res)
{
change_mode(res, OperationModeRequest::STOP);
}

void OperationModeNode::on_change_to_autonomous(
const ChangeToAutonomous::Service::Request::SharedPtr,
const ChangeToAutonomous::Service::Response::SharedPtr res)
{
change_mode(res, OperationModeRequest::AUTONOMOUS);
}

void OperationModeNode::on_change_to_local(
const ChangeToLocal::Service::Request::SharedPtr,
const ChangeToLocal::Service::Response::SharedPtr res)
{
change_mode(res, OperationModeRequest::LOCAL);
}

void OperationModeNode::on_change_to_remote(
const ChangeToRemote::Service::Request::SharedPtr,
const ChangeToRemote::Service::Response::SharedPtr res)
{
change_mode(res, OperationModeRequest::REMOTE);
}

void OperationModeNode::on_enable_autoware_control(
const EnableAutowareControl::Service::Request::SharedPtr,
const EnableAutowareControl::Service::Response::SharedPtr res)
{
if (!mode_available_[curr_state_.mode]) {
throw component_interface_utils::ServiceException(
ServiceResponse::ERROR_NOT_AVAILABLE, "The mode change is blocked by the system.");
}
const auto req = std::make_shared<AutowareControlRequest>();
req->autoware_control = true;
component_interface_utils::status::copy(cli_control_->call(req), res); // NOLINT
}

void OperationModeNode::on_disable_autoware_control(
const DisableAutowareControl::Service::Request::SharedPtr,
const DisableAutowareControl::Service::Response::SharedPtr res)
{
const auto req = std::make_shared<AutowareControlRequest>();
req->autoware_control = false;
component_interface_utils::status::copy(cli_control_->call(req), res); // NOLINT
}

void OperationModeNode::on_state(const OperationModeState::Message::ConstSharedPtr msg)
{
curr_state_ = *msg;
update_state();
}

void OperationModeNode::on_timer()
{
bool autonomous_available = true;
for (const auto & state : module_states_) {
autonomous_available &= state;
}
mode_available_[OperationModeState::Message::AUTONOMOUS] = autonomous_available;

update_state();
}

void OperationModeNode::update_state()
{
// Clear stamp to compare other fields.
OperationModeState::Message state = curr_state_;
state.stamp = builtin_interfaces::msg::Time();
state.is_stop_mode_available &= mode_available_[OperationModeState::Message::STOP];
state.is_autonomous_mode_available &= mode_available_[OperationModeState::Message::AUTONOMOUS];
state.is_local_mode_available &= mode_available_[OperationModeState::Message::LOCAL];
state.is_remote_mode_available &= mode_available_[OperationModeState::Message::REMOTE];

if (prev_state_ != state) {
prev_state_ = state;
state.stamp = now();
pub_state_->publish(state);
}
}

} // namespace default_ad_api

#include <rclcpp_components/register_node_macro.hpp>
RCLCPP_COMPONENTS_REGISTER_NODE(default_ad_api::OperationModeNode)
100 changes: 100 additions & 0 deletions system/default_ad_api/src/operation_mode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2022 TIER IV, 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 OPERATION_MODE_HPP_
#define OPERATION_MODE_HPP_

#include <autoware_ad_api_specs/operation_mode.hpp>
#include <component_interface_specs/system.hpp>
#include <component_interface_utils/status.hpp>
#include <rclcpp/rclcpp.hpp>

#include <unordered_map>
#include <vector>

// TODO(Takagi, Isamu): define interface
#include <tier4_system_msgs/msg/mode_change_available.hpp>

// This file should be included after messages.
#include "utils/types.hpp"

namespace default_ad_api
{
class OperationModeNode : public rclcpp::Node
{
public:
explicit OperationModeNode(const rclcpp::NodeOptions & options);

private:
using OperationModeState = autoware_ad_api::operation_mode::OperationModeState;
using EnableAutowareControl = autoware_ad_api::operation_mode::EnableAutowareControl;
using DisableAutowareControl = autoware_ad_api::operation_mode::DisableAutowareControl;
using ChangeToStop = autoware_ad_api::operation_mode::ChangeToStop;
using ChangeToAutonomous = autoware_ad_api::operation_mode::ChangeToAutonomous;
using ChangeToLocal = autoware_ad_api::operation_mode::ChangeToLocal;
using ChangeToRemote = autoware_ad_api::operation_mode::ChangeToRemote;
using OperationModeRequest = system_interface::ChangeOperationMode::Service::Request;
using AutowareControlRequest = system_interface::ChangeAutowareControl::Service::Request;
using ModeChangeAvailable = tier4_system_msgs::msg::ModeChangeAvailable;

OperationModeState::Message curr_state_;
OperationModeState::Message prev_state_;
std::unordered_map<OperationModeState::Message::_mode_type, bool> mode_available_;

rclcpp::CallbackGroup::SharedPtr group_cli_;
rclcpp::TimerBase::SharedPtr timer_;
Pub<autoware_ad_api::operation_mode::OperationModeState> pub_state_;
Srv<autoware_ad_api::operation_mode::ChangeToStop> srv_stop_mode_;
Srv<autoware_ad_api::operation_mode::ChangeToAutonomous> srv_autonomous_mode_;
Srv<autoware_ad_api::operation_mode::ChangeToLocal> srv_local_mode_;
Srv<autoware_ad_api::operation_mode::ChangeToRemote> srv_remote_mode_;
Srv<autoware_ad_api::operation_mode::EnableAutowareControl> srv_enable_control_;
Srv<autoware_ad_api::operation_mode::DisableAutowareControl> srv_disable_control_;
Sub<system_interface::OperationModeState> sub_state_;
Cli<system_interface::ChangeOperationMode> cli_mode_;
Cli<system_interface::ChangeAutowareControl> cli_control_;

std::vector<bool> module_states_;
std::vector<rclcpp::Subscription<ModeChangeAvailable>::SharedPtr> sub_module_states_;

void on_change_to_stop(
const ChangeToStop::Service::Request::SharedPtr req,
const ChangeToStop::Service::Response::SharedPtr res);
void on_change_to_autonomous(
const ChangeToAutonomous::Service::Request::SharedPtr req,
const ChangeToAutonomous::Service::Response::SharedPtr res);
void on_change_to_local(
const ChangeToLocal::Service::Request::SharedPtr req,
const ChangeToLocal::Service::Response::SharedPtr res);
void on_change_to_remote(
const ChangeToRemote::Service::Request::SharedPtr req,
const ChangeToRemote::Service::Response::SharedPtr res);
void on_enable_autoware_control(
const EnableAutowareControl::Service::Request::SharedPtr req,
const EnableAutowareControl::Service::Response::SharedPtr res);
void on_disable_autoware_control(
const DisableAutowareControl::Service::Request::SharedPtr req,
const DisableAutowareControl::Service::Response::SharedPtr res);

void on_state(const OperationModeState::Message::ConstSharedPtr msg);
void on_timer();
void update_state();

template <class ResponseT>
void change_mode(const ResponseT res, const OperationModeRequest::_mode_type mode);
};

} // namespace default_ad_api

#endif // OPERATION_MODE_HPP_