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 #ifndef ROSCPP_SERVICE_CLIENT_H
00029 #define ROSCPP_SERVICE_CLIENT_H
00030
00031 #include "ros/forwards.h"
00032 #include "ros/common.h"
00033 #include "ros/service_traits.h"
00034 #include "ros/serialization.h"
00035
00036 namespace ros
00037 {
00038
00042 class ServiceClient
00043 {
00044 public:
00045 ServiceClient() {}
00046 ServiceClient(const std::string& service_name, bool persistent, const M_string& header_values, const std::string& service_md5sum);
00047 ServiceClient(const ServiceClient& rhs);
00048 ~ServiceClient();
00049
00054 template<class MReq, class MRes>
00055 bool call(MReq& req, MRes& res)
00056 {
00057 namespace st = service_traits;
00058
00059 if (!isValid())
00060 {
00061 return false;
00062 }
00063
00064 if (strcmp(st::md5sum(req), st::md5sum(res)))
00065 {
00066 ROS_ERROR("The request and response parameters to the service "
00067 "call must be autogenerated from the same "
00068 "server definition file (.srv). your service call "
00069 "for %s appeared to use request/response types "
00070 "from different .srv files. (%s vs. %s)", impl_->name_.c_str(), st::md5sum(req), st::md5sum(res));
00071 return false;
00072 }
00073
00074 return call(req, res, st::md5sum(req));
00075 }
00076
00080 template<class Service>
00081 bool call(Service& service)
00082 {
00083 namespace st = service_traits;
00084
00085 if (!isValid())
00086 {
00087 return false;
00088 }
00089
00090 return call(service.request, service.response, st::md5sum(service));
00091 }
00092
00096 template<typename MReq, typename MRes>
00097 bool call(const MReq& req, MRes& resp, const std::string& service_md5sum)
00098 {
00099 namespace ser = serialization;
00100 SerializedMessage ser_req = ser::serializeMessage(req);
00101 SerializedMessage ser_resp;
00102 bool ok = call(ser_req, ser_resp, service_md5sum);
00103 if (!ok)
00104 {
00105 return false;
00106 }
00107
00108 try
00109 {
00110 ser::deserializeMessage(ser_resp, resp);
00111 }
00112 catch (std::exception& e)
00113 {
00114 deserializeFailed(e);
00115 return false;
00116 }
00117
00118 return true;
00119 }
00120
00121 bool call(const SerializedMessage& req, SerializedMessage& resp, const std::string& service_md5sum);
00122
00127 bool isValid() const;
00128
00137 void shutdown();
00138
00145 bool waitForExistence(ros::Duration timeout = ros::Duration(-1));
00146
00151 bool exists();
00152
00156 std::string getService();
00157
00158 operator void*() const { return isValid() ? (void*)1 : (void*)0; }
00159 bool operator<(const ServiceClient& rhs) const
00160 {
00161 return impl_ < rhs.impl_;
00162 }
00163
00164 bool operator==(const ServiceClient& rhs) const
00165 {
00166 return impl_ == rhs.impl_;
00167 }
00168
00169 bool operator!=(const ServiceClient& rhs) const
00170 {
00171 return impl_ != rhs.impl_;
00172 }
00173
00174 private:
00175
00176
00177
00178 void deserializeFailed(const std::exception& e)
00179 {
00180 ROS_ERROR("Exception thrown while while deserializing service call: %s", e.what());
00181 }
00182
00183 struct Impl
00184 {
00185 Impl();
00186 ~Impl();
00187
00188 void shutdown();
00189 bool isValid() const;
00190
00191 ServiceServerLinkPtr server_link_;
00192 std::string name_;
00193 bool persistent_;
00194 M_string header_values_;
00195 std::string service_md5sum_;
00196 bool is_shutdown_;
00197 double constructed_;
00198 };
00199 typedef boost::shared_ptr<Impl> ImplPtr;
00200 typedef boost::weak_ptr<Impl> ImplWPtr;
00201
00202 ImplPtr impl_;
00203
00204 friend class NodeHandle;
00205 friend class NodeHandleBackingCollection;
00206 };
00207 typedef boost::shared_ptr<ServiceClient> ServiceClientPtr;
00208
00209 }
00210
00211 #endif