AutoAPMS
Resilient Robot Mission Management
Loading...
Searching...
No Matches
logger.cpp
1// Copyright 2024 Robin Müller
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "auto_apms_behavior_tree_core/node.hpp"
16#include "rclcpp/logging.hpp"
17#include "rcutils/error_handling.h"
18#include "rcutils/logging.h"
19
20#define INPUT_KEY_MSG "message"
21#define INPUT_KEY_LEVEL "level"
22
24{
25
26class Logger : public BT::SyncActionNode
27{
28public:
29 Logger(const std::string & instance_name, const BT::NodeConfig & config, const core::RosNodeContext & context)
30 : SyncActionNode(instance_name, config), context_(context)
31 {
32 }
33
34 static BT::PortsList providedPorts()
35 {
36 return {
37 BT::InputPort<std::string>(
38 INPUT_KEY_LEVEL, "INFO",
39 "Logger level. Must be one of [UNSET, DEBUG, INFO, WARN, ERROR, FATAL] but is not case sensitive."),
40 BT::InputPort<BT::AnyTypeAllowed>(INPUT_KEY_MSG, "Message to be logged via rclcpp::Logger.")};
41 }
42
43 BT::NodeStatus tick() override final
44 {
45 const std::string level_str = getInput<std::string>(INPUT_KEY_LEVEL).value();
46 int level;
47 if (
48 rcutils_logging_severity_level_from_string(level_str.c_str(), rcutils_get_default_allocator(), &level) !=
49 RCUTILS_RET_OK) {
50 const std::string error = rcutils_get_error_string().str;
51 rcutils_reset_error();
52 throw exceptions::RosNodeError(
53 "Cannot convert input of port '" + std::string(INPUT_KEY_LEVEL) +
54 "' to a valid logging severity level: " + error);
55 }
56 const BT::PortsRemapping::iterator it = config().input_ports.find(INPUT_KEY_MSG);
57 if (it == config().input_ports.end()) return BT::NodeStatus::SUCCESS;
58
59 std::string msg;
60 if (isBlackboardPointer(it->second)) {
61 // If input port is blackboard pointer, try to cast the underlying value to a string
62 if (const BT::Expected<BT::Any> expected = getInput<BT::Any>(INPUT_KEY_MSG)) {
63 const BT::Any & any = expected.value();
64 msg = it->second + " (Cannot convert " + BT::demangle(any.type()) + " to string)";
65 if (const BT::Expected<std::string> casted = any.tryCast<std::string>()) {
66 msg = casted.value().c_str();
67 }
68 } else {
69 throw exceptions::RosNodeError(context_.getFullyQualifiedTreeNodeName(this) + " - " + expected.error());
70 }
71 } else {
72 // Otherwise print the input directly
73 msg = it->second;
74 }
75
76 msg = context_.getFullyQualifiedTreeNodeName(this, false) + " - " + msg + (msg.back() == '.' ? "" : ".");
77 RCUTILS_LOG_COND_NAMED(
78 level, RCUTILS_LOG_CONDITION_EMPTY, RCUTILS_LOG_CONDITION_EMPTY, context_.getBaseLogger().get_name(),
79 msg.c_str());
80 return BT::NodeStatus::SUCCESS;
81 }
82
83private:
84 const core::RosNodeContext context_;
85};
86
87} // namespace auto_apms_behavior_tree
88
89AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(auto_apms_behavior_tree::Logger)
#define AUTO_APMS_BEHAVIOR_TREE_DECLARE_NODE(type)
Macro for registering a behavior tree node plugin.
Definition node.hpp:40
Useful tooling for incorporating behavior trees for task development.
Definition builder.hpp:30