Greetings fellow robotics enthusiasts,
I am back and brought a new public repo with me:
This is a plugin for QML which allows communicating with ROS2 nodes directly from QML.
No compilation or modification necessary!
If you don’t know it, QML is a markup language by the Qt people which is a lot nicer than the QWidget stuff (both in terms of looks and writing code) and comes with hardware acceleration already integrated.
Since pictures speak more than words, here’s a bunch of those put in sequence:
This shows a short snippet of the start of Team Hector’s finals run in the DRZ challenge at the RoboCup German Open 2022 hosted at the German Rescue Robotics Center (DRZ).
The user interface you see here is built using QML and the QML ROS Plugin which is the ROS 1 version of this plugin since our robots are still running on ROS 1.
However, you could build the same interface for ROS 2 (if you port the hector_rviz_overlay for rviz2 that is ).
Of course, the package also comes with some small examples and documentation to help you get started.
Please note that as described in the topic for the release of ROS2 BabelFish which is used for the communication under the hood, the examples for service and action clients currently do not work and will print a helpful error message on the console with a link to the PR that needs to be merged for the implementation to work.
Also, it should work with any middleware but I’ve only tested it with the default RMW of foxy and galactic.
Here’s also a small code example:
import QtQuick 2.2
import QtQuick.Controls 2.5
import QtMultimedia 5.10
import Ros2 1.0
Item {
Component.onCompleted: Ros2.init('qml_example_node')
ImageTransportSubscription {
id: imageSubscription
topic: "/image_raw"
}
VideoOutput { anchors.fill: parent; source: imageSubscription }
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
width: 120; height: 120
radius: 60
color: '#aaaaaa' // a ghost! :O
MouseArea {
anchors.fill: parent
property var pub: Ros2.createPublisher("/cmd_vel",
"geometry_msgs/Twist", 1)
onPositionChanged: {
var x = -mouse.x / (width / 2) + 1
var y = -mouse.y / (height / 2) + 1
pub.publish({linear: {x: y}, angular: {z: x}})
}
}
}
Button {
anchors.bottom: parent.bottom
property bool isOn: true
property var flashlightClient: Ros2.createServiceClient('/flashlight', 'std_srvs/srv/SetBool')
text: 'Flashlight: ' + (isOn ? 'On' : 'Off')
onClicked: {
flashlightClient.sendRequestAsync(
{data: !isOn},
function (result) {
if (result === false) {
Ros2.error("Failed to toggle flashlight!")
return
}
isOn = !isOn
})
}
}
}
These roughly 50 lines of code are all it takes to create a minimal interface with a camera stream, a steering joypad area and a button to toggle a flashlight using a service call.
That’s all, I hope it may be of use to some of you.
If you’ve built something cool with it, feel free to shoot me a message or email