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 | }; |