diff --git a/CMakeLists.txt b/CMakeLists.txt index e947f59e331fe9d71940752abee60abc4307884b..f5c9aeeb7aea7c0d029f9531af41a85f6600d4a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ include_directories( add_executable(${PROJECT_NAME}_dummy_selection_provider src/dummy_selection_provider.cpp ${PROTO_SRCS} ${PROTO_HDRS}) add_executable(${PROJECT_NAME}_dummy_pickplace_provider src/dummy_pickplace_provider.cpp ${PROTO_SRCS} ${PROTO_HDRS}) add_executable(${PROJECT_NAME}_dummy_sorting_controller src/dummy_sorting_controller.cpp ${PROTO_SRCS} ${PROTO_HDRS}) -add_executable(${PROJECT_NAME}_main_controller src/main_controller.cpp ${PROTO_SRCS} ${PROTO_HDRS} src/cell.cpp src/action.cpp src/task.cpp src/cell_controller.cpp include/cell_controller.h) +add_executable(${PROJECT_NAME}_main_controller src/main_controller.cpp ${PROTO_SRCS} ${PROTO_HDRS} src/action.cpp src/cell_controller.cpp include/cell_controller.h) add_executable(${PROJECT_NAME}_virtual_scene_provider src/virtual_scene_provider.cpp ${PROTO_SRCS} ${PROTO_HDRS}) add_executable(${PROJECT_NAME}_moveit_sorting_controller src/moveit_sorting_controller.cpp ${PROTO_SRCS} ${PROTO_HDRS}) add_executable(${PROJECT_NAME}_object_locator src/object_locator.cpp ${PROTO_SRCS} ${PROTO_HDRS}) diff --git a/include/action.h b/include/action.h index 1a1317fef3d0ac9131449c1430f0d6ffa3ef8739..32a84656a1d1d3217f069f9e9a08e2f3ba6fc034 100644 --- a/include/action.h +++ b/include/action.h @@ -58,18 +58,7 @@ public: /// \param scene /// \param id the prefix the object starts with /// \return - [[nodiscard]] static std::optional<Object> lookupObject(const Scene& scene, const std::string& id) - { - for (Object object : scene.objects()) - { - // if the id can be found at position 0 - if (object.id().rfind(id, 0) == 0) - { - return object; - } - } - return std::nullopt; - } + [[nodiscard]] static std::optional<Object> lookupObject(const Scene& scene, const std::string& id); [[nodiscard]] Type getType() const { @@ -93,10 +82,7 @@ public: * @param source * @param target */ - Action(Type type, std::string source, std::string target) - : type_(type), source_(std::move(source)), target_(std::move(target)) - { - } + Action(Type type, std::string source, std::string target); /** * an action can be performed in a scene if source and target exist in the scene and have the correct type for the @@ -104,26 +90,9 @@ public: * @param scene * @return true if the action can be performed */ - bool canBePerformed(const Scene& scene) - { - auto s = lookupObject(scene, source_); - auto t = lookupObject(scene, target_); - return s && t && s->type() == requiredSourceType(type_) && t->type() == requiredTargetType(type_); - } + bool canBePerformed(const Scene& scene); - [[nodiscard]] bool isCompleted(const Scene& scene) const - { - switch (type_) - { - case Action::Type::PICK_DROP: - // pick and drop is completed if the dropped element no longer exists - return !lookupObject(scene, source_).has_value(); - case Action::Type::UNDEFINED: - // undefined actions are defined to be completed - default: - return true; - } - } + [[nodiscard]] bool isCompleted(const Scene& scene) const; friend std::ostream& operator<<(std::ostream& os, const Action& action); }; diff --git a/include/cell_controller.h b/include/cell_controller.h index 784f299213258fd2bd6aed5cdb97345725df1b35..617e96169d6c1da812b2e3b65c7d7e8e9f5ab664 100644 --- a/include/cell_controller.h +++ b/include/cell_controller.h @@ -37,105 +37,34 @@ public: return cell_; } - bool hasCurrentAction() const + [[maybe_unused]] bool hasCurrentAction() const { return current_action_ == nullptr; } - const Action& getCurrentAction() const + [[maybe_unused]] const Action& getCurrentAction() const { return *current_action_; } - const std::shared_ptr<Task>& getCurrentTask() const + [[maybe_unused]] const std::shared_ptr<Task>& getCurrentTask() const { return current_task_; } - void setCurrentTask(const std::shared_ptr<Task>& new_task) - { - if (!currentActionCompleted()) - { - ROS_WARN_STREAM("Cell " << cell_.id - << " got a new task although an action of the previous task is still ongoing."); - } - current_task_.reset(new_task.get()); - } + void setCurrentTask(const std::shared_ptr<Task>& new_task); - void proceedWithTask() - { - if (currentActionCompleted()) - { - auto action = triggerNextAction(); - } - } + void proceedWithTask(); - void updateModel(const std::string& scene_string) - { - ROS_INFO_STREAM("Getting a scene update for cell " << cell_.id); - - cell_.scene.ParseFromString(scene_string); - for (const auto& object : cell_.scene.objects()) - { - if (object.type() == Object_Type_ARM) - { - cell_.state = object.state() == Object_State_STATE_IDLE ? Cell::IDLE : Cell::WORKING; - break; - } - } - proceedWithTask(); - } + void updateModel(const std::string& scene_string); /** * A current action is completed if there is no current action or the current action can no longer be performed * @return */ - bool currentActionCompleted() - { - if (current_action_ == nullptr) - { - return true; - } - else if (current_action_->isCompleted(cell_.scene)) - { - // the current action is completed, but this was not registered before, so we have to set the cell state - cell_.state = Cell::IDLE; - current_action_ = nullptr; - return true; - } - else - { - return false; - } - } + bool currentActionCompleted(); - std::optional<Action> triggerNextAction() - { - if (current_action_ != nullptr && !current_action_->isCompleted(cell_.scene)) - { - return std::nullopt; - } - // TODO this assumes each action can be performed only once, which holds for pick-and-drop tasks but not in general - for (Action action : current_task_->getActions()) - { - ROS_WARN_STREAM("Action completed: " << !action.isCompleted(cell_.scene)); - if (cell_.state != Cell::WORKING && !action.isCompleted(cell_.scene) && action.canBePerformed(cell_.scene)) - { - cell_.state = Cell::WORKING; - ROS_INFO_STREAM("Triggering action " << action); - auto source = Action::lookupObject(cell_.scene, action.getSource()); - auto target = Action::lookupObject(cell_.scene, action.getTarget()); - if (!source || !target) - { - return std::nullopt; - } - current_action_ = std::make_shared<Action>(action.getType(), source->id(), target->id()); - action_callback_(*current_action_); - return action; - } - } - return std::nullopt; - } + std::optional<Action> triggerNextAction(); }; #endif // CCF_IMMERSIVE_SORTING_CELL_CONTROLLER_H_ diff --git a/src/action.cpp b/src/action.cpp index 419ba79ddaa6d16ea1e4cc87ca50a2bb78d1ad1a..94229d7837649e00e0c386c3c82e0af1547df2ac 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -11,4 +11,39 @@ std::ostream& operator<<(std::ostream& os, const Action& action) os << "[unknown action with source " << action.source_ << " and target " << action.target_ << "]"; } return os; -} \ No newline at end of file +} +std::optional<Object> Action::lookupObject(const Scene& scene, const std::string& id) +{ + for (Object object : scene.objects()) + { + // if the id can be found at position 0 + if (object.id().rfind(id, 0) == 0) + { + return object; + } + } + return std::nullopt; +} +Action::Action(Action::Type type, std::string source, std::string target) + : type_(type), source_(std::move(source)), target_(std::move(target)) +{ +} +bool Action::canBePerformed(const Scene& scene) +{ + auto s = lookupObject(scene, source_); + auto t = lookupObject(scene, target_); + return s && t && s->type() == requiredSourceType(type_) && t->type() == requiredTargetType(type_); +} +bool Action::isCompleted(const Scene& scene) const +{ + switch (type_) + { + case Action::Type::PICK_DROP: + // pick and drop is completed if the dropped element no longer exists + return !lookupObject(scene, source_).has_value(); + case Action::Type::UNDEFINED: + // undefined actions are defined to be completed + default: + return true; + } +} diff --git a/src/cell.cpp b/src/cell.cpp deleted file mode 100644 index 6c6de79faaad2b3b0c85acdd309a9a7f81526a3a..0000000000000000000000000000000000000000 --- a/src/cell.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "cell.h" diff --git a/src/cell_controller.cpp b/src/cell_controller.cpp index b6b779996ef36c46233ebd037811446c4c76c5c6..99b070521b4ac6822c7b4b66cb2080bf430ebe84 100644 --- a/src/cell_controller.cpp +++ b/src/cell_controller.cpp @@ -1 +1,77 @@ #include "cell_controller.h" +std::optional<Action> CellController::triggerNextAction() +{ + if (current_action_ != nullptr && !current_action_->isCompleted(cell_.scene)) + { + return std::nullopt; + } + // TODO this assumes each action can be performed only once, which holds for pick-and-drop tasks but not in general + for (Action action : current_task_->getActions()) + { + ROS_WARN_STREAM("Action completed: " << !action.isCompleted(cell_.scene)); + if (cell_.state != Cell::WORKING && !action.isCompleted(cell_.scene) && action.canBePerformed(cell_.scene)) + { + cell_.state = Cell::WORKING; + ROS_INFO_STREAM("Triggering action " << action); + auto source = Action::lookupObject(cell_.scene, action.getSource()); + auto target = Action::lookupObject(cell_.scene, action.getTarget()); + if (!source || !target) + { + return std::nullopt; + } + current_action_ = std::make_shared<Action>(action.getType(), source->id(), target->id()); + action_callback_(*current_action_); + return action; + } + } + return std::nullopt; +} +bool CellController::currentActionCompleted() +{ + if (current_action_ == nullptr) + { + return true; + } + else if (current_action_->isCompleted(cell_.scene)) + { + // the current action is completed, but this was not registered before, so we have to set the cell state + cell_.state = Cell::IDLE; + current_action_ = nullptr; + return true; + } + else + { + return false; + } +} +void CellController::updateModel(const std::string& scene_string) +{ + ROS_INFO_STREAM("Getting a scene update for cell " << cell_.id); + + cell_.scene.ParseFromString(scene_string); + for (const auto& object : cell_.scene.objects()) + { + if (object.type() == Object_Type_ARM) + { + cell_.state = object.state() == Object_State_STATE_IDLE ? Cell::IDLE : Cell::WORKING; + break; + } + } + proceedWithTask(); +} +void CellController::setCurrentTask(const std::shared_ptr<Task>& new_task) +{ + if (!currentActionCompleted()) + { + ROS_WARN_STREAM("Cell " << cell_.id + << " got a new task although an action of the previous task is still ongoing."); + } + current_task_.reset(new_task.get()); +} +void CellController::proceedWithTask() +{ + if (currentActionCompleted()) + { + auto action = triggerNextAction(); + } +} diff --git a/src/task.cpp b/src/task.cpp deleted file mode 100644 index 204c27c5737a9215ca00e5dc65d81329fa4a6c40..0000000000000000000000000000000000000000 --- a/src/task.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "task.h"