-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/bdd exec comm #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: rolling
Are you sure you want to change the base?
Changes from all commits
c82d834
eddca6f
19f13c3
37f1487
47b438f
c478006
e69d7c2
a0c9b12
55944a8
e31a4fd
ee577d0
5a4f115
76454b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| located_at_pick: "/obs_policy/located_at_pick_ws" | ||
| is_held: "/obs_policy/is_held" | ||
| located_at_place: "/obs_policy/located_at_place_ws" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| #ifndef BDD_COLLAB_BHV__UTILS_HPP | ||
| #define BDD_COLLAB_BHV__UTILS_HPP | ||
|
|
||
| #include <string> | ||
| #include <map> | ||
| #include <stdexcept> | ||
| #include <yaml-cpp/yaml.h> | ||
|
|
||
| namespace bdd_collab_bhv { | ||
|
|
||
| using TopicConfig = std::map<std::string, std::string>; | ||
|
|
||
| inline TopicConfig load_topics(const std::string &file_path) | ||
| { | ||
| try { | ||
| YAML::Node root = YAML::LoadFile(file_path); | ||
|
|
||
| TopicConfig topics; | ||
| topics["located_at_pick"] = root["located_at_pick"].as<std::string>(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
| topics["is_held"] = root["is_held"].as<std::string>(); | ||
| topics["located_at_place"] = root["located_at_place"].as<std::string>(); | ||
|
|
||
| if ( | ||
| topics["located_at_pick"].empty() || topics["is_held"].empty() | ||
| || topics["located_at_place"].empty() | ||
| ) { | ||
| throw std::runtime_error( | ||
| "YAML must contain non-empty values for 'located_at_pick', 'is_held', and " | ||
| "'located_at_place'" | ||
| ); | ||
| } | ||
|
|
||
| return topics; | ||
| } catch (const YAML::Exception &e) { | ||
| throw std::runtime_error(std::string("Failed to parse YAML file: ") + e.what()); | ||
| } | ||
| } | ||
|
|
||
| } // namespace bdd_collab_bhv | ||
|
|
||
| #endif // BDD_COLLAB_BHV__UTILS_HPP | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,13 +26,14 @@ | |
| #include <rclcpp_action/server.hpp> | ||
| #include <rclcpp/utilities.hpp> | ||
| #include <utility> | ||
| #include "bdd_collab_bhv_cpp/collab_pickplace.hpp" | ||
| #include "bdd_collab_bhv_cpp/collab_pickplace_fsm.hpp" | ||
| #include "coord2b/functions/event_loop.h" | ||
| #include "coord2b/functions/fsm.h" | ||
| #include "bdd_ros2_interfaces/action/behaviour.hpp" | ||
| #include "bdd_collab_bhv_cpp/conversions.hpp" | ||
| #include "bdd_collab_bhv_cpp/fsm_behaviours.hpp" | ||
| #include "bdd_collab_bhv_cpp/collab_pickplace_node.hpp" | ||
| #include "bdd_collab_bhv_cpp/utils.hpp" | ||
|
|
||
| #define TICK_MILI_SECS 1 // 1kHz | ||
| #define HEARTBEAT_MILI_SECS 500 // 2Hz | ||
|
|
@@ -47,6 +48,8 @@ bcb::CollabPickplaceNode::CollabPickplaceNode(const rclcpp::NodeOptions &pOption | |
|
|
||
| declare_parameter<std::string>("bhv_server_name", "bhv_server"); | ||
| declare_parameter<std::string>("exec_context", "mockup"); | ||
| declare_parameter<std::string>("event_topic", ""); | ||
| declare_parameter<std::string>("topic_config", ""); | ||
|
|
||
| auto execCtxStr = get_parameter("exec_context").as_string(); | ||
| if (execCtxStr.compare("mockup") == 0) { | ||
|
|
@@ -105,6 +108,32 @@ bcb::CollabPickplaceNode::CollabPickplaceNode(const rclcpp::NodeOptions &pOption | |
| mBhvServerPtr = rclcpp_action::create_server<Behaviour>( | ||
| this, serverName, goalHandler, cancelHandler, accepted_handler | ||
| ); | ||
|
|
||
| const std::string eventTopic = get_parameter("event_topic").as_string(); | ||
| if (eventTopic.empty()) { | ||
| throw std::runtime_error("'event_topic' parameter is empty or not provided"); | ||
| } | ||
| RCLCPP_INFO(this->get_logger(), "Publishing events on topic: %s", eventTopic.c_str()); | ||
| mEventPublisher = this->create_publisher<Event>(eventTopic, rclcpp::QoS(10)); | ||
|
|
||
| const std::string topicConfigPath = get_parameter("topic_config").as_string(); | ||
| if (topicConfigPath.empty()) { | ||
| throw std::runtime_error("'topic_config' parameter is empty or not provided"); | ||
| } | ||
| try { | ||
| auto topicConfig = bcb::load_topics(topicConfigPath); | ||
| mLocatedPickTopic = topicConfig["located_at_pick"]; | ||
| mIsHeldTopic = topicConfig["is_held"]; | ||
| mLocatedPlaceTopic = topicConfig["located_at_place"]; | ||
| } catch (const std::exception &e) { | ||
| RCLCPP_ERROR(this->get_logger(), "Failed to load topic config: %s", e.what()); | ||
| throw; | ||
| } | ||
| mLocatedPickPublisher = | ||
| this->create_publisher<TrinaryStamped>(mLocatedPickTopic, rclcpp::QoS(10)); | ||
| mIsHeldPublisher = this->create_publisher<TrinaryStamped>(mIsHeldTopic, rclcpp::QoS(10)); | ||
| mLocatedPlacePublisher = | ||
| this->create_publisher<TrinaryStamped>(mLocatedPlaceTopic, rclcpp::QoS(10)); | ||
| } | ||
|
|
||
| void bcb::CollabPickplaceNode::start_fsm() | ||
|
|
@@ -137,15 +166,23 @@ void bcb::CollabPickplaceNode::fsm_loop() | |
| std::unique_ptr<BehaviourInterface> bhvInfPtr = nullptr; | ||
| switch (mExecCtx) { | ||
| case ExecutionType::Mockup: | ||
| bhvInfPtr = std::make_unique<MockupCollabBehaviour>(now, HEARTBEAT_MILI_SECS); | ||
| bhvInfPtr = std::make_unique<MockupCollabBehaviour>( | ||
| now, HEARTBEAT_MILI_SECS, mLocatedPickPublisher, mIsHeldPublisher, mLocatedPlacePublisher | ||
| ); | ||
| break; | ||
| default: | ||
| throw std::runtime_error( | ||
| std::format("Unhandled execution context type: '{}'", exec_type_to_str(mExecCtx)) | ||
| ); | ||
| } | ||
|
|
||
| auto response = std::make_shared<Behaviour::Result>(); | ||
| auto feedback = std::make_shared<Behaviour::Feedback>(); | ||
| Event evt_msg; | ||
|
|
||
| while (rclcpp::ok() && mFsmLoopRunning.load(std::memory_order_acquire)) { | ||
| now = this->get_clock()->now(); | ||
|
|
||
| if (!processingGoal) { | ||
| activeGoal = std::move(mPendingGoal); | ||
| mPendingGoal.reset(); | ||
|
|
@@ -155,12 +192,62 @@ void bcb::CollabPickplaceNode::fsm_loop() | |
| std::lock_guard<std::mutex> lockFsm(mFsmMutex); | ||
| produce_event(mFsmPtr->eventData, collab_pickplace::E_STEP); | ||
|
|
||
| response->result.scenario_context_id = activeGoal->mGoalCopy.scenario_context_id; | ||
|
|
||
| // Event publishing | ||
| for (unsigned int evt : CollabPickplaceNode::EXPORTED_EVENTS) { | ||
| if (!consume_event(mFsmPtr->eventData, evt)) continue; | ||
| evt_msg.scenario_context_id = activeGoal->mGoalCopy.scenario_context_id; | ||
| evt_msg.stamp = now; | ||
| evt_msg.uri = collab_pickplace::EVENT_URIS[evt]; | ||
| mEventPublisher->publish(evt_msg); | ||
| } | ||
|
|
||
| // Goal handling | ||
| if (activeGoal && !processingGoal) { | ||
| produce_event(mFsmPtr->eventData, collab_pickplace::E_NEW_GOAL); | ||
| processingGoal = true; | ||
| } | ||
| if (consume_event(mFsmPtr->eventData, collab_pickplace::E_GOAL_FINISHED)) { | ||
| response->result.stamp = now; | ||
| response->result.trinary.value = bdd_ros2_interfaces::msg::Trinary::TRUE; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The response may be different for simulation and real robot, I'd move this logic to the mockup behaviour code. Since you're anyway passing the goal handler to the step function this shouldn't be an issue. |
||
|
|
||
| if (auto goalHandle = activeGoal->mGoalHandlerPtr) { | ||
| goalHandle->succeed(response); | ||
| } else { | ||
| RCLCPP_ERROR( | ||
| this->get_logger(), | ||
| "Goal finished but no active goal handle: %s", | ||
| uuid_to_hex(activeGoal->mGoalCopy.scenario_context_id).c_str() | ||
| ); | ||
| } | ||
|
|
||
| processingGoal = false; | ||
| activeGoal.reset(); | ||
| } | ||
|
|
||
| if (mCancelRequested.load(std::memory_order_acquire)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All the mockup-specific implementation need to be moved to https://github.com/secorolab/bdd_collab_bhv_cpp/blob/-/src/fsm_behaviours.cpp. In the loop we will call mockup/mujoco/real robot behaviours depending on the config. |
||
| produce_event(mFsmPtr->eventData, collab_pickplace::E_GOAL_CANCELLED); | ||
| mCancelRequested.store(false, std::memory_order_release); | ||
| RCLCPP_INFO( | ||
| this->get_logger(), | ||
| "Goal cancel requested: %s", | ||
| uuid_to_hex(activeGoal->mGoalCopy.scenario_context_id).c_str() | ||
| ); | ||
|
|
||
| response->result.stamp = now; | ||
| response->result.trinary.value = bdd_ros2_interfaces::msg::Trinary::FALSE; | ||
|
|
||
| if (auto goalHandle = activeGoal->mGoalHandlerPtr) { | ||
| goalHandle->canceled(response); | ||
| } else { | ||
| RCLCPP_ERROR( | ||
| this->get_logger(), | ||
| "Goal cancel requested but no active goal handle: %s", | ||
| uuid_to_hex(activeGoal->mGoalCopy.scenario_context_id).c_str() | ||
| ); | ||
| } | ||
|
|
||
| processingGoal = false; | ||
| activeGoal.reset(); | ||
| } | ||
|
|
@@ -170,7 +257,16 @@ void bcb::CollabPickplaceNode::fsm_loop() | |
| } | ||
|
|
||
| // Behaviour & FSM update | ||
| bhvInfPtr->step(nodePtr, mFsmPtr.get()); | ||
| if (activeGoal && processingGoal) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are there 2 different calls to |
||
| bhvInfPtr->step( | ||
| nodePtr, | ||
| mFsmPtr.get(), | ||
| activeGoal->mGoalCopy.scenario_context_id, | ||
| activeGoal->mGoalHandlerPtr | ||
| ); | ||
| } else { | ||
| bhvInfPtr->step(nodePtr, mFsmPtr.get()); | ||
| } | ||
| fsm_step_nbx(mFsmPtr.get()); | ||
| reconfig_event_buffers(mFsmPtr->eventData); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please turn these strings into constants or
#define