SHOW:
|
|
- or go back to the newest paste.
| 1 | Send goal to robot | |
| 2 | ---------------- | |
| 3 | #include <ros/ros.h> | |
| 4 | #include <move_base_msgs/MoveBaseAction.h> | |
| 5 | #include <actionlib/client/simple_action_client.h> | |
| 6 | #include <trsimcpp/threadsafe_stack_wrapper.h> | |
| 7 | #include <future> // std::async, std::future | |
| 8 | // Initialize stack with -1 error value | |
| 9 | threadsafe_stack<int> mystack(-1,1); | |
| 10 | ||
| 11 | typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient; | |
| 12 | ||
| 13 | void sendgoal(std::string robot_name) | |
| 14 | {
| |
| 15 | //tell the action client that we want to spin a thread by default | |
| 16 | ||
| 17 | MoveBaseClient ac("/" + robot_name + "/move_base", true);
| |
| 18 | ||
| 19 | //wait for the action server to come up | |
| 20 | while(!ac.waitForServer(ros::Duration(5.0))){
| |
| 21 | ROS_INFO("Waiting for the move_base action server to come up");
| |
| 22 | } | |
| 23 | ||
| 24 | move_base_msgs::MoveBaseGoal goal; | |
| 25 | ||
| 26 | //we'll send a goal to the robot to move 1 meter forward | |
| 27 | goal.target_pose.header.frame_id = "map"; | |
| 28 | goal.target_pose.header.stamp = ros::Time::now(); | |
| 29 | ||
| 30 | goal.target_pose.pose.position.x = 3.0; | |
| 31 | goal.target_pose.pose.orientation.w = 1.0; | |
| 32 | ||
| 33 | ROS_INFO("Sending goal");
| |
| 34 | ac.sendGoal(goal); | |
| 35 | ||
| 36 | ac.waitForResult(); | |
| 37 | ||
| 38 | if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) | |
| 39 | ROS_INFO("Status:1");
| |
| 40 | else | |
| 41 | ROS_INFO("Status:0");
| |
| 42 | ||
| 43 | } | |
| 44 | ||
| 45 | ||
| 46 | int main(int argc, char** argv){
| |
| 47 | ros::init(argc, argv, "simple_navigation_goals"); | |
| 48 | // Hold an election | |
| 49 | auto f1 = std::async(std::launch::async,pop); | |
| 50 | auto f2 = std::async(std::launch::async,pop); | |
| 51 | ||
| 52 | ||
| 53 | if(f1.get() != -1) | |
| 54 | {
| |
| 55 | std::cout <<"robot 1 won!\n"; | |
| 56 | sendgoal("robot1");
| |
| 57 | } | |
| 58 | else | |
| 59 | {
| |
| 60 | std::cout<<"robot 2 won!\n"; | |
| 61 | sendgoal("robot2");
| |
| 62 | } | |
| 63 | ||
| 64 | ||
| 65 | ||
| 66 | return 0; | |
| 67 | - | } |
| 67 | + | |
| 68 | ||
| 69 | ||
| 70 | =========== | |
| 71 | ||
| 72 | #ifndef THREADSAFE_STACK_H | |
| 73 | #define THREADSAFE_STACK_H | |
| 74 | #include <stack> | |
| 75 | #include <mutex> | |
| 76 | #include <memory> | |
| 77 | #include <algorithm> | |
| 78 | #include <cassert> | |
| 79 | ||
| 80 | /* | |
| 81 | This stack can contain at max 1 element, pushed at the time of creation. | |
| 82 | One item can be popped, after which EMPTY_STACK error is returned. | |
| 83 | */ | |
| 84 | ||
| 85 | ||
| 86 | template<typename T> | |
| 87 | class threadsafe_stack | |
| 88 | {
| |
| 89 | public: | |
| 90 | ||
| 91 | threadsafe_stack(T EMPTY_STACK_, T initval):EMPTY_STACK(EMPTY_STACK_) | |
| 92 | {
| |
| 93 | std::lock_guard<std::mutex> lock(m); | |
| 94 | data.push(initval); | |
| 95 | } | |
| 96 | ||
| 97 | threadsafe_stack(const threadsafe_stack &other): EMPTY_STACK(other.EMPTY_STACK) | |
| 98 | {
| |
| 99 | // From Williams' book | |
| 100 | std::lock_guard<std::mutex> lock2(other.m); | |
| 101 | assert (other.data.size() == 1); | |
| 102 | data.push(other.data.top()); | |
| 103 | } | |
| 104 | ||
| 105 | threadsafe_stack& operator = (const threadsafe_stack&) = delete; | |
| 106 | ||
| 107 | T pop() | |
| 108 | {
| |
| 109 | std::lock_guard<std::mutex> lock(m); | |
| 110 | T rv = EMPTY_STACK; | |
| 111 | if(!data.empty()) | |
| 112 | {
| |
| 113 | rv = data.top(); | |
| 114 | data.pop(); | |
| 115 | } | |
| 116 | return rv; | |
| 117 | } | |
| 118 | ||
| 119 | ||
| 120 | ||
| 121 | private: | |
| 122 | std::stack<T> data; | |
| 123 | mutable std::mutex m; | |
| 124 | const T EMPTY_STACK; | |
| 125 | }; |