Calling ROS Services & Actions
The Bridge Client node autodetects all available ROS Services and Actions on all discovered nodes, and the Web UI then provides various tools to call them with custom data payloads and receive replies. Service and action calls can be even mapped to keyboard keys, gamepad and touch UI buttons.
ROS action calls use the same UI and API as ROS services, both are internally implemented as service calls. The main difference between a service and an action is that action receives two replies: one when the goal is set (or refused), another one when the goal is reached or cancelled. Multiplle calls of a particular service are queued and executed sequentially, while a repeated invocation of an action in the UI cancels its previously set goal.
Note
The services API provides a reliable way of calling ROS services and actions, however, it is not designed with speed nor low latency in mind. All service requests are queued and processed in sequential order by the Bridge Client node which also waits for every service reply. If no reply arrives withing 20s (default), you will receive a timeout error. If you need to call a service several times per second, you should probably use topic messages instead.
Services and actions can be blacklisted or collapsed in the menu, the default timeout can be adjusted in the phntm_bridge.yaml config file:
/**:
ros__parameters:
blacklist_services: [] # blacklist services and actions from discovery (msg types or full service ids)
collapse_unhandled_services: True # the UI will collapse services with unsupported message types
collapse_services: # list of service IDs and/or types to be collapsed in the UI
- rcl_interfaces/srv/DescribeParameters
- rcl_interfaces/srv/GetParameterTypes
- type_description_interfaces/srv/GetTypeDescription
default_service_timeout_sec: 20.0 # default timeout for service replies
In order to be able to call any ROS service or action, the Bridge Client node needs to have access to its type definitions. See Custom message & Service types for more info.
The most basic service types (e.g. std_srvs/srv/Empty, std_srvs/srv/Trigger or std_srvs/srv/SetBool) come with pre-defined user interface out of the box to make calling them as simple as clicking a button. For services or actions that take more complex input data, we first need to define the payload.
Implementing Custom Widgets
In addition to calling services with pre-configured payloads as described above, you can also create a completely unique controls for any ROS service.
To do that, you need to extend the ServiceInputBase class and create a custom service widget that will be displayed in the service dropdown menu in a similar fashion to the standard buttons. A custom widget is responsible for rendering of its own DOM elements, and can be initialized by a value provided by a getter ROS service.
An example of such a widget - a slider menu element - can be found in the Bridge UI Extras repo and also in the live demos.
To register your custom service widget, include it in the UI using the ui_custom_includes_js parameter.
You can then map it to a service as shown below, plus any custom parameters to be passed to the widget.
The extra params defined for the service can be read using this.client.getServiceConfig(id_service) in your extended class.
Timeouts for each service call can be customized in this.client.serviceCall().
/**:
ros__parameters:
ui_custom_includes_js:
- https://www.some-server.com/custom-service-widget.js
# custom service menu widget mapping
/some_node/some_service:
menu_widget: CustomServiceWidget # widget class to use, must be included via ui_custom_includes_js
custom_widget_param_1: 0.5 # custom attributes for the widget class follow
custom_widget_param_2: 'This is a string param'
custom_widget_param_3: False
custom_widget_getter_service: /some_node/some_other_service
See Customizing the User Interface for more details on how to host the extension files and ServiceInputBase for API reference.