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();
75 const NodeModelMap model_map = doc.getNodeModel(include_native);
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 MD060 -->
100| Registration Name | Class Name | Package |
101| :--- | :---: | :---: |)";
102 for (
const std::string & package_name : input_packages) {
103 for (
const auto & [registration_name,
model] : model_map) {
105 if (package_name != package_for_class[options.
class_name])
continue;
106 content <<
"\n| [" << registration_name <<
"](#" << lowerize(registration_name) <<
") | `" << options.
class_name
107 <<
"` | " << package_for_class[options.
class_name] <<
" |";
111 for (
const std::string & package_name : input_packages) {
112 content <<
"\n## " << package_name <<
"\n";
113 for (
const auto & [registration_name,
model] : model_map) {
115 if (package_name != package_for_class[options.
class_name])
continue;
118)" << "### " << registration_name << R
"(
122**Plugin Class:** `)" << options.class_name << R"(`
128**Node Type:** `)" << BT::toStr(model.type) << R"(`
130**Description:** )" << (options.description.empty() ? "No description available." : options.
description) << R
"(
132 if (
model.port_infos.empty()) {
133 content <<
"\n*This node doesn't have any ports.*\n";
136 std::vector<NodePortInfo> inputs;
137 std::vector<NodePortInfo> outputs;
138 std::vector<NodePortInfo> inouts;
141 case BT::PortDirection::INPUT:
142 inputs.push_back(port_info);
144 case BT::PortDirection::OUTPUT:
145 outputs.push_back(port_info);
147 case BT::PortDirection::INOUT:
148 inouts.push_back(port_info);
152 if (!inputs.empty()) {
156| Input Name | Type | Default Value | Description |
157| :--- | :---: | :---: | :--- |
163 if (!outputs.empty()) {
167| Output Name | Type | Default Value | Description |
168| :--- | :---: | :---: | :--- |
174 if (!inouts.empty()) {
176#### Bidirectional Ports
178| Port Name | Type | Default Value | Description |
179| :--- | :---: | :---: | :--- |
189 std::ofstream out_stream(output_file);
190 if (out_stream.is_open()) {
191 out_stream << content.str();
194 throw std::runtime_error(
"Error opening markdown output file '" + output_file.string() +
"'");
196 }
catch (
const std::exception & e) {
197 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 fromResource(const NodeManifestResourceIdentity &search_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::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.
Powerful tooling for incorporating behavior trees for task development.
std::map< std::string, NodeModel > NodeModelMap
Mapping of node registration names and their implementation details.
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.
Parameters for loading and registering a behavior tree node class from a shared library using e....
std::string description
Short description of the behavior tree node's purpose and use-case.
std::string class_name
Fully qualified name of the behavior tree node plugin class.