diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 7b0a0406f55e61fe06bf97ea1e1f2c18abbeade7..415fbf1b23145dde3e71b5924cc9e29d62d227e2 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -10,6 +10,10 @@ RUN apt update -q \ libboost-all-dev \ xauth \ ros-${ROS_DISTRO}-example-interfaces \ + mesa-utils \ + x11-apps \ + ros-jazzy-rqt-graph \ + gdb-multiarch \ && apt clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b0cf01ca48c700124e9b27534e56f752a5db5d2f..ec1841bb827533ae3c8f63627f6d6b5d3f7af608 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -38,7 +38,9 @@ //"mounts": ["src=/home/leolol/Code/dyknow-ros-2,dst=/root/ros2_ws,type=bind"], "mounts": [], "runArgs": [ - "--net=host" + "--net=host", + "-e=DISPLAY=192.168.1.224:0", + "-v=/tmp/.X11-unix:/tmp/.X11-unix" ] } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index f18101c280745ea7a705c185ed2475b8002b72f8..8389a9a7ff5939f1e6fcb7bbba406e8c19cf6fbb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,13 +12,22 @@ "environment": [], "externalConsole": false, "MIMode": "gdb", - "miDebuggerServerAddress": "localhost:3001", - "miDebuggerPath": "/usr/bin/gdb", + "miDebuggerPath": "/usr/bin/gdb-multiarch", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true + }, + { + "description": "Ignore controlling terminal errors", + "text": "set inferior-tty /dev/null", + "ignoreFailures": true + }, + { + "description": "Disable SVE register fetching", + "text": "set debug target-async 0", + "ignoreFailures": true } ], "preLaunchTask": "build" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..4dfa18ae46c7f58a93cfb2177407c0aead6ad60f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Leo Jarhede + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/someCommands.bash b/someCommands.bash index 7edd137239561dedb8368e48fcc55894288b2560..560c420d6f82000612ff33d3a1ec47a27de934ce 100644 --- a/someCommands.bash +++ b/someCommands.bash @@ -1,10 +1,38 @@ #Create the echo transformation -ros2 service call /add_transformation dyknow_interfaces/srv/AddTransformation "{transformations: [{label: 'echo', type: 'node', source_package: 'dyknow_echo', source_plugin: "echo::EchoComp", params: [], out_ports: [], in_ports: [], tags: [], cost: 0, environment: 0}], envid: 0}" +ros2 service call /add_transformation dyknow_interfaces/srv/AddTransformation "{transformations: [{label: 'echo', type: 'node', source_package: 'dyknow_echo', source_plugin: "echo::EchoComp", params: [], out_ports: ['/1'], in_ports: ['_1'], tags: [], cost: 0, environment: 0}], envid: 0}" #Instanciate the echo computeUnit (create componet) -ros2 service call /spawn dyknow_interfaces/srv/Spawn "{name: 'echoNode', type: 'echo', protect: true, envid: 0}" +ros2 service call /spawn dyknow_interfaces/srv/Spawn "{name: 'echoNode', type: 'echo', protect: false, envid: 0}" #Check the current model -ros2 service call /get_model dyknow_interfaces/srv/GetConfiguration {}\ +ros2 service call /get_model dyknow_interfaces/srv/GetConfiguration {}\ + + +apt update && apt install -y mesa-utils x11-apps ros-jazzy-rqt-grap gdb-multiarch +apt update && apt install -y ros-jazzy-rqt-grap +rqt_graph + +ros2 service call /echoNode/set_config dyknow_interfaces/srv/Configure "{config: {in_names:['in'], in_channels: ['_1'], out_names: ['out'], out_channels: ['/1'] manager: ''}}" + +ros2 service call /configure dyknow_interfaces/srv/ManagerConfigure "{config: {in_names:['in'], in_channels: ['_1'], out_names: ['out'], out_channels: ['/1'] manager: ''}}" + +ros2 service call /destroy dyknow_interfaces/srv/Destroy "{name: echoNode, envid: 0}" + +ros2 service call /ComponentManager/_container/unload_node composition_interfaces/srv/UnloadNode "{unique_id: 1}" + + + +ros2 service call /add_transformation dyknow_interfaces/srv/AddTransformation "{transformations: [{label: 'echo0', type: 'node', source_package: 'dyknow_echo', source_plugin: "echo::EchoComp", params: [], out_ports: ['/1'], in_ports: ['_1'], tags: [{port: '/1', tag: 'out1'}, {port: '_1', tag: 'in1'}], cost: 0, environment: 0}], envid: 0}" + +ros2 service call /add_transformation dyknow_interfaces/srv/AddTransformation "{transformations: [{label: 'echo1', type: 'node', source_package: 'dyknow_echo', source_plugin: "echo::EchoComp", params: [], out_ports: ['/1'], in_ports: ['_1'], tags: [{port: '/1', tag: 'out2'}, {port: '_1', tag: 'out1'}], cost: 0, environment: 0}], envid: 0}" + +ros2 service call /add_target dyknow_interfaces/srv/AddTarget "{ targets: [{label: 'echo1', port: 0 , topic: 'theout', environment: 0}], envid: 0 }" + +ros2 service call /spawn dyknow_interfaces/srv/Spawn "{name: 'echoNode0', type: 'echo0', protect: false, envid: 0}" + +ros2 service call /spawn dyknow_interfaces/srv/Spawn "{name: 'echoNode1', type: 'echo1', protect: false, envid: 0}" + + +ros2 service call /add_target dyknow_interfaces/srv/AddTarget "{ targets: [{label '', port: _ , topic: '', environment: 0}] envid: 0 }" \ No newline at end of file diff --git a/src/dyknow_echo/CMakeLists.txt b/src/dyknow_echo/CMakeLists.txt index 1c6d19cc7206ee3c29bf2806b9ac764ee1157d96..25d31a6178677923fadeb16a1d1649418612e802 100644 --- a/src/dyknow_echo/CMakeLists.txt +++ b/src/dyknow_echo/CMakeLists.txt @@ -12,7 +12,6 @@ find_package(rclcpp_components REQUIRED) find_package(dyknow_nodehandle REQUIRED) find_package(dyknow_analytics REQUIRED) find_package(composition_interfaces REQUIRED) -find_package(example_interfaces REQUIRED) # include_directories( # include @@ -38,7 +37,6 @@ ament_target_dependencies(dyknow_echo_component dyknow_nodehandle dyknow_analytics composition_interfaces - example_interfaces ) # rclcpp_components_register_node(dyknow_echo_component diff --git a/src/dyknow_echo/package.xml b/src/dyknow_echo/package.xml index e4e3ae7e0be8bada3529337fe0324747e7a99db9..606d30185271f2bf94bcf788a114bebb8b78dc77 100644 --- a/src/dyknow_echo/package.xml +++ b/src/dyknow_echo/package.xml @@ -4,7 +4,7 @@ <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="leoja464@student.liu.se">root</maintainer> - <license>TODO: License declaration</license> + <license>MIT</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>rclcpp</depend> diff --git a/src/dyknow_echo/src/echoComposition.cpp b/src/dyknow_echo/src/echoComposition.cpp index c1f1fb25ac86f36468154772467ba274cfa4aded..3f47ca91015ee51358ba28a68eb319c840fadfea 100644 --- a/src/dyknow_echo/src/echoComposition.cpp +++ b/src/dyknow_echo/src/echoComposition.cpp @@ -1,7 +1,6 @@ #include "dyknow_echo/echoComposition.hpp" #include <rclcpp_components/register_node_macro.hpp> #include <composition_interfaces/srv/load_node.hpp> -#include "example_interfaces/srv/add_two_ints.hpp" @@ -13,9 +12,9 @@ namespace echo { for(int i = 0; i < arity; i++) { node->create_subscription<dyknow_interfaces::msg::Sample, EchoComp>(1000, &EchoComp::callback, this); } - node->connectInput("_1", "in"); + //node->connectInput("_1", "in"); pub = node->create_publisher<dyknow_interfaces::msg::Sample>(1000); - node->connectOutput("/1", "in"); + //node->connectOutput("/1", "in"); } rclcpp::node_interfaces::NodeBaseInterface::SharedPtr EchoComp::get_node_base_interface() const @@ -31,27 +30,27 @@ namespace echo { copy.test = sample->test; - // if the client is incorectly defined here then we will get a segmentation fault, on top of that if the service is not available then we just crash - // ros2 service call /ComponentManager/_container/load_node composition_interfaces/srv/LoadNode "{ package_name: "nav2_planner", plugin_name: "nav2_planner::PlannerServer", parameters: [ {name: "global_costmap.global_costmap.resolution", value: { type: 3, double_value: "1.23"}}]}" - // ros2 service call /ComponentManager/_container/load_node composition_interfaces/srv/LoadNode "{ package_name: "dyknow_echo", plugin_name: "echo::EchoComp", parameters: []}" - rclcpp::Client<composition_interfaces::srv::LoadNode>::SharedPtr client = node->create_client<composition_interfaces::srv::LoadNode>("ComponentManager/_container/load_node"); - //rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client = node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints"); + // // if the client is incorectly defined here then we will get a segmentation fault, on top of that if the service is not available then we just crash + // // ros2 service call /ComponentManager/_container/load_node composition_interfaces/srv/LoadNode "{ package_name: "nav2_planner", plugin_name: "nav2_planner::PlannerServer", parameters: [ {name: "global_costmap.global_costmap.resolution", value: { type: 3, double_value: "1.23"}}]}" + // // ros2 service call /ComponentManager/_container/load_node composition_interfaces/srv/LoadNode "{ package_name: "dyknow_echo", plugin_name: "echo::EchoComp", parameters: []}" + // rclcpp::Client<composition_interfaces::srv::LoadNode>::SharedPtr client = node->create_client<composition_interfaces::srv::LoadNode>("ComponentManager/_container/load_node"); + // //rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client = node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints"); - auto loadComponentService = std::make_shared<composition_interfaces::srv::LoadNode::Request>(); - //auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>(); - // request->a = 1; - // request->b = 2; + // auto loadComponentService = std::make_shared<composition_interfaces::srv::LoadNode::Request>(); + // //auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>(); + // // request->a = 1; + // // request->b = 2; - loadComponentService->package_name = "dyknow_echo"; - loadComponentService->plugin_name = "echo::EchoComp"; + // loadComponentService->package_name = "dyknow_echo"; + // loadComponentService->plugin_name = "echo::EchoComp"; - if (!client->wait_for_service(std::chrono::seconds(10))) - { - RCLCPP_ERROR(node->get_logger(), "Service %s/load_nodelet not available"); - return; - } + // if (!client->wait_for_service(std::chrono::seconds(10))) + // { + // RCLCPP_ERROR(node->get_logger(), "Service %s/load_nodelet not available"); + // return; + // } - auto result = client->async_send_request(loadComponentService); + // //auto result = client->async_send_request(loadComponentService); pub.publish(copy); } diff --git a/src/dyknow_interfaces/package.xml b/src/dyknow_interfaces/package.xml index 7447859027601bb274257901b273519258913863..f9f87a239eed9c421a59eb2087959aa323e79132 100644 --- a/src/dyknow_interfaces/package.xml +++ b/src/dyknow_interfaces/package.xml @@ -5,7 +5,7 @@ <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="leoja464@student.liu.se">root</maintainer> - <license>TODO: License declaration</license> + <license>MIT</license> <buildtool_depend>ament_cmake</buildtool_depend> diff --git a/src/dyknow_manager/CMakeLists.txt b/src/dyknow_manager/CMakeLists.txt index 5a936cfb8ac2469fddd47ecd91c359b5fbd0a832..55ad4b92b30f39e39b9617d10e0eb6fb520250f9 100644 --- a/src/dyknow_manager/CMakeLists.txt +++ b/src/dyknow_manager/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.8) project(dyknow_manager) +set(CMAKE_BUILD_TYPE Debug) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() diff --git a/src/dyknow_manager/include/dyknow_manager/compunit_helper.hpp b/src/dyknow_manager/include/dyknow_manager/compunit_helper.hpp index caf98d8a11b61db9239644914710308255facb0d..abe3511f9990a0f1f7f2487016562be1d75ef03f 100644 --- a/src/dyknow_manager/include/dyknow_manager/compunit_helper.hpp +++ b/src/dyknow_manager/include/dyknow_manager/compunit_helper.hpp @@ -14,6 +14,13 @@ #include "dyknow_nodehandle/node.hpp" #include "transformation_spec.hpp" #include <composition_interfaces/srv/load_node.hpp> +#include <composition_interfaces/srv/unload_node.hpp> +#include <rcl_interfaces/msg/parameter.hpp> +#include <rcl_interfaces/msg/parameter_value.hpp> +#include <rcl_interfaces/msg/parameter_type.hpp> +#include <dyknow_interfaces/srv/configure.hpp> + + namespace dyknow { @@ -22,9 +29,9 @@ class CompUnitHelper { public: CompUnitHelper() {} ~CompUnitHelper() {} - static bool spawn(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& node_name, const std::string& source_package, const std::string& source_plugin, std::vector<std::string>& args); + static long spawn(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& node_name, const std::string& source_package, const std::string& source_plugin, std::vector<std::string>& args); static bool configure(std::shared_ptr<dyknow::Node> nh, const std::string& manager, std::string name, std::map<std::string, std::string> inputMap, std::map<std::string, std::string> outputMap); - static bool destroy(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& name); + static bool destroy(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& name, const long& unique_id); }; diff --git a/src/dyknow_manager/include/dyknow_manager/configuration_manager.hpp b/src/dyknow_manager/include/dyknow_manager/configuration_manager.hpp index 9d92b69528acbf082cbf11d89f0142ef3eabc6ce..2d9abb9d1ea8975581c8efdb28fd8ef5f3920966 100644 --- a/src/dyknow_manager/include/dyknow_manager/configuration_manager.hpp +++ b/src/dyknow_manager/include/dyknow_manager/configuration_manager.hpp @@ -79,6 +79,7 @@ public: void refreshCallback(const std::shared_ptr<dyknow_interfaces::srv::Refresh::Request> req, std::shared_ptr<dyknow_interfaces::srv::Refresh::Response> res); void repairCallback(const std::shared_ptr<dyknow_interfaces::srv::Repair::Request> req, std::shared_ptr<dyknow_interfaces::srv::Repair::Response> res); void getValidInputsCallback(const std::shared_ptr<dyknow_interfaces::srv::GetValidInputs::Request> req, std::shared_ptr<dyknow_interfaces::srv::GetValidInputs::Response> res); + // getFeasabilityMatix? would be nice for debugging.. void expPopulateCallback(const std::shared_ptr<dyknow_interfaces::srv::ExpPopulate::Request> req, std::shared_ptr<dyknow_interfaces::srv::ExpPopulate::Response> res); bool apply(Change delta, int environment); diff --git a/src/dyknow_manager/include/dyknow_manager/environment.hpp b/src/dyknow_manager/include/dyknow_manager/environment.hpp index a6adf3b96ada3d7872e1d5628a128add67448e4b..ca30588e2c9fe6d69076988e31f93ed9141ef570 100644 --- a/src/dyknow_manager/include/dyknow_manager/environment.hpp +++ b/src/dyknow_manager/include/dyknow_manager/environment.hpp @@ -14,12 +14,14 @@ namespace dyknow { struct ComputationUnit { std::string name; std::string type; + long unique_id; ComputationUnit() {} - ComputationUnit(std::string name, std::string type) { + ComputationUnit(std::string name, std::string type, long unique_id) { this->name = name; this->type = type; + this->unique_id = unique_id; } }; diff --git a/src/dyknow_manager/include/dyknow_manager/feasibility_matrix.hpp b/src/dyknow_manager/include/dyknow_manager/feasibility_matrix.hpp index dc72160a404e02cac2ca3d568b0b4ee0c1f526c3..ceb310a63852ec0a1648f959c994f63c88faaeca 100644 --- a/src/dyknow_manager/include/dyknow_manager/feasibility_matrix.hpp +++ b/src/dyknow_manager/include/dyknow_manager/feasibility_matrix.hpp @@ -15,6 +15,52 @@ public: virtual std::map<Port, std::vector<Port> > generate(std::vector<TransformationSpec> library) = 0; }; + +class TagMatrixGenerator : public FeasibilityMatrixGenerator { + public: + TagMatrixGenerator() : FeasibilityMatrixGenerator() {} + virtual ~TagMatrixGenerator() {} + virtual std::map<Port, std::vector<Port>> generate(std::vector<TransformationSpec> library) { + std::map<Port, std::vector<Port>> result; + for(TransformationSpec inSpecification : library) { + for(int i = 0; i < inSpecification.inPorts.size(); i++){ + Port inPort(inSpecification.id, i); + result[inPort] = std::vector<Port>(); + + // The name of the port as deified in the transformication specification + std::string inPortLabel = inSpecification.inPorts[i]; + + // Find the correct tag that corresponds with the current port. + TransformationTag inTag = getTagFormPort(inSpecification, inPortLabel); + + for (TransformationSpec outSpecification : library){ + for(int j = 0; j < outSpecification.outPorts.size(); j++){ + Port outPort(outSpecification.id, j); + std::string outPortLabel = outSpecification.outPorts[j]; + + TransformationTag outTag = getTagFormPort(outSpecification, outPortLabel); + + if (inTag.second == outTag.second) { + result[inPort].push_back(outPort); + } + } + } + } + } + return result; + } + private: + virtual TransformationTag getTagFormPort(TransformationSpec transformationSpecification, std::string portLabel){ + for (TransformationTag tag : transformationSpecification.tags){ + if (tag.first == portLabel){ + return tag; + + } + } + } +}; + + class RandomMatrixGenerator : public FeasibilityMatrixGenerator { public: RandomMatrixGenerator() : FeasibilityMatrixGenerator(), density(0.01) {} diff --git a/src/dyknow_manager/package.xml b/src/dyknow_manager/package.xml index 7672d8ba2802753bb10c4fabe662c5c3c5518e93..6a5494a5a7b98292a8d0fe7072c185c1365af052 100644 --- a/src/dyknow_manager/package.xml +++ b/src/dyknow_manager/package.xml @@ -5,7 +5,7 @@ <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="leoja464@student.liu.se">root</maintainer> - <license>TODO: License declaration</license> + <license>MIT</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>rclcpp</depend> diff --git a/src/dyknow_manager/src/compunit_helper.cpp b/src/dyknow_manager/src/compunit_helper.cpp index d3b19faa3ef3e019c91b442df97fa07f65aab743..e1a8fc0f5baa80510f427f572d3b4494a07651cb 100644 --- a/src/dyknow_manager/src/compunit_helper.cpp +++ b/src/dyknow_manager/src/compunit_helper.cpp @@ -2,7 +2,7 @@ namespace dyknow { -bool CompUnitHelper::spawn(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& node_name, const std::string& source_package, const std::string& source_plugin, std::vector<std::string>& args) { +long CompUnitHelper::spawn(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& node_name, const std::string& source_package, const std::string& source_plugin, std::vector<std::string>& args) { if(source_package == "") { RCLCPP_WARN(nh->get_logger(), "Failed to spawn: %s does not provide a package name", node_name.c_str()); return false; @@ -12,109 +12,99 @@ bool CompUnitHelper::spawn(std::shared_ptr<dyknow::Node> nh, const std::string& rclcpp::Client<composition_interfaces::srv::LoadNode>::SharedPtr client = nh->create_client<composition_interfaces::srv::LoadNode>("ComponentManager/_container/load_node"); auto loadComponentRequest = std::make_shared<composition_interfaces::srv::LoadNode::Request>(); - loadComponentRequest->node_name = node_name; loadComponentRequest->package_name = source_package; loadComponentRequest->plugin_name = source_plugin; + // Build the ParameterValue (type 4 means string) + rcl_interfaces::msg::ParameterValue param_value; + param_value.type = 4; + param_value.string_value = node_name; + + // Build the Parameter message and assign its name and value + rcl_interfaces::msg::Parameter parameter; + parameter.name = "dyknow_name"; + parameter.value = param_value; + + // Add the parameter to the request + loadComponentRequest->parameters.push_back(parameter); + + // OK this technically works but not ideal.... bool isWaiting = true; - int timeout = 10; // The maximum that we are willing to wait - int waited = 0; + std::shared_ptr<composition_interfaces::srv::LoadNode_Response> response; using ServiceResponseFuture = rclcpp::Client<composition_interfaces::srv::LoadNode>::SharedFuture; - auto response_received_callback = [&nh, &isWaiting](ServiceResponseFuture future) { - //auto result = future.get(); + auto response_received_callback = [&nh, &isWaiting, &response](ServiceResponseFuture future) { + response = future.get(); isWaiting= false; }; - auto result = client->async_send_request(loadComponentRequest, response_received_callback); - - // while (isWaiting){ - // RCLCPP_INFO(nh->get_logger(), "Waiting for response from component manager, regarding a load_node service call"); - // rclcpp::sleep_for(std::chrono::seconds(1)); - - // if (waited > timeout){ - // isWaiting= false; - // result.future.get()->success = false; - // RCLCPP_WARN(nh->get_logger(), "Timeout"); - // } - // else{ - // waited++; - // } - // } + client->async_send_request(loadComponentRequest, response_received_callback); + while (isWaiting){ + RCLCPP_INFO(nh->get_logger(), "Waiting for response from component manager, regarding a load_node service call"); + rclcpp::sleep_for(std::chrono::seconds(1)); + } - // Retrive the response of the load node service - // TODO, if there is no response from the component manager the dyknow manager will hang - if (result.future.get()->success) + if (response->success) { RCLCPP_INFO(nh->get_logger(), "Successfully spawned component %s", node_name.c_str()); - return true; + long id = response->unique_id; + return id ; } else { RCLCPP_ERROR(nh->get_logger(), "Unable to call service for %s with source %s", node_name.c_str(), source_package.c_str()); - return false; + return 0; } - - return false; } bool CompUnitHelper::configure(std::shared_ptr<dyknow::Node> nh, const std::string& manager, std::string name, std::map<std::string, std::string> inputMap, std::map<std::string, std::string> outputMap) { - return false; - // ros::ServiceClient client = nh.serviceClient<dyknow_nodehandle::Configure>("/"+name+"/set_config"); - // dyknow_nodehandle::Configure configureService; - // //std::pair<std::string, std::string> elem; - // for_each(outputMap.begin(), outputMap.end(), [&configureService](std::pair<std::string, std::string> elem) { - // configureService.request.config.out_names.push_back(elem.second); - // configureService.request.config.out_channels.push_back(elem.first); - // }); + rclcpp::Client<dyknow_interfaces::srv::Configure>::SharedPtr client = nh->create_client<dyknow_interfaces::srv::Configure>(name+"/set_config"); - // for_each(inputMap.begin(), inputMap.end(), [&configureService](std::pair<std::string, std::string> elem) { - // configureService.request.config.in_names.push_back(elem.second); - // configureService.request.config.in_channels.push_back(elem.first); - // }); + auto configureService = std::make_shared<dyknow_interfaces::srv::Configure::Request>(); + for (std::pair<std::string, std::string> elem : outputMap) { + configureService->config.out_names.push_back(elem.second); + configureService->config.out_channels.push_back(elem.first); + } - // configureService.request.config.manager = manager; + for (std::pair<std::string, std::string> elem : inputMap) { + configureService->config.in_names.push_back(elem.second); + configureService->config.in_channels.push_back(elem.first); + } - // if (client.call(configureService)) - // { - // if(!configureService.response.success) { - // RCLCPP_ERROR(nh->get_logger(), "Failed to configure nodelet %s", name.c_str()); - // } - // else { - // RCLCPP_INFO(nh->get_logger(), "Successfully configured nodelet %s", name.c_str()); - // } - // return true; - // } - // else - // { - // RCLCPP_ERROR(nh->get_logger(), "Unable to configure nodelet %s", name.c_str()); - // return false; - // } + configureService->config.manager = manager; + + auto result = client->async_send_request(configureService); + + if(result.future.get()->success) { + RCLCPP_ERROR(nh->get_logger(), "Failed to configure nodelet %s", name.c_str()); + } + else { + RCLCPP_INFO(nh->get_logger(), "Successfully configured nodelet %s", name.c_str()); + } + return true; } -bool CompUnitHelper::destroy(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& name) { - return false; - // ros::ServiceClient unloadClient = nh.serviceClient<nodelet::NodeletUnload>("/" + manager + "/unload_nodelet"); - // nodelet::NodeletUnload unloadService; - // // Call unload service - // unloadService.request.name = name.c_str(); +bool CompUnitHelper::destroy(std::shared_ptr<dyknow::Node> nh, const std::string& manager, const std::string& name, const long& unique_id) { + rclcpp::Client<composition_interfaces::srv::UnloadNode>::SharedPtr client = nh->create_client<composition_interfaces::srv::UnloadNode>("ComponentManager/_container/unload_node"); - // if (unloadClient.call(unloadService)) - // { - // if(!unloadService.response.success) { - // RCLCPP_ERROR(nh->get_logger(), "Unable to unload nodelet %s: failure while unloading", name.c_str()); - // return false; - // } - // else { - // RCLCPP_INFO(nh->get_logger(), "Successfully unloaded nodelet %s", name.c_str()); - // return true; - // } - // } - // else + auto unloadComponentRequest = std::make_shared<composition_interfaces::srv::UnloadNode::Request>(); + + unloadComponentRequest->unique_id = unique_id; + auto result = client->async_send_request(unloadComponentRequest); + + if(!result.future.get()->success) { + RCLCPP_ERROR(nh->get_logger(), "Unable to unload nodelet %s: failure while unloading", name.c_str()); + return false; + } + else { + RCLCPP_INFO(nh->get_logger(), "Successfully unloaded nodelet %s", name.c_str()); + return true; + } + //else // { // RCLCPP_ERROR(nh->get_logger(), "Unable to unload nodelet %s: service unavailable", name.c_str()); // return false; diff --git a/src/dyknow_manager/src/configuration_planner.cpp b/src/dyknow_manager/src/configuration_planner.cpp index a7ac8fdd23cd440169b4a8944f07c841e91619c6..7f83a3c601ddadfcd4b3b9ee7945fbc0a91e600b 100644 --- a/src/dyknow_manager/src/configuration_planner.cpp +++ b/src/dyknow_manager/src/configuration_planner.cpp @@ -22,9 +22,8 @@ Change ConfigurationPlanner::optimise(std::vector<TargetSpec> targets, Computati std::vector<TransformationSpec> targetTransforms; std::vector<int> targetPorts; - //TargetSpec target; + // Find all the target port and transformations combinations that are indicated by targets for (TargetSpec target : targets) { - //TransformationSpec spec; for (TransformationSpec spec : graph.transformations) { if(target.id == spec.id) { targetTransforms.push_back(spec); @@ -219,13 +218,14 @@ void ConfigurationPlanner::expandCompUnit(ConfigurationNode* nodePtr, Computatio // Consider using computation units double bestCost = nodePtr->hasBest(index) ? nodePtr->bestMap[index]->cost : ConfigurationNode::MAX_COST + 1; + // Port candidate; for (Port candidate : candidates) { + TransformationSpec candidateSpec = matrix.decode(candidate); if(candidateSpec.id < 0) { continue; } -// if(verbosity >= 9) RCLCPP_INFO(nh->get_logger(),"Considering (%s, /%i | arity: %lu) as input for (%s, _%i | arity: %lu)", candidateSpec.label.c_str(), candidate.second, candidateSpec.inPorts.size(), nodePtr->type.label.c_str(), index, nodePtr->type.inPorts.size()); + if(verbosity >= 9) RCLCPP_INFO(nh->get_logger(),"Considering (%s, /%i | arity: %lu) as input for (%s, _%i | arity: %lu)", candidateSpec.label.c_str(), candidate.second, candidateSpec.inPorts.size(), nodePtr->type.label.c_str(), index, nodePtr->type.inPorts.size()); - ComputationUnit compUnit; for (ComputationUnit compUnit : graph.computationUnits) { if(candidateSpec.label == compUnit.type && find(ancestors.begin(), ancestors.end(), candidateSpec) == ancestors.end()) { @@ -272,8 +272,11 @@ void ConfigurationPlanner::expandTransformation(ConfigurationNode* nodePtr, Feas //Port candidate; for (Port candidate : candidates) { + TransformationSpec candidateSpec = matrix.decode(candidate); -// if(verbosity >= 9) RCLCPP_INFO(nh->get_logger(),"Considering (%s, /%i | arity: %lu) as input for (%s, _%i | arity: %lu)", candidateSpec.label.c_str(), candidate.second, candidateSpec.inPorts.size(), nodePtr->type.label.c_str(), index, nodePtr->type.inPorts.size()); + + if(verbosity >= 9) RCLCPP_INFO(nh->get_logger(),"Considering (%s, /%i | arity: %lu) as input for (%s, _%i | arity: %lu)", candidateSpec.label.c_str(), candidate.second, candidateSpec.inPorts.size(), nodePtr->type.label.c_str(), index, nodePtr->type.inPorts.size()); + if(find(ancestors.begin(), ancestors.end(), candidateSpec) != ancestors.end()) { // Not allowed to reuse this transformation along this path if(verbosity >= 3) RCLCPP_INFO(nh->get_logger(),"May not reuse: %s (skipping)", candidateSpec.label.c_str()); diff --git a/src/dyknow_manager/src/environment.cpp b/src/dyknow_manager/src/environment.cpp index 429a03ced8c9e2412c8bdfb99930fe59b0c054fe..f8bde52fd760cc9db3a88454bab0cf52b4e7a9e5 100644 --- a/src/dyknow_manager/src/environment.cpp +++ b/src/dyknow_manager/src/environment.cpp @@ -43,9 +43,9 @@ bool Environment::spawn(std::string node_name, std::string type, bool protect) { for (const auto& param : iter->parameters) { args.push_back(param.value); //FIXME: The interface currently ignores parameter names and types } - RCLCPP_INFO(this->nh->get_logger(), "** %s is now protected **", node_name.c_str()); - if (CompUnitHelper::spawn(nh, componentManagerName, node_name, iter->source_package, iter->source_plugin, args)) { - ComputationUnit cu(node_name, type); + long id = CompUnitHelper::spawn(nh, componentManagerName, node_name, iter->source_package, iter->source_plugin, args); + if (id != 0) { + ComputationUnit cu(node_name, type, id); computationUnits.push_back(cu); subscriptionMap.emplace(node_name, Subscription()); generatorMap.emplace(node_name, Generator()); @@ -60,12 +60,15 @@ bool Environment::spawn(std::string node_name, std::string type, bool protect) { } bool Environment::destroy(std::string name) { - auto iter = std::find_if(computationUnits.begin(), computationUnits.end(), [&name](const ComputationUnit& cu) { - return cu.name == name; - }); - - if (iter != computationUnits.end()) { - if (CompUnitHelper::destroy(nh, componentManagerName, name)) { + // Check if CU instance exists + std::vector<ComputationUnit>::iterator iter; + for(iter = computationUnits.begin(); iter != computationUnits.end() ; iter++) { + if(iter->name.compare(name) == 0) { + break; + } + } + if(iter != computationUnits.end()) { + if(CompUnitHelper::destroy(nh, componentManagerName, name, iter->unique_id)) { computationUnits.erase(iter); subscriptionMap.erase(name); generatorMap.erase(name); @@ -112,6 +115,7 @@ bool Environment::addTarget(TargetSpec spec) { RCLCPP_WARN(this->nh->get_logger(), "Could not find identifier for target %s", spec.label.c_str()); return false; } + } else { targets.push_back(spec); this->repair = true; @@ -159,6 +163,6 @@ std::vector<Port> Environment::getValidInputs(Port source) { return matrix.getValid(source); } -// expPopulate couldbe added here! +// expPopulate could be added here! } //namespace diff --git a/src/dyknow_manager/src/feasibility_matrix.cpp b/src/dyknow_manager/src/feasibility_matrix.cpp index 741f214dc6d95bacf533054c7e4e6183b427f502..0bf6b5e295912a32f3a2aacb8c80a7dd20c0858f 100644 --- a/src/dyknow_manager/src/feasibility_matrix.cpp +++ b/src/dyknow_manager/src/feasibility_matrix.cpp @@ -3,7 +3,8 @@ namespace dyknow { FeasibilityMatrix::FeasibilityMatrix(std::vector<TransformationSpec> library, double density) { - RandomMatrixGenerator gen(density); + //RandomMatrixGenerator gen(density); + TagMatrixGenerator gen; // This is the type of matrix generator that we will be using this->matrix = gen.generate(library); this->library = library; } diff --git a/src/dyknow_manager/src/manager_componet.cpp b/src/dyknow_manager/src/manager_componet.cpp index 18357f1c72acf17445429eedc449d5e657562a7f..5ec80375c4cc56887c4d7fa893054e0c971838f2 100644 --- a/src/dyknow_manager/src/manager_componet.cpp +++ b/src/dyknow_manager/src/manager_componet.cpp @@ -5,8 +5,6 @@ namespace manager { ManagerComponet::ManagerComponet(const rclcpp::NodeOptions & options): node(std::make_shared<dyknow::Node>("manager_componet", options)) { - - RCLCPP_INFO(node->get_logger(), "I LIVE, AM I ALIVE, I AM MEEEEE "); configManPtr = std::shared_ptr<dyknow::ConfigurationManager>(new dyknow::ConfigurationManager(this->node)); } diff --git a/src/dyknow_nodehandle/include/dyknow_nodehandle/node.hpp b/src/dyknow_nodehandle/include/dyknow_nodehandle/node.hpp index 8dd22e3f6320afb03f95d2c0987f39edbceec1d6..e7296cbbc5955588b338760e27a0783ec54da79b 100644 --- a/src/dyknow_nodehandle/include/dyknow_nodehandle/node.hpp +++ b/src/dyknow_nodehandle/include/dyknow_nodehandle/node.hpp @@ -24,10 +24,13 @@ public: Node(const std::string & nodeName, const rclcpp::NodeOptions & options) : rclcpp::Node(nodeName, options) , subCount(0), pubCount(0), reconfigCount(0), reconfigCallbackFn(NULL) { + this->declare_parameter<std::string>("dyknow_name", ""); + std::string dyknowName = this->get_parameter("dyknow_name").as_string(); + configureService = this->create_service<dyknow_interfaces::srv::Configure>( - nodeName + "/set_config", std::bind(&Node::configureCallback, this, std::placeholders::_1, std::placeholders::_2)); + dyknowName + "/set_config", std::bind(&Node::configureCallback, this, std::placeholders::_1, std::placeholders::_2)); getConfigService = this->create_service<dyknow_interfaces::srv::GetConfig>( - nodeName + "/get_config", std::bind(&Node::getConfigCallback, this, std::placeholders::_1, std::placeholders::_2)); + dyknowName + "/get_config", std::bind(&Node::getConfigCallback, this, std::placeholders::_1, std::placeholders::_2)); analyticsTimer = this->create_wall_timer( std::chrono::seconds(1), std::bind(&Node::analyticsCallback, this)); analyticsPublisher = this->rclcpp::Node::create_publisher<dyknow_analytics::msg::MonitorSet>("analytics", 10); diff --git a/src/dyknow_nodehandle/package.xml b/src/dyknow_nodehandle/package.xml index 90e7e56fd164fa59f6af331a133a4fa9c1e377cb..8d6a43cc8264e82499d16f703b54378042a059ac 100644 --- a/src/dyknow_nodehandle/package.xml +++ b/src/dyknow_nodehandle/package.xml @@ -5,7 +5,7 @@ <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="leoja464@student.liu.se">root</maintainer> - <license>TODO: License declaration</license> + <license>MIT</license> <!-- Build tools --> <buildtool_depend>ament_cmake</buildtool_depend>