diff --git a/include/mediator/mg_mediator.h b/include/mediator/mg_mediator.h index 7752625c5f68e60be3943512c25b660b8db1cb00..7d7d9e7f96938d2c2ad18feff3c0e37a4619e1a2 100644 --- a/include/mediator/mg_mediator.h +++ b/include/mediator/mg_mediator.h @@ -47,7 +47,7 @@ class MGMediator: public AbstractMediator, virtual Controller{ std::unique_ptr<moveit::planning_interface::PlanningSceneInterface> psi_; //!< PlanningSceneInteface to manage Scene Objects std::map<std::string, std::vector<uint8_t>> acm_; //!< shared allowed collision matrix between robots std::map<std::string, std::vector<uint8_t>> rs_; //!< shared robot state between all robots - std::shared_ptr<planning_scene::PlanningScene> ps_; //!< Shared Planning Scene + std::shared_ptr<moveit_msgs::PlanningScene> ps_; //!< Shared Planning Scene @@ -79,6 +79,11 @@ class MGMediator: public AbstractMediator, virtual Controller{ moveit::task_constructor::Task place(const std::string& obj, const std::string& robotId, const std::string& target); moveit::task_constructor::Task drop(const std::string& obj, const std::string& robotId, const std::string& drop); + void manipulateACM(moveit_msgs::PlanningScene& ps, const std::string& robotId); + void parallelExec(const moveit_task_constructor_msgs::SubTrajectory st, const std::string& robotId); + void mergePS(const moveit_msgs::PlanningScene& in, const std::string& robotId); + void mergeACM(); + void processSharedStructure(); void setupMqtt(); diff --git a/src/mediator/mg_mediator.cpp b/src/mediator/mg_mediator.cpp index a298446ddda552cfe08d00328facb913c8c54112..2a493ab656d6b12a076be04ab95f80fb232fc62d 100644 --- a/src/mediator/mg_mediator.cpp +++ b/src/mediator/mg_mediator.cpp @@ -6,6 +6,86 @@ std::vector<std::pair<std::string,moveit_task_constructor_msgs::ExecuteTaskSolut std::mutex shared_mutex; std::condition_variable cv; + +void MGMediator::mergeACM(){ + moveit_msgs::PlanningScene::_allowed_collision_matrix_type acmt; + acmt.entry_values.resize(acm_.size()); + + int i = 0; + for (auto& a : acm_){ + acmt.entry_names.push_back(a.first); + acmt.entry_values[i].enabled = a.second; + i++; + } + + ps_->allowed_collision_matrix = acmt; +} + +void MGMediator::parallelExec(moveit_task_constructor_msgs::SubTrajectory st, const std::string& robotId){ + { + std::unique_lock<std::mutex> lock(shared_mutex); + manipulateACM(st.scene_diff, robotId); + mergePS(st.scene_diff, robotId); + } + + AbstractRobotDecorator* mr = nullptr; + { + std::unique_lock<std::mutex> lock(shared_mutex); + mr= robots_.at(robotId).get(); + } + mr->mgi()->execute(st.trajectory); +} + +void MGMediator::mergePS(const moveit_msgs::PlanningScene& in, const std::string& robotId){ + // get full mr link list + if (!ps_){ + ps_ = std::make_shared<moveit_msgs::PlanningScene>(in); + return; + } + + AbstractRobotDecorator* mr = nullptr; + { + std::unique_lock<std::mutex> lock(shared_mutex); + mr= robots_.at(robotId).get(); + } + + for (auto ao : in.robot_state.attached_collision_objects) ps_->robot_state.attached_collision_objects.push_back(ao); + ps_->robot_state.is_diff |= in.robot_state.is_diff; + ps_->is_diff |= in.is_diff; + ps_->robot_state.joint_state.header = in.robot_state.joint_state.header; + ps_->robot_model_name = "panda"; + + std::vector<std::string> links; + for (auto link : mr->mgi()->getLinkNames()) links.push_back(link); + links.push_back(mr->map()["left_finger"]); + links.push_back(mr->map()["right_finger"]); + links.push_back(mr->map()["hand_link"]); + links.push_back(mr->map()["base"]); + + for (auto link : links) { + for(int i = 0; i < in.robot_state.joint_state.name.size(); i++){ + if(link == in.robot_state.joint_state.name[i]){ + ps_->robot_state.joint_state.effort.push_back(in.robot_state.joint_state.effort[i]); + ps_->robot_state.joint_state.position.push_back(in.robot_state.joint_state.position[i]); + ps_->robot_state.joint_state.velocity.push_back(in.robot_state.joint_state.velocity[i]); + } + } + + for(int i = 0; i < in.link_padding.size(); i++){ + if(link == in.link_padding[i].link_name){ + ps_->link_padding.push_back(in.link_padding[i]); + } + } + + for(int i = 0; i < in.link_scale.size(); i++){ + if(link == in.link_scale[i].link_name){ + ps_->link_scale.push_back(in.link_scale[i]); + } + } + } +} + + void MGMediator::processSharedStructure() { while (ros::ok()) { std::vector<std::pair<std::string, moveit_task_constructor_msgs::SubTrajectory>> peak; @@ -24,14 +104,7 @@ void MGMediator::processSharedStructure() { it->second.solution.sub_trajectory.erase(it->second.solution.sub_trajectory.begin()); } - if (it->second.solution.sub_trajectory.empty() && it->first == "panda_arm1") { - /* - All sub_trajectorys of an Robot are done, so the grammar should be informed about the state - */ - std::stringstream ss; - ss << it->first << "/idle"; - sendToAll(ss.str(), ""); - + if (it->second.solution.sub_trajectory.empty()) { /* Lets publish also scene modifications here But I want to publish only vanished objects @@ -39,22 +112,28 @@ void MGMediator::processSharedStructure() { */ std::string temp; - if ((cuboid_reader_->cuboidBox().size() + cuboid_reader_->cuboidBox().size()) > psi_->getObjects().size()){ + try{ + for (const auto& c : cuboid_reader_->cuboidBox()){ + temp = c.Name; + psi_->getObjects().at(c.Name); + } + } catch (const std::out_of_range& e) { ROS_INFO("object is vanished!"); - try{ - for (const auto& c : cuboid_reader_->cuboidBox()){ - temp = c.Name; - psi_->getObjects().at(c.Name); - } - } catch (const std::out_of_range& e) { - std::stringstream payload; - payload << "{\"type\": \"MODIFY\", \"mode\": \"DELETE\", \"robot\": \""<< it->first <<"\", \"object\": \""<< temp <<"\" }"; - - std::stringstream payload_topic; - payload_topic << it->first << "/payload"; - sendToAll(payload_topic.str(), payload.str()); - } - } + std::stringstream payload; + payload << "{\"type\": \"MODIFY\", \"mode\": \"DELETE\", \"robot\": \""<< it->first <<"\", \"object\": \""<< temp <<"\" }"; + + std::stringstream payload_topic; + payload_topic << it->first << "/payload"; + sendToAll(payload_topic.str(), payload.str()); + } + + + /* + All sub_trajectorys of an Robot are done, so the grammar should be informed about the state + */ + std::stringstream ss; + ss << it->first << "/idle"; + sendToAll(ss.str(), ""); it = shared_structure.erase(it); @@ -62,22 +141,22 @@ void MGMediator::processSharedStructure() { } } - } - + } + + std::vector<std::thread> th; for (const auto& exec : peak){ - if(exec.first == "panda_arm1"){ - AbstractRobotDecorator* mr = nullptr; - try{ - mr= robots_.at(exec.first).get(); - mr->mgi()->execute(exec.second.trajectory); - planning_scene_diff_publisher_->publish(exec.second.scene_diff); - } catch (std::out_of_range& oor){ - ROS_INFO("Robot not found"); - ros::shutdown(); - } - } + th.push_back(std::thread(&MGMediator::parallelExec, this, exec.second, std::ref(exec.first))); + } + + for(auto& t : th){ + t.join(); + } + mergeACM(); + planning_scene_diff_publisher_->publish(*ps_); + + // The lock is automatically released here when `lock` goes out of scope // Print the sizes of the sub_trajectory vectors @@ -103,6 +182,7 @@ MGMediator::MGMediator(std::shared_ptr<ros::NodeHandle> const& nh) , cartesian_planner_(std::make_unique<moveit::task_constructor::solvers::CartesianPath>()) , psi_(std::make_unique<moveit::planning_interface::PlanningSceneInterface>()) , mgi_(std::make_shared<moveit::planning_interface::MoveGroupInterface>("panda_arms")) +, ps_(nullptr) , planning_scene_diff_publisher_(std::make_shared<ros::Publisher>(nh_->advertise<moveit_msgs::PlanningScene>("planning_scene", 1))){ @@ -868,7 +948,7 @@ void MGMediator::publishTables(){ ss << ",{\"id\": \"" << c.Name <<"\",\"type\": \"BOX\",\"pos\": {\"x\": "<< c.Pose.position.x << ",\"y\": "<< c.Pose.position.y <<",\"z\": " << c.Pose.position.x << "},\"size\": {\"length\": "<< c.x_depth <<",\"width\": "<< c.y_width <<",\"height\": "<< c.z_heigth <<"},\"orientation\": {\"x\": "<< c.Pose.orientation.x <<", \"y\": "<< c.Pose.orientation.y <<" , \"z\": "<< c.Pose.orientation.z <<", \"w\": "<< c.Pose.orientation.w<< "},"; ss << "\"color\": {\"r\": 0.2,\"g\": 0.2,\"b\": 0.2}}"; } - // acm_.insert(std::pair<std::string, std::vector<uint8_t>>(item.id, std::vector<uint8_t>())); + acm_.insert(std::pair<std::string, std::vector<uint8_t>>(c.Name, std::vector<uint8_t>())); } for (auto& c: cuboid_reader_->cuboidObstacle()){ @@ -877,6 +957,7 @@ void MGMediator::publishTables(){ ss << ",{\"id\": \"" << c.Name <<"\",\"type\": \"BIN\",\"pos\": {\"x\": "<< c.Pose.position.x << ",\"y\": "<< c.Pose.position.y <<",\"z\": " << c.Pose.position.x << "},\"size\": {\"length\": "<< c.x_depth <<",\"width\": "<< c.y_width <<",\"height\": "<< c.z_heigth <<"},\"orientation\": {\"x\": "<< c.Pose.orientation.x <<", \"y\": "<< c.Pose.orientation.y <<" , \"z\": "<< c.Pose.orientation.z <<", \"w\": "<< c.Pose.orientation.w<< "},"; ss << "\"color\": {\"r\": 0.2,\"g\": 0.2,\"b\": 0.2}}"; } + acm_.insert(std::pair<std::string, std::vector<uint8_t>>(c.Name, std::vector<uint8_t>())); } ss << "]}"; @@ -978,3 +1059,230 @@ void MGMediator::setPanel(){ s_r.second->notify(); } } + +void MGMediator::manipulateACM(moveit_msgs::PlanningScene& ps, const std::string& robotId){ + + AbstractRobotDecorator* mr = nullptr; + try{ + mr= robots_.at(robotId).get(); + } catch (std::out_of_range& oor){ + ROS_INFO("Robot not found"); + ros::shutdown(); + } + // First find ID from panda to start with + std::regex rx_panda(mr->pattern()); + std::smatch match; + std::regex_match(mr->name(), match, rx_panda); + + // build panda link regex + std::stringstream ss; + ss << "panda_" << match[1] << "_.*"; + std::regex rx_panda_links(ss.str()); + std::regex rx_table("table.*"); + + + // Iterate task collsion matrix + for(int j = 0; j < ps.allowed_collision_matrix.entry_names.size(); j++ ){ + if( mr->map().at("base") == ps.allowed_collision_matrix.entry_names[j]){ + //In case an entry matches an robot spezific link + + for(int k = 0; k < ps.allowed_collision_matrix.entry_values[j].enabled.size(); k++){ + // For that specific entry, loop over values + int distance = std::distance(acm_.begin(),acm_.find(ps.allowed_collision_matrix.entry_names[k])); + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_panda_links)){ + acm_.at(mr->map().at("base"))[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + /* + BOX -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidBox()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(mr->map().at("base"))[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidObstacle()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(mr->map().at("base"))[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_table)){ + acm_.at(mr->map().at("base"))[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + if (mr->map().at("base")== ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(mr->map().at("base"))[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + } + + if(std::regex_match(ps.allowed_collision_matrix.entry_names[j], match, rx_panda_links)){ + //In case an entry matches an robot spezific link + ROS_INFO("entry matches link %s at index %i", ps.allowed_collision_matrix.entry_names[j].c_str(), j); + for(int k = 0; k < ps.allowed_collision_matrix.entry_values[j].enabled.size(); k++){ + //For that specific entry, loop over values + int distance = std::distance(acm_.begin(),acm_.find(ps.allowed_collision_matrix.entry_names[k])); + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_panda_links)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + /* + BOX -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidBox()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidObstacle()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_table)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + if (mr->map().at("base")== ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + } + + /* + BOX -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidBox()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[j]){ + for(int k = 0; k < ps.allowed_collision_matrix.entry_values[j].enabled.size(); k++){ + //For that specific entry, loop over values + int distance = std::distance(acm_.begin(),acm_.find(ps.allowed_collision_matrix.entry_names[k])); + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_panda_links)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + + /* + BOX -> Based on the context + */ + for (const auto& c1 : cuboid_reader_->cuboidBox()) { + if (c1.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c1 : cuboid_reader_->cuboidObstacle()) { + if (c1.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_table)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + if (mr->map().at("base")== ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidObstacle()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[j]){ + for(int k = 0; k < ps.allowed_collision_matrix.entry_values[j].enabled.size(); k++){ + //For that specific entry, loop over values + int distance = std::distance(acm_.begin(),acm_.find(ps.allowed_collision_matrix.entry_names[k])); + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_panda_links)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + /* + BOX -> Based on the context + */ + for (const auto& c1 : cuboid_reader_->cuboidBox()) { + if (c1.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c1 : cuboid_reader_->cuboidObstacle()) { + if (c1.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_table)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + if (mr->map().at("base")== ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + } + } + + if(std::regex_match(ps.allowed_collision_matrix.entry_names[j], match, rx_table)){ + //In case an entry matches an robot spezific link + for(int k = 0; k < ps.allowed_collision_matrix.entry_values[j].enabled.size(); k++){ + //For that specific entry, loop over values + int distance = std::distance(acm_.begin(),acm_.find(ps.allowed_collision_matrix.entry_names[k])); + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_panda_links)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + /* + BOX -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidBox()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + /* + BIN -> Based on the context + */ + for (const auto& c : cuboid_reader_->cuboidObstacle()) { + if (c.Name == ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + + if (std::regex_match(ps.allowed_collision_matrix.entry_names[k], match, rx_table)){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + + if (mr->map().at("base")== ps.allowed_collision_matrix.entry_names[k]){ + acm_.at(ps.allowed_collision_matrix.entry_names[j])[distance] = ps.allowed_collision_matrix.entry_values[j].enabled[k]; + } + } + } + } +} + diff --git a/src/mg_routine.cpp b/src/mg_routine.cpp index 333250c348256f1bd2e18c1667f8f9785565c60c..1f27a6d65ba730ab87d70a385e7da4e329e901d8 100644 --- a/src/mg_routine.cpp +++ b/src/mg_routine.cpp @@ -18,7 +18,7 @@ int main(int argc, char **argv){ ros::init(argc, argv, "mg_routine"); std::shared_ptr<ros::NodeHandle> n(new ros::NodeHandle); - ros::AsyncSpinner spinner(4); + ros::AsyncSpinner spinner(6); spinner.start(); std::shared_ptr<MGMediator> mediator = std::make_shared<MGMediator>(n);