Calling ROS Services
The Bridge Client node autodetects all available ROS services of all discovered nodes, and the Web UI then provides various tools to call them with custom data payloads and receive replies. Service calls can be even mapped to keyboard keys, gamepad and touch UI buttons.
Note
The services API provides a reliable way of calling ROS services, 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 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 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, the Bridge 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 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.