(Work In Progress)
Telemetry app for the web, using React and Typescript, roslibjs.
During the winter of semester of 2020, three software engineering students (Anthony Frezzato, Hervé Carol Marorerwa, Laurent Boisvert) have accepted the mandate to remake the telemetry. The club have already a telemetry based on RQT under python but the encounter several problem because they are really dependent of packages. They would like to create a web telemetry which is independent of the module architecture using ROSLIB.
The current telemetry is based on RQT and directly ROS packages made by the club. This create a strong coupling between the telemetry and the ROS packages. RQT is a software framework of ROS that implements the various GUI tools in the form of plugins, but they have some problem of portability. Currently the club is using mostly the telemetry on Ubuntu that is a GNU / Linux operating system based on the Debian Linux distribution.
The club provided some requirement to the developpement teams:
Here a list of features requested by the club by priority order:
With all this in mind, the solution adopted is:
The telemetry can be runned locally but every module need to receive data from ROS.
In order to simulate data you can use a BAG. A bag is a file format in ROS for storing ROS message data.
The club provided bags to the team and have team to replay live situation.
In order to run a bag you need to install the following component from ROS:
In order to run a bag, you need three terminal:
The result should be something like:
The result should be something like:
The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications.
The telemetry have to communicate with the ROS bridge in order to display or send informations. ROS provide a library called ROSLIB javascript (s) and this is the core JavaScript library for interacting with ROS from the browser. It uses WebSockets to connect with rosbridge and provides publishing, subscribing, service calls.
On our end we implemented three function:
Here a sample of code how to suscribe to a ros topic:
useROSTopicSubscriber<any>(thrusterEffortCallback, "/provider_thruster/effort", "sonia_common/ThrusterEffort")
In this example we provide a callback function. This function will be called at every update of the data topic subscribe.
The second parameter is the name of the topic and the third parameter is the type of the message (here sonia_common/ThrusterEffort is a custom message type by SONIA).
The callback function receive the data inside the variable x, aftermath the UI is updating components depending the new value:
const thrusterEffortCallback = useCallback( (x: any) => { ...do something here... }, [] )
Here a sample of code how to publish to a ros topic
Declaration (once):
const testBoardPublisher = useROSTopicPublisher<any>("/interface_rs485/dataRx", "sonia_common/SendRS485Msg")
Usage (can be called on demand with different parameters):
testBoardPublisher({slave: slave, cmd: cmd, data: data})
In this example we provide again the name of the topic and the type of the message (here sonia_common/SendRS485Msg is a custom message type by SONIA). testBoardPublisher has to be declared once and it can be used multiple of times with different values. The field (slave, cmd and data) depends of the service definition refers to "sonia_common\msg" to see the definition of a specific message.
Here a sample of code how to request a ros service
Declaration (once):
const getFilterChainFromExecutionServiceCall = useROSService<any>(getFilterChainFromExecutionCallback, "/proc_image_processing/get_media_from_execution", "sonia_common/GetMediaFromExecution");
In this example we provide a callback function. This function will be called on response of the service call. The second parameters is the name of the service, the third parameter is the type of the service.
The callback function receive the data inside the variable x, aftermath the UI is updating components depending the new value:
const getFilterChainFromExecutionCallback = useCallback( (x: any) => { ...do something here... }, [] )
Usage (can be called on demand with different parameters):
var request = ServiceRequestFactory({ exec_name: x.target.value });
getFilterChainFromExecutionServiceCall(request)
In this usage example we create a request and the fields (exec_name) depends of the service definition, refer to "sonia_common\srv" to see the definition of a specific message.
Material-UI is an open-source project that features React components that implement Google's Material Design.
In the telemetry we used mostly this library to design the UI components.
Here the list of major components used from Material UI and the corresponding documentation:
In this section the module we describe the modules implemented during the PFE
The truster module allow to control the motors of the submarine during a dry test.
Characteristics:
/provider_thruster/effort
, Message type: sonia_common/ThrusterEffort
/provider_thruster/thruster_effort
, Message type: std_msgs/String
The actuator module allow to activate actuators on the submarine.
Characteristics:
/provider_actuators/do_action_srv
, Service type: sonia_common/ActuatorDoActionSrv
The camera viewer allow to see camera video stream. Uncompressed and compressed format are supported.
Characteristics:
/rosapi/topics/
, Service type: /rosapi/topics/
/provider_vision/Front_GigE/compressed
or /provider_vision/Bottom_GigE/compressed
, Message type: sensor_msgs/CompressedImage
/provider_vision/Front_GigE
or /provider_vision/Bottom_GigE
, Message type: sensor_msgs/Image
The toolbar is made up of buttons that allow the user to send ROS commands
characteristics:
proc_control/EnableControl
, Service type: sonia_common/EnableControl
/provider_vision/StarStopCamera
, Service type: sonia_common/StartStopMedia
/provider_power/power
, message type: sonia_common/PowerMsg
/provider_kill_mission/mission_switch_msg
, message type: sonia_common/MissionSwitchMsg
/provider_kill_mission/kill_switch_msg
, message type: sonia_common/KillSwitchMsg
/provider_jetson/system_temperature
, message type: std_msgs/Float32
The vision UI allow to apply image filter on the submarine camera. The vision UI is able to create and edit a chain of filters.
In order to see result, the image viewer can be used.
Characteristics:
/provider_vision/start_stop_camera
, Service type: sonia_common/StartStopMedia
/proc_image_processing/execute_cmd
, Service type: sonia_common/ExecuteCmd
/proc_image_processing/get_information_list
, Service type: sonia_common/GetInformationList
/proc_image_processing/get_information_list
, Service type: sonia_common/GetInformationList
/proc_image_processing/manage_filterchain
, Service type: sonia_common/ManageFilterchain
/proc_image_processing/get_information_list
, Service type: sonia_common/GetInformationList
/proc_image_processing/copy_filterchain
, Service type: sonia_common/CopyFilterchain
/proc_image_processing/manage_filterchain
, Service type: sonia_common/ManageFilterchain
/proc_image_processing/get_filterchain_filter
, Service type: sonia_common/GetFilterchainFilter
/proc_image_processing/get_media_from_execution
, Service type: sonia_common/GetMediaFromExecution
/proc_image_processing/get_information_list
, Service type: sonia_common/GetInformationList
/proc_image_processing/execute_cmd
, Service type: sonia_common/ExecuteCmd
/proc_image_processing/get_information_list
, Service type: sonia_common/GetInformationList
/proc_image_processing/manage_filterchain_filter
, Service type: sonia_common/ManageFilterchain
/proc_image_processing/save_filterchain
, Service type: sonia_common/SaveFilterchain
/proc_image_processing/set_filterchain_filter_order
, Service type: sonia_common/SetFilterchainFilterOrder
/proc_image_processing/set_filterchain_filter_observer
, Service type: sonia_common/SetFilterchainFilterObserver
/proc_image_processing/get_filterchain_filter_all_param
, Service type: sonia_common/GetFilterchainFilterAllParam
/proc_image_processing/set_filterchain_filter_param
, Service type: sonia_common/SetFilterchainFilterParam
The waypoint module allow to control the position and the speed of the submarine
Characteristics:
/proc_control/set_control_mode
, Service type: sonia_common/SetControlMode
/proc_control/clear_waypoint
, Service type: sonia_common/ClearWaypoint
/proc_navigation/set_world_x_y_offset
, Service type: sonia_common/SetWorldXYOffset
/proc_navigation/set_depth_offset
, Service type: sonia_common/SetDepthOffset
/proc_control/set_global_target
, Service type: sonia_common/SetPositionTarget
/proc_control/control_mode
, Message type: std_msgs/UInt8
/proc_control/control_mode
, Message type: geometry_msgs/Pose
/proc_control/current_target_velocity
, Message type: geometry_msgs/Twist
The testboard modules contains a form of with 4 inputs: CMD, Slave, Data and rate. On the submit of the form, the data that is sent is formed of the 3 inputs CMD, Slave and Data. The rate input in used when the user wants to send the data continuously. If the single send checkbox is checked, the data will be sent only once to ROS. If the single send checkbox is not checked, the data will be sent continuously at the rate defined in the rate input.
/interface_rs485/dataRx
, message type: sonia_common/SendRS485Msg
The misssion manager is used to select a mission and load it on the submarine. This module is necessary for the competition because it allows us to select a mission before disconnecting the cable between the dockbox and the AUV. To refresh the missions list, you simply have to press the "Update" button. Select the mission and press "Send" to load the mission on the submarine. Here's what the module looks like.
/mission_manager/mission_name_msg
, message type: /mission_manager/MissionNameMsg
(Will be updated soon)/mission_executor/list_missions
, Service type: ListMissions
(Will be updated soon)The PFD allow to see the different position/angles of the submarine.
Characteristics:
/proc_navigation/odom
, Service type: nav_msgs/Odometry
/proc_control/current_target
, Service type: geometry_msgs/Pose
/proc_control/current_target_velocity
, Service type: geometry_msgs/Twist
The side bar contains the ModulePicker
component, which allows the user to pick which modules are to be displayed - or active - in the application.
These settings are remembered across sessions through
LocalStorage
.
The current layout just save the position of all modules. If the telemetry is close and re-open all modules remains at the same place.
In order to reset the layout and return to an initial setup, please go to "Menu" on top left and click on "Clear Layout"
This module allows the users to have visual returns on the different components of the AUV (sensors, DVL, MPC, etc.). It is also possible to create a trajectory for the submarine based on the selected mode.
*These are clickable buttons.
This section explain how to add a new module to and continue to follow the current project architecture.
Please refer to the template created: octopus-telemetry/src/components/TemplateModule.tsx
Steps:
1- Create a new module .tsx file in the components folder: octopus-telemetry/src/components/.
In this example, it is TemplateModule.tsx
2- Add the new component in ModulesMetadata.tsx: octopus-telemetry/src/components/modulepicker/ModulesMetadata.tsx
3- Add the new component in generalContext.tsx: octopus-telemetry/src/context/generalContext.tsx
4- Add the new component in App.tsx: octopus-telemetry/src/App.tsx
The team used the github board tools to track issues and follow the progress of the projects.
https://github.com/sonia-auv/octopus-telemetry/projects/1
A possibility to create different layouts to place module and be able to save/restore has been discussed but remains to be done.
On the previous telemetry the path taken by the submarine was displayed on a map and a position command was available on the map. We are able to clear the waypoints but we cannot see them. This is remain to do.
The technology choices in our application were chosen rather quickly - we opted for a React application, using Typescript to have the benefit of fast development with React's API and the relative safety of Typescript.
We could have implemented an application in Dash, knowing that most of the Sonia codebase was already implemented in Python (TODO laurent: link repo here). Dash applications allow to serve a presentation layer in HTML, and uses callbacks to chain events together. Dash effectively allows the development of a full blown we application, without using an API. It blurs the line between the frontend and the backend.
However, due to the nature of the application to be developed, we decided that using a more traditional approach (an API, consumed by a React application served to the client) would be a more robust and scalable approach.
We thought about using Material UI and Vue.js as the frontend framework (instead of React), but decided against it, as the SONIA team seemed more interested in React, which has an large community, very good support and features, and is production-ready.
https://www.youtube.com/watch?v=_10IUdKBPy4