gz-transport icon indicating copy to clipboard operation
gz-transport copied to clipboard

Add overloaded Request for non-blocking calls using abstract types

Open srmainwaring opened this issue 1 year ago • 4 comments

🎉 New feature

Summary

Add an overloaded Request method to the class Node that accepts references to abstract request and response types, specifically the type google::protobuf::Message.

The addition is to support a non-blocking version of the service call used in cmdServiceReq (gz-transport/src/cmd/gz.hh). The existing Request methods accepting a callback function all require a concrete type as they call Request().GetTypeName() and Response().GetTypeName(). This does not work when the request or response types are the abstract base class google::protobuf::Message. The instance calls _request->GetTypeName() and _response->GetTypeName() on the other hand are valid, and this is what the new overload function uses.

There is also a change to the template specialisation of ReqHandler to support callbacks.

Test it

Tasks

  • [ ] Change target to main because of ABI changes.
  • [ ] Add a test to gz-transport

The current use case is in a downstream project providing python bindings for gz-msgs and gz-transport: https://github.com/srmainwaring/gz-python/tree/srmainwaring/service-request

At present only blocking service requests are supported. The Python bindings use the same approach as the gz service command line tools. This PR allows asynchronous callbacks as well. The example below is for a service that allows the PID settings of a joint controller to be updated in Python at runtime. Both blocking and non-blocking versions of the call are demonstrated.

import time

from gz.msgs.pid_pb2 import PID

from gz.transport import Node

# service response callback 
def rep_cb(msg, result):
    print("Result: {}".format(result))
    print("Response: {}".format(msg))

def main():
    # create a transport node
    node = Node()
    service = "/model/iris_with_ardupilot/"\
              "joint/iris_with_standoffs::rotor_0_joint/pid"
    req_type_name = PID.DESCRIPTOR.full_name
    rep_type_name = PID.DESCRIPTOR.full_name

    # populate PID message
    req = PID()
    req.p_gain_optional.data = 0.2
    req.i_gain_optional.data = 0.0
    req.d_gain_optional.data = 0.0
    req.i_max_optional.data = 1.0
    req.i_min_optional.data = -1.0
    req.limit_optional.data = 10.0

    # timeout in ms
    timeout = 1000

    # call service (blocking)
    print("Blocking service call")
    executed = node.request(service, req, timeout, rep_type_name)

    # update PID so we can verify second call
    req.p_gain_optional.data = 0.3

    # call service (non-blocking)
    print("Non-blocking service call")
    executed = node.request(service, req, rep_cb, rep_type_name)

    # wait for response before exiting
    time.sleep(timeout/1000)
    print("Done")

if __name__ == "__main__":
    main()

Expected console output:

% ~/Code/osrf/gz_garden_ws/src/gz-python/python/pid_service.py
Blocking service call
Non-blocking service call
Result: True
Response: p_gain_optional {
  data: 0.3
}
i_gain_optional {
}
d_gain_optional {
}
i_max_optional {
  data: 1.0
}
i_min_optional {
  data: -1.0
}
limit_optional {
  data: 10.0
}

Done

Expected gz sim output (using a modified version of the ArduPilot plugin: https://github.com/srmainwaring/ardupilot_gazebo-1/commit/c938fd5922699b961ab2aa7fbb8f93743c670c15):

[Msg] Updated PIDs for [iris_with_standoffs::rotor_0_joint]
p_gain: 0.2
i_gain: 0
d_gain: 0
i_max: 1
i_min: -1
cmd_max: 10
cmd_min: -10
[Msg] Updated PIDs for [iris_with_standoffs::rotor_0_joint]
p_gain: 0.3
i_gain: 0
d_gain: 0
i_max: 1
i_min: -1
cmd_max: 10
cmd_min: -10

Checklist

  • [x] Signed all commits for DCO
  • [ ] Added tests
  • [ ] Added example and/or tutorial
  • [ ] Updated documentation (as needed)
  • [ ] Updated migration guide (as needed)
  • [ ] Consider updating Python bindings (if the library has them)
  • [ ] codecheck passed (See contributing)
  • [ ] All tests passed (See test coverage)
  • [ ] While waiting for a review on your PR, please help review another open pull request to support the maintainers

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by messages.

srmainwaring avatar Feb 24 '23 15:02 srmainwaring