[Documentation] [TitleIndex] [WordIndex

Only released in EOL distros:  

visualization_engine: rve_common | rve_common_transformers | rve_dynlib | rve_geometry | rve_interface_gen | rve_interfaces | rve_mesh_loader | rve_msgs | rve_pluginloader | rve_properties | rve_qt | rve_render_client | rve_render_server | rve_rpc | rve_transformer

Package Summary

rve_rpc provides a rpc (remote procedure call) mechanism similar to services, but using topics for communication.

Why?

rve_rpc is essentially a service replacement. You may ask, then, what the advantages of rve_rpc are vs. services.

Examples

rve_rpc was mainly designed for use by rve_interface_gen, so its API could probably use some work. Using it standalone is still fairly easy though.

Server

A server callback looks something like this:

   1 void callback(rve_rpc::CallHandle<RequestMessage, ResponseMessage>& handle)
   2 {
   3   const RequestMessageConstPtr& req = handle.getRequest();
   4   // do stuff with req
   5   // ...
   6   TestResponsePtr res(new TestResponse);
   7   handle.respond(res);
   8 }

handle here allows you to either respond immediately (like in the example), or store it off and respond later. If an rve_rpc::CallHandle is destroyed without ever responding, it responds with an exception.

To indicate an error, you can either call handle.except("my error message goes here"), or you can throw an exception derived from std::exception from within your callback.

Setting up the server is done using the rve_rpc::Server class, like so:

   1 Server s("server_name", nh);
   2 s.addMethod<RequestMessage, ResponseMessage>("callMe", callback);
   3 s.ready();

Client

Use of a client looks something like this:

   1 Client c("server_name", nh);
   2 Method<RequestMessage, ResponseMessage> m = c.addMethod<RequestMessage, ResponseMessage>("callMe");
   3 c.connect();
   4 
   5 ReqeustMessagePtr req(new RequestMessagePtr);
   6 // fill out req...
   7 ResponseMessageConstPtr res = m.call(req);

Alternatively, you can use it asynchronously like so:

   1 m.callAsync(req, callback);

where callback is of the form:

   1 void callback(const MethodResponse<ResponseMessage>& res)
   2 {
   3   if (res.error_code == rve_rpc::Response::SUCCESS)
   4   {
   5     const ResponseMessageConstPtr& msg = res.response;
   6     //...
   7   }
   8 }

Internals

An rve_rpc client/server pair operate on a "request/response" topic. For example:

/server_name/request
/server_name/response

These topics are always of the type rve_rpc::Request and rve_rpc::Response. The request/response messages are serialized into a uint8 array inside the container message. This is why "rostopic echo" won't give you what you might expect with these topics.

rve_rpc uses RequestWrapper and ResponseWrapper classes that serialize to the same wire format as the messages to support no-copy "serialization" when running intraprocess.


2024-03-16 13:00