Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef TOPIC_PROXY_SERVICE_CLIENT_H
00030 #define TOPIC_PROXY_SERVICE_CLIENT_H
00031
00032 #include <ros/forwards.h>
00033 #include <ros/common.h>
00034 #include <ros/service_traits.h>
00035 #include <ros/serialization.h>
00036
00037 namespace topic_proxy
00038 {
00039
00040 class ServiceClient {
00041 public:
00042 ServiceClient();
00043 ServiceClient(const ServiceClient& rhs);
00044 ~ServiceClient();
00045
00046 template <typename Service>
00047 ServiceClient(const std::string& service_name, const std::string& host = std::string(), uint32_t port = 0, const ros::M_string& header_values = ros::M_string())
00048 {
00049 init<Service>(service_name, host, port, header_values);
00050 }
00051
00052 template <typename Service>
00053 bool init(const std::string& service_name, std::string host = std::string(), uint32_t port = 0, const ros::M_string& header_values = ros::M_string())
00054 {
00055 return init(service_name, std::string(ros::service_traits::md5sum<Service>()), host, port, header_values);
00056 }
00057
00058 bool init(const std::string& service_name, const std::string& service_md5sum, std::string host = std::string(), uint32_t port = 0, const ros::M_string& header_values = ros::M_string());
00059
00064 template<class MReq, class MRes>
00065 bool call(MReq& req, MRes& res)
00066 {
00067 namespace st = ros::service_traits;
00068
00069 if (!isValid())
00070 {
00071 return false;
00072 }
00073
00074 if (strcmp(st::md5sum(req), st::md5sum(res)))
00075 {
00076 ROS_ERROR("The request and response parameters to the service "
00077 "call must be autogenerated from the same "
00078 "server definition file (.srv). your service call "
00079 "for %s appeared to use request/response types "
00080 "from different .srv files. (%s vs. %s)", impl_->name_.c_str(), st::md5sum(req), st::md5sum(res));
00081 return false;
00082 }
00083
00084 return call(req, res, st::md5sum(req));
00085 }
00086
00090 template<class Service>
00091 bool call(Service& service)
00092 {
00093 namespace st = ros::service_traits;
00094
00095 if (!isValid())
00096 {
00097 return false;
00098 }
00099
00100 return call(service.request, service.response, st::md5sum(service));
00101 }
00102
00106 template<typename MReq, typename MRes>
00107 bool call(const MReq& req, MRes& resp, const std::string& service_md5sum)
00108 {
00109 namespace ser = ros::serialization;
00110 ros::SerializedMessage ser_req = ser::serializeMessage(req);
00111 ros::SerializedMessage ser_resp;
00112 bool ok = call(ser_req, ser_resp, service_md5sum);
00113 if (!ok)
00114 {
00115 return false;
00116 }
00117
00118 try
00119 {
00120 ser::deserializeMessage(ser_resp, resp);
00121 }
00122 catch (std::exception& e)
00123 {
00124 deserializeFailed(e);
00125 return false;
00126 }
00127
00128 return true;
00129 }
00130
00131 bool call(const ros::SerializedMessage& req, ros::SerializedMessage& resp, const std::string& service_md5sum);
00132
00137 bool isValid() const;
00138
00147 void shutdown();
00148
00152 std::string getService();
00153
00154 private:
00155
00156
00157
00158 void deserializeFailed(const std::exception& e)
00159 {
00160 ROS_ERROR("Exception thrown while while deserializing service call: %s", e.what());
00161 }
00162
00163 struct Impl
00164 {
00165 Impl();
00166 ~Impl();
00167
00168 void shutdown();
00169 bool isValid() const;
00170
00171 ros::ServiceServerLinkPtr server_link_;
00172 std::string name_;
00173 ros::M_string header_values_;
00174 bool is_shutdown_;
00175 };
00176 typedef boost::shared_ptr<Impl> ImplPtr;
00177 typedef boost::weak_ptr<Impl> ImplWPtr;
00178
00179 ImplPtr impl_;
00180 };
00181
00182 }
00183
00184 #endif // TOPIC_PROXY_SERVICE_CLIENT_H