26int main(
int argc,
char** argv)
30 std::cerr <<
"generate_node_model: Missing inputs! The program requires: \n\t1.) The path to the node plugin "
31 "manifest.\n\t2.) The xml file to store the model.\n";
32 std::cerr <<
"Usage: generate_node_model <manifest_file> <output_file>.\n";
38 const std::string manifest_file{ std::filesystem::absolute(argv[1]).string() };
39 const std::filesystem::path output_file{ std::filesystem::absolute(argv[2]) };
42 if (manifest_file.empty())
44 throw std::runtime_error(
"Argument manifest_file must not be empty.");
46 if (output_file.empty())
48 throw std::runtime_error(
"Argument output_file must not be empty.");
52 if (output_file.extension() !=
".xml")
54 throw std::runtime_error(
"Output file '" + output_file.string() +
"' has wrong extension. Must be '.xml'.");
57 rclcpp::init(argc, argv);
58 auto node_ptr = std::make_shared<rclcpp::Node>(
"_generate_node_model_temp_node");
62 BT::BehaviorTreeFactory factory;
70 auto class_loader = class_loader::MultiLibraryClassLoader{
false };
71 for (
const auto& [node_name, params] : manifest.getInternalMap())
73 if (params.library.empty())
76 throw std::runtime_error(
"Parameters for node '" + node_name +
"' do not specify a library path.");
78 const auto& library_path = params.library;
81 if (!class_loader.isLibraryAvailable(library_path))
85 class_loader.loadLibrary(library_path);
87 catch (
const std::exception& e)
89 throw std::runtime_error(
"Failed to load library '" + library_path +
"': " + e.what() +
".");
94 const std::string factory_classname =
95 "auto_apms_behavior_tree::NodeRegistrationFactory<" + params.class_name +
">";
97 if (std::find(classes.begin(), classes.end(), factory_classname) == classes.end())
99 throw std::runtime_error{
"Node '" + node_name +
" (Class: " + params.class_name +
100 ")' cannot be loaded, because factory class '" + factory_classname +
101 "' couldn't be found. Check that the class name is spelled correctly and registered "
102 "by calling auto_apms_behavior_tree_register_nodes() in the CMakeLists.txt of the "
103 "corresponding package. Also make sure that you called the "
104 "AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE macro in the source file." };
107 RCLCPP_DEBUG(node_ptr->get_logger(),
"Loading behavior tree node '%s' (Class: %s) from library %s.",
108 node_name.c_str(), params.class_name.c_str(), library_path.c_str());
114 plugin_instance->registerWithBehaviorTreeFactory(factory, node_name, &ros_node_context);
116 catch (
const std::exception& e)
118 throw std::runtime_error(
"Failed to load and register node '" + node_name +
" (Class: " + params.class_name +
119 ")': " + e.what() +
".");
124 std::ofstream out_stream{ output_file };
125 if (out_stream.is_open())
127 out_stream << BT::writeTreeNodesModelXML(factory);
132 throw std::runtime_error(
"Error opening node model output file '" + output_file.string() +
"'.");
135 catch (
const std::exception& e)
137 std::cerr <<
"ERROR (generate_node_model): " << e.what() <<
"\n";