rm_control
Loading...
Searching...
No Matches
service_caller.h
Go to the documentation of this file.
1/*******************************************************************************
2 * BSD 3-Clause License
3 *
4 * Copyright (c) 2021, Qiayuan Liao
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * * Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *******************************************************************************/
33
34//
35// Created by qiayuan on 5/22/21.
36//
37
38#pragma once
39
40#include <chrono>
41#include <mutex>
42#include <thread>
43#include <utility>
44#include <ros/ros.h>
45#include <ros/service.h>
46#include <controller_manager_msgs/SwitchController.h>
47#include <control_msgs/QueryCalibrationState.h>
48#include <rm_msgs/StatusChange.h>
49#include <std_srvs/Empty.h>
50#include <std_srvs/SetBool.h>
51#include <std_srvs/Trigger.h>
52
53namespace rm_common
54{
55template <class ServiceType>
57{
58public:
59 explicit ServiceCallerBase(ros::NodeHandle& nh, const std::string& service_name = "") : fail_count_(0), fail_limit_(0)
60 {
61 nh.param("fail_limit", fail_limit_, 0);
62 if (!nh.param("service_name", service_name_, service_name) && service_name.empty())
63 {
64 ROS_ERROR("Service name no defined (namespace: %s)", nh.getNamespace().c_str());
65 return;
66 }
67 client_ = nh.serviceClient<ServiceType>(service_name_);
68 }
69 ServiceCallerBase(ros::NodeHandle& nh, std::string& service_name) : fail_count_(0), fail_limit_(0)
70 {
71 service_name_ = service_name;
72 client_ = nh.serviceClient<ServiceType>(service_name_);
73 }
74 ServiceCallerBase(XmlRpc::XmlRpcValue& controllers, ros::NodeHandle& nh, const std::string& service_name = "")
76 {
77 if (controllers.hasMember("service_name"))
78 service_name_ = static_cast<std::string>(controllers["service_name"]);
79 else
80 {
81 service_name_ = service_name;
82 if (service_name.empty())
83 {
84 ROS_ERROR("Service name no defined (namespace: %s)", nh.getNamespace().c_str());
85 return;
86 }
87 }
88 client_ = nh.serviceClient<ServiceType>(service_name_);
89 }
91 {
92 delete thread_;
93 }
95 {
96 if (isCalling())
97 return;
98 thread_ = new std::thread(&ServiceCallerBase::callingThread, this);
99 thread_->detach();
100 }
101 ServiceType& getService()
102 {
103 return service_;
104 }
106 {
107 std::unique_lock<std::mutex> guard(mutex_, std::try_to_lock);
108 return !guard.owns_lock();
109 }
110
111protected:
113 {
114 std::lock_guard<std::mutex> guard(mutex_);
115 if (!client_.call(service_))
116 {
117 ROS_INFO_ONCE("Failed to call service %s on %s. Retrying now ...", typeid(ServiceType).name(),
118 service_name_.c_str());
119 if (fail_limit_ != 0)
120 {
121 fail_count_++;
122 if (fail_count_ >= fail_limit_)
123 {
124 ROS_ERROR_ONCE("Failed to call service %s on %s", typeid(ServiceType).name(), service_name_.c_str());
125 fail_count_ = 0;
126 }
127 }
128 // ros::WallDuration(0.2).sleep();
129 }
130 }
131 std::string service_name_;
132 ros::ServiceClient client_;
133 ServiceType service_;
134 std::thread* thread_{};
135 std::mutex mutex_;
136 int fail_count_, fail_limit_;
137};
138
139class ColorChangeServiceCaller : public ServiceCallerBase<std_srvs::SetBool>
140{
141public:
142 explicit ColorChangeServiceCaller(ros::NodeHandle& nh)
143 : ServiceCallerBase<std_srvs::SetBool>(nh, "/superpower_track_vision/change_color")
144 {
145 service_.request.data = false;
146 callService();
147 }
149 {
150 service_.request.data = !service_.request.data;
151 callService();
152 }
153};
154
155class TrackerResetServiceCaller : public ServiceCallerBase<std_srvs::Trigger>
156{
157public:
158 explicit TrackerResetServiceCaller(ros::NodeHandle& nh)
159 : ServiceCallerBase<std_srvs::Trigger>(nh, "/superpower_track/reset")
160 {
161 callService();
162 }
163 void reset()
164 {
165 callService();
166 }
167};
168class SwitchControllersServiceCaller : public ServiceCallerBase<controller_manager_msgs::SwitchController>
169{
170public:
171 explicit SwitchControllersServiceCaller(ros::NodeHandle& nh)
172 : ServiceCallerBase<controller_manager_msgs::SwitchController>(nh, "/controller_manager/switch_controller")
173 {
174 service_.request.strictness = service_.request.BEST_EFFORT;
175 service_.request.start_asap = true;
176 }
177 void startControllers(const std::vector<std::string>& controllers)
178 {
179 service_.request.start_controllers = controllers;
180 }
181 void stopControllers(const std::vector<std::string>& controllers)
182 {
183 service_.request.stop_controllers = controllers;
184 }
185 bool getOk()
186 {
187 if (isCalling())
188 return false;
189 return service_.response.ok;
190 }
191};
192
193class QueryCalibrationServiceCaller : public ServiceCallerBase<control_msgs::QueryCalibrationState>
194{
195public:
196 explicit QueryCalibrationServiceCaller(ros::NodeHandle& nh)
197 : ServiceCallerBase<control_msgs::QueryCalibrationState>(nh)
198 {
199 }
200 QueryCalibrationServiceCaller(ros::NodeHandle& nh, std::string& service_name)
201 : ServiceCallerBase<control_msgs::QueryCalibrationState>(nh, service_name)
202 {
203 }
204 QueryCalibrationServiceCaller(XmlRpc::XmlRpcValue& controllers, ros::NodeHandle& nh)
205 : ServiceCallerBase<control_msgs::QueryCalibrationState>(controllers, nh)
206 {
207 }
209 {
210 if (isCalling())
211 return false;
212 return service_.response.is_calibrated;
213 }
214};
215
216class SwitchDetectionCaller : public ServiceCallerBase<rm_msgs::StatusChange>
217{
218public:
219 explicit SwitchDetectionCaller(ros::NodeHandle& nh)
220 : ServiceCallerBase<rm_msgs::StatusChange>(nh, "/Processor/status_change")
221 {
222 service_.request.target = rm_msgs::StatusChangeRequest::ARMOR;
223 service_.request.exposure = rm_msgs::StatusChangeRequest::EXPOSURE_LEVEL_0;
224 service_.request.armor_target = rm_msgs::StatusChangeRequest::ARMOR_ALL;
225 callService();
226 }
227
228 explicit SwitchDetectionCaller(ros::NodeHandle& nh, std::string service_name)
229 : ServiceCallerBase<rm_msgs::StatusChange>(nh, service_name)
230 {
231 service_.request.target = rm_msgs::StatusChangeRequest::ARMOR;
232 service_.request.exposure = rm_msgs::StatusChangeRequest::EXPOSURE_LEVEL_0;
233 service_.request.armor_target = rm_msgs::StatusChangeRequest::ARMOR_ALL;
234 callService();
235 }
236
237 void setEnemyColor(const int& robot_id_, const std::string& robot_color_)
238 {
239 if (robot_id_ != 0)
240 {
241 service_.request.color =
242 robot_color_ == "blue" ? rm_msgs::StatusChangeRequest::RED : rm_msgs::StatusChangeRequest::BLUE;
243 ROS_INFO_STREAM("Set enemy color: " << (service_.request.color == service_.request.RED ? "red" : "blue"));
244
245 callService();
246 }
247 else
248 ROS_INFO_STREAM("Set enemy color failed: referee offline");
249 }
250 void setColor(uint8_t color)
251 {
252 service_.request.color = color;
253 }
255 {
256 service_.request.color = service_.request.color == rm_msgs::StatusChangeRequest::RED;
257 }
259 {
260 service_.request.target = service_.request.target == rm_msgs::StatusChangeRequest::ARMOR;
261 }
262 void setTargetType(uint8_t target)
263 {
264 service_.request.target = target;
265 }
267 {
268 service_.request.armor_target = service_.request.armor_target == rm_msgs::StatusChangeRequest::ARMOR_ALL;
269 }
270 void setArmorTargetType(uint8_t armor_target)
271 {
272 service_.request.armor_target = armor_target;
273 }
275 {
276 service_.request.exposure = service_.request.exposure == rm_msgs::StatusChangeRequest::EXPOSURE_LEVEL_4 ?
277 rm_msgs::StatusChangeRequest::EXPOSURE_LEVEL_0 :
278 service_.request.exposure + 1;
279 }
281 {
282 return service_.request.color;
283 }
285 {
286 return service_.request.target;
287 }
289 {
290 return service_.request.armor_target;
291 }
293 {
294 return service_.request.exposure;
295 }
297 {
298 if (isCalling())
299 return false;
300 return service_.response.switch_is_success;
301 }
302
303private:
304 bool is_set_{};
305};
306
307} // namespace rm_common
Definition service_caller.h:140
void changeColor()
Definition service_caller.h:148
ColorChangeServiceCaller(ros::NodeHandle &nh)
Definition service_caller.h:142
Definition service_caller.h:194
QueryCalibrationServiceCaller(ros::NodeHandle &nh, std::string &service_name)
Definition service_caller.h:200
QueryCalibrationServiceCaller(XmlRpc::XmlRpcValue &controllers, ros::NodeHandle &nh)
Definition service_caller.h:204
bool isCalibrated()
Definition service_caller.h:208
QueryCalibrationServiceCaller(ros::NodeHandle &nh)
Definition service_caller.h:196
Definition service_caller.h:57
std::mutex mutex_
Definition service_caller.h:135
int fail_limit_
Definition service_caller.h:136
bool isCalling()
Definition service_caller.h:105
ros::ServiceClient client_
Definition service_caller.h:132
ServiceCallerBase(ros::NodeHandle &nh, std::string &service_name)
Definition service_caller.h:69
ServiceCallerBase(XmlRpc::XmlRpcValue &controllers, ros::NodeHandle &nh, const std::string &service_name="")
Definition service_caller.h:74
std::string service_name_
Definition service_caller.h:131
int fail_count_
Definition service_caller.h:136
ServiceType & getService()
Definition service_caller.h:101
ServiceCallerBase(ros::NodeHandle &nh, const std::string &service_name="")
Definition service_caller.h:59
~ServiceCallerBase()
Definition service_caller.h:90
ServiceType service_
Definition service_caller.h:133
void callService()
Definition service_caller.h:94
void callingThread()
Definition service_caller.h:112
Definition service_caller.h:169
void startControllers(const std::vector< std::string > &controllers)
Definition service_caller.h:177
void stopControllers(const std::vector< std::string > &controllers)
Definition service_caller.h:181
bool getOk()
Definition service_caller.h:185
SwitchControllersServiceCaller(ros::NodeHandle &nh)
Definition service_caller.h:171
Definition service_caller.h:217
int getArmorTarget()
Definition service_caller.h:288
void setColor(uint8_t color)
Definition service_caller.h:250
void switchTargetType()
Definition service_caller.h:258
SwitchDetectionCaller(ros::NodeHandle &nh, std::string service_name)
Definition service_caller.h:228
void setTargetType(uint8_t target)
Definition service_caller.h:262
void setArmorTargetType(uint8_t armor_target)
Definition service_caller.h:270
int getTarget()
Definition service_caller.h:284
void switchArmorTargetType()
Definition service_caller.h:266
int getColor()
Definition service_caller.h:280
void switchEnemyColor()
Definition service_caller.h:254
uint8_t getExposureLevel()
Definition service_caller.h:292
bool getIsSwitch()
Definition service_caller.h:296
SwitchDetectionCaller(ros::NodeHandle &nh)
Definition service_caller.h:219
void setEnemyColor(const int &robot_id_, const std::string &robot_color_)
Definition service_caller.h:237
void switchExposureLevel()
Definition service_caller.h:274
Definition service_caller.h:156
void reset()
Definition service_caller.h:163
TrackerResetServiceCaller(ros::NodeHandle &nh)
Definition service_caller.h:158
Definition calibration_queue.h:44