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(component_interface_utils): change service log output #2022

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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: 1 addition & 1 deletion common/component_interface_utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ project(component_interface_utils)

find_package(autoware_cmake REQUIRED)
autoware_package()

ament_export_dependencies(tier4_system_msgs)
kenji-miyake marked this conversation as resolved.
Show resolved Hide resolved
ament_auto_package()
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
#define COMPONENT_INTERFACE_UTILS__RCLCPP_HPP_

#include <component_interface_utils/rclcpp/create_interface.hpp>
#include <component_interface_utils/rclcpp/interface.hpp>
#include <component_interface_utils/rclcpp/service_client.hpp>
#include <component_interface_utils/rclcpp/service_server.hpp>
#include <component_interface_utils/rclcpp/topic_publisher.hpp>
#include <component_interface_utils/rclcpp/topic_subscription.hpp>

#include <memory>
#include <optional>
#include <utility>

Expand All @@ -43,38 +45,38 @@ class NodeAdaptor

public:
/// Constructor.
explicit NodeAdaptor(rclcpp::Node * node) : node_(node) {}
explicit NodeAdaptor(rclcpp::Node * node) { interface_ = std::make_shared<NodeInterface>(node); }

/// Create a client wrapper for logging.
template <class SharedPtrT>
void init_cli(SharedPtrT & cli, CallbackGroup group = nullptr) const
{
using SpecT = typename SharedPtrT::element_type::SpecType;
cli = create_client_impl<SpecT>(node_, group);
cli = create_client_impl<SpecT>(interface_, group);
}

/// Create a service wrapper for logging.
template <class SharedPtrT, class CallbackT>
void init_srv(SharedPtrT & srv, CallbackT && callback, CallbackGroup group = nullptr) const
{
using SpecT = typename SharedPtrT::element_type::SpecType;
srv = create_service_impl<SpecT>(node_, std::forward<CallbackT>(callback), group);
srv = create_service_impl<SpecT>(interface_, std::forward<CallbackT>(callback), group);
}

/// Create a publisher using traits like services.
template <class SharedPtrT>
void init_pub(SharedPtrT & pub) const
{
using SpecT = typename SharedPtrT::element_type::SpecType;
pub = create_publisher_impl<SpecT>(node_);
pub = create_publisher_impl<SpecT>(interface_->node);
}

/// Create a subscription using traits like services.
template <class SharedPtrT, class CallbackT>
void init_sub(SharedPtrT & sub, CallbackT && callback) const
{
using SpecT = typename SharedPtrT::element_type::SpecType;
sub = create_subscription_impl<SpecT>(node_, std::forward<CallbackT>(callback));
sub = create_subscription_impl<SpecT>(interface_->node, std::forward<CallbackT>(callback));
}

/// Relay message.
Expand Down Expand Up @@ -119,7 +121,7 @@ class NodeAdaptor

private:
// Use a node pointer because shared_from_this cannot be used in constructor.
rclcpp::Node * node_;
NodeInterface::SharedPtr interface_;
};

} // namespace component_interface_utils
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef COMPONENT_INTERFACE_UTILS__RCLCPP__CREATE_INTERFACE_HPP_
#define COMPONENT_INTERFACE_UTILS__RCLCPP__CREATE_INTERFACE_HPP_

#include <component_interface_utils/rclcpp/interface.hpp>
#include <component_interface_utils/rclcpp/service_client.hpp>
#include <component_interface_utils/rclcpp/service_server.hpp>
#include <component_interface_utils/rclcpp/topic_publisher.hpp>
Expand All @@ -28,28 +29,24 @@ namespace component_interface_utils
{

/// Create a client wrapper for logging. This is a private implementation.
template <class SpecT, class NodeT>
template <class SpecT>
typename Client<SpecT>::SharedPtr create_client_impl(
NodeT * node, rclcpp::CallbackGroup::SharedPtr group = nullptr)
NodeInterface::SharedPtr interface, rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
// This function is a wrapper for the following.
// https://github.com/ros2/rclcpp/blob/48068130edbb43cdd61076dc1851672ff1a80408/rclcpp/include/rclcpp/node.hpp#L253-L265
auto client = node->template create_client<typename SpecT::Service>(
SpecT::name, rmw_qos_profile_services_default, group);
return Client<SpecT>::make_shared(client, node->get_logger());
return Client<SpecT>::make_shared(interface, group);
}

/// Create a service wrapper for logging. This is a private implementation.
template <class SpecT, class NodeT, class CallbackT>
template <class SpecT, class CallbackT>
typename Service<SpecT>::SharedPtr create_service_impl(
NodeT * node, CallbackT && callback, rclcpp::CallbackGroup::SharedPtr group = nullptr)
NodeInterface::SharedPtr interface, CallbackT && callback,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
// This function is a wrapper for the following.
// https://github.com/ros2/rclcpp/blob/48068130edbb43cdd61076dc1851672ff1a80408/rclcpp/include/rclcpp/node.hpp#L267-L281
auto wrapped = Service<SpecT>::wrap(callback, node->get_logger());
auto service = node->template create_service<typename SpecT::Service>(
SpecT::name, wrapped, rmw_qos_profile_services_default, group);
return Service<SpecT>::make_shared(service);
return Service<SpecT>::make_shared(interface, std::forward<CallbackT>(callback), group);
}

/// Create a publisher using traits like services. This is a private implementation.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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 COMPONENT_INTERFACE_UTILS__RCLCPP__INTERFACE_HPP_
#define COMPONENT_INTERFACE_UTILS__RCLCPP__INTERFACE_HPP_

#include <rclcpp/rclcpp.hpp>

#include <tier4_system_msgs/msg/service_log.hpp>

#include <memory>
#include <string>

namespace component_interface_utils
{

struct NodeInterface
{
using SharedPtr = std::shared_ptr<NodeInterface>;
using ServiceLog = tier4_system_msgs::msg::ServiceLog;

explicit NodeInterface(rclcpp::Node * node)
{
this->node = node;
this->logger = node->create_publisher<ServiceLog>("/service_log", 10);

node_name_ = node->get_namespace();
if (node_name_.empty() || node_name_.back() != '/') {
node_name_ += "/";
}
node_name_ += node->get_name();
}

void log(ServiceLog::_type_type type, const std::string & name, const std::string & yaml)
{
ServiceLog msg;
msg.stamp = node->now();
msg.type = type;
msg.name = name;
msg.node = node_name_;
msg.yaml = yaml;
logger->publish(msg);
}

rclcpp::Node * node;
rclcpp::Publisher<ServiceLog>::SharedPtr logger;
std::string node_name_;
};

} // namespace component_interface_utils

#endif // COMPONENT_INTERFACE_UTILS__RCLCPP__INTERFACE_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
#define COMPONENT_INTERFACE_UTILS__RCLCPP__SERVICE_CLIENT_HPP_

#include <component_interface_utils/rclcpp/exceptions.hpp>
#include <rclcpp/client.hpp>
#include <rclcpp/logger.hpp>
#include <rclcpp/logging.hpp>
#include <component_interface_utils/rclcpp/interface.hpp>
#include <rclcpp/node.hpp>

#include <tier4_system_msgs/msg/service_log.hpp>

#include <optional>
#include <string>
#include <utility>

namespace component_interface_utils
Expand All @@ -34,28 +36,30 @@ class Client
RCLCPP_SMART_PTR_DEFINITIONS(Client)
using SpecType = SpecT;
using WrapType = rclcpp::Client<typename SpecT::Service>;
using ServiceLog = tier4_system_msgs::msg::ServiceLog;

/// Constructor.
explicit Client(typename WrapType::SharedPtr client, const rclcpp::Logger & logger)
: logger_(logger)
Client(NodeInterface::SharedPtr interface, rclcpp::CallbackGroup::SharedPtr group)
: interface_(interface)
{
client_ = client; // to keep the reference count
client_ = interface->node->create_client<typename SpecT::Service>(
SpecT::name, rmw_qos_profile_services_default, group);
}

/// Send request.
typename WrapType::SharedResponse call(
const typename WrapType::SharedRequest request, std::optional<double> timeout = std::nullopt)
{
if (!client_->service_is_ready()) {
RCLCPP_INFO_STREAM(logger_, "client unready: " << SpecT::name);
interface_->log(ServiceLog::ERROR_UNREADY, SpecType::name, "");
throw ServiceUnready(SpecT::name);
}

const auto future = this->async_send_request(request);
if (timeout) {
const auto duration = std::chrono::duration<double, std::ratio<1>>(timeout.value());
if (future.wait_for(duration) != std::future_status::ready) {
RCLCPP_INFO_STREAM(logger_, "client timeout: " << SpecT::name);
interface_->log(ServiceLog::ERROR_TIMEOUT, SpecType::name, "");
throw ServiceTimeout(SpecT::name);
}
}
Expand All @@ -78,11 +82,11 @@ class Client
#endif

const auto wrapped = [this, callback](typename WrapType::SharedFuture future) {
RCLCPP_INFO_STREAM(logger_, "client exit: " << SpecT::name << "\n" << to_yaml(*future.get()));
interface_->log(ServiceLog::CLIENT_RESPONSE, SpecType::name, to_yaml(*future.get()));
callback(future);
};

RCLCPP_INFO_STREAM(logger_, "client call: " << SpecT::name << "\n" << to_yaml(*request));
interface_->log(ServiceLog::CLIENT_REQUEST, SpecType::name, to_yaml(*request));

#ifdef ROS_DISTRO_GALACTIC
return client_->async_send_request(request, wrapped);
Expand All @@ -94,7 +98,7 @@ class Client
private:
RCLCPP_DISABLE_COPY(Client)
typename WrapType::SharedPtr client_;
rclcpp::Logger logger_;
NodeInterface::SharedPtr interface_;
};

} // namespace component_interface_utils
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
#define COMPONENT_INTERFACE_UTILS__RCLCPP__SERVICE_SERVER_HPP_

#include <component_interface_utils/rclcpp/exceptions.hpp>
#include <rclcpp/logging.hpp>
#include <rclcpp/service.hpp>
#include <component_interface_utils/rclcpp/interface.hpp>
#include <rclcpp/node.hpp>

#include <tier4_system_msgs/msg/service_log.hpp>

#include <string>

namespace component_interface_utils
{
Expand Down Expand Up @@ -45,25 +49,31 @@ class Service
RCLCPP_SMART_PTR_DEFINITIONS(Service)
using SpecType = SpecT;
using WrapType = rclcpp::Service<typename SpecT::Service>;
using ServiceLog = tier4_system_msgs::msg::ServiceLog;

/// Constructor.
explicit Service(typename WrapType::SharedPtr service)
template <class CallbackT>
Service(
NodeInterface::SharedPtr interface, CallbackT && callback,
rclcpp::CallbackGroup::SharedPtr group)
: interface_(interface)
{
service_ = service; // to keep the reference count
service_ = interface_->node->create_service<typename SpecT::Service>(
SpecT::name, wrap(callback), rmw_qos_profile_services_default, group);
}

/// Create a service callback with logging added.
template <class CallbackT>
static auto wrap(CallbackT && callback, const rclcpp::Logger & logger)
typename WrapType::CallbackType wrap(CallbackT && callback)
{
auto wrapped = [logger, callback](
auto wrapped = [this, callback](
typename SpecT::Service::Request::SharedPtr request,
typename SpecT::Service::Response::SharedPtr response) {
#ifdef ROS_DISTRO_GALACTIC
using rosidl_generator_traits::to_yaml;
#endif
// If the response has status, convert it from the exception.
RCLCPP_INFO_STREAM(logger, "service call: " << SpecT::name << "\n" << to_yaml(*request));
interface_->log(ServiceLog::SERVER_REQUEST, SpecType::name, to_yaml(*request));
if constexpr (!has_status_type<typename SpecT::Service::Response>::value) {
callback(request, response);
} else {
Expand All @@ -73,14 +83,15 @@ class Service
error.set(response->status);
}
}
RCLCPP_INFO_STREAM(logger, "service exit: " << SpecT::name << "\n" << to_yaml(*response));
interface_->log(ServiceLog::SERVER_RESPONSE, SpecType::name, to_yaml(*response));
};
return wrapped;
}

private:
RCLCPP_DISABLE_COPY(Service)
typename WrapType::SharedPtr service_;
NodeInterface::SharedPtr interface_;
};

} // namespace component_interface_utils
Expand Down
2 changes: 2 additions & 0 deletions common/component_interface_utils/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<test_depend>ament_lint_auto</test_depend>
<test_depend>autoware_lint_common</test_depend>

<build_export_depend>tier4_system_msgs</build_export_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
Expand Down