20#include "auto_apms_behavior_tree_core/tree/tree_document.hpp"
21#include "auto_apms_util/container.hpp"
22#include "auto_apms_util/string.hpp"
23#include "behaviortree_cpp/basic_types.h"
27int main(
int argc,
char ** argv)
29 bool print_help =
false;
31 const std::string arg(argv[1]);
32 print_help =
"-h" == arg ||
"--help" == arg;
34 if (print_help || argc < 2) {
35 std::cerr <<
"create_node_reference_markdown: The program accepts: \n\t1.) Path to the markdown file to write "
36 "to.\n\t2.) Node manifest identities of installed resources used to "
37 "create the documentation. All "
38 "arguments after the first one are interpreted as resource identities.\n";
39 std::cerr <<
"Usage: create_node_reference_markdown <output_file> [<node_manifest_identity> ...]\n";
45 if (output_file.empty()) {
46 throw std::runtime_error(
"Argument output_file must not be empty.");
50 if (output_file.extension() !=
".md") {
51 throw std::runtime_error(
"Output file '" + output_file.string() +
"' has wrong extension. Must be '.md'.");
55 std::vector<std::string> input_packages;
56 for (
int i = 2; i < argc; ++i) {
58 input_packages.push_back(package_name);
59 if (package_name ==
"include_native")
continue;
65 const std::string native_package_name =
"auto_apms_behavior_tree (BehaviorTree.CPP)";
66 for (std::string & ele : input_packages) {
67 if (ele ==
"include_native") ele = native_package_name;
71 core::NodeRegistrationLoader::SharedPtr node_loader_ptr = core::NodeRegistrationLoader::make_shared();
72 core::TreeDocument doc(core::TreeDocument::BTCPP_FORMAT_DEFAULT_VERSION, node_loader_ptr);
73 doc.registerNodes(node_manifest);
74 std::map<std::string, std::string> package_for_class = node_loader_ptr->getClassPackageMap();
80 const std::set<std::string> native_node_names = BT::BehaviorTreeFactory().builtinNodes();
81 for (
const auto & [registration_name, _] : model_map) {
82 if (!node_manifest.
contains(registration_name)) {
83 if (native_node_names.find(registration_name) != native_node_names.end()) {
84 node_manifest.
add(registration_name, native_node_options);
85 package_for_class[node_manifest[registration_name].class_name] = native_package_name;
87 throw std::runtime_error(
"Package for node '" + registration_name +
"' is unkown.");
92 auto lowerize = [](
const std::string & str) {
94 std::transform(ret.begin(), ret.end(), ret.begin(), [](
unsigned char c) { return std::tolower(c); });
98 std::ostringstream content;
99 content << R
"(<!-- markdownlint-disable MD024 MD041 -->
102| Registration Name | Class Name | Package |
103| :--- | :---: | :---: |)";
104 for (
const std::string & package_name : input_packages) {
105 for (
const auto & [registration_name,
model] : model_map) {
107 if (package_name != package_for_class[options.
class_name])
continue;
108 content <<
"\n| [" << registration_name <<
"](#" << lowerize(registration_name) <<
") | `" << options.
class_name
109 <<
"` | " << package_for_class[options.
class_name] <<
" |";
113 for (
const std::string & package_name : input_packages) {
114 content <<
"\n## " << package_name <<
"\n";
115 for (
const auto & [registration_name,
model] : model_map) {
117 if (package_name != package_for_class[options.
class_name])
continue;
120)" << "### " << registration_name << R
"(
124**Node Type:** `)" << BT::toStr(model.type) << R"(`
126 if (
model.port_infos.empty()) {
127 content <<
"\n*This node doesn't have any ports.*\n";
130 std::vector<core::TreeDocument::NodePortInfo> inputs;
131 std::vector<core::TreeDocument::NodePortInfo> outputs;
132 std::vector<core::TreeDocument::NodePortInfo> inouts;
135 case BT::PortDirection::INPUT:
136 inputs.push_back(port_info);
138 case BT::PortDirection::OUTPUT:
139 outputs.push_back(port_info);
141 case BT::PortDirection::INOUT:
142 inouts.push_back(port_info);
146 if (!inputs.empty()) {
150| Input Name | Type | Default Value | Description |
151| :--- | :---: | :---: | :--- |
157 if (!outputs.empty()) {
161| Output Name | Type | Default Value | Description |
162| :--- | :---: | :---: | :--- |
168 if (!inouts.empty()) {
170#### Bidirectional Ports
172| Port Name | Type | Default Value | Description |
173| :--- | :---: | :---: | :--- |
183 std::ofstream out_stream(output_file);
184 if (out_stream.is_open()) {
185 out_stream << content.str();
188 throw std::runtime_error(
"Error opening markdown output file '" + output_file.string() +
"'");
190 }
catch (
const std::exception & e) {
191 std::cerr <<
"ERROR (create_node_reference_markdown): " << e.what() <<
"\n";
Data structure for information about which behavior tree node plugin to load and how to configure the...
NodeManifest & add(const std::string &node_name, const RegistrationOptions &opt)
Add registration options for a behavior tree node to the manifest.
bool contains(const std::string &node_name) const
Determine if a behavior tree node has been added to the manifest.
NodeManifest & merge(const NodeManifest &other, bool replace=false)
Merges another NodeManifest with this one.
static NodeManifest fromResourceIdentity(const std::string &identity)
Create a node manifest from an installed resource.
Document Object Model (DOM) for the behavior tree XML schema. This class offers a programmatic approa...
std::map< std::string, NodeModel > NodeModelMap
Mapping of node registration names and their implementation details.
std::string trimWhitespaces(const std::string &str)
Trim whitespaces from both ends of a string.
bool contains(const ContainerT< ValueT, AllocatorT > &c, const ValueT &val)
Check whether a particular container structure contains a value.
std::vector< std::string > splitString(const std::string &str, const std::string &delimiter, bool remove_empty=true)
Split a string into multiple tokens using a specific delimiter string (Delimiter may consist of multi...
Models for all available behavior tree nodes.
Useful tooling for incorporating behavior trees for task development.
Parameters for loading and registering a behavior tree node class from a shared library using e....
std::string class_name
Fully qualified name of the behavior tree node plugin class.
Implementation details of a single data port.
std::string port_default
Default value of the port encoded as string.
bool port_has_default
Flag whether the port implements a default value or not.
std::string port_description
Description of the port.
BT::PortDirection port_direction
Direction of the port.
std::string port_type
String representation of the C++ type given to the port.
std::string port_name
Name of the port.