service_client.h
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2013, Johannes Meyer, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Flight Systems and Automatic Control group,
00013 //       TU Darmstadt, nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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   // This works around a problem with the OSX linker that causes the static variable declared by
00156   // ROS_ERROR to error with missing symbols when it's used directly in the templated call() method above
00157   // This for some reason only showed up in the rxtools package
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 } // namespace topic_proxy
00183 
00184 #endif // TOPIC_PROXY_SERVICE_CLIENT_H


topic_proxy
Author(s): Johannes Meyer
autogenerated on Mon Oct 6 2014 07:55:47