Reference article:
Dell’Anna, D., Jamshidnejad, A. SONAR: An Adaptive Control Architecture for Social Norm Aware Robots. Int J of Soc Robotics (2024). https://doi.org/10.1007/s12369-024-01172-8
MQTT-Nao-Interface is a Python 2.7 resource that can be used to control a Nao robot via Python and that can receive commands (e.g., from SONAR) and publish data (e.g., captured via Nao's sensors) via MQTT.
Below the structure of this repository and the steps required to install and run MQTT-Nao-Interface.
MQTT-Nao-Interface
└───actuators # The actuator services that receive directives for the robot's actuators via MQTT
│ actuator.py # An abstract class implemented by all the actuators
│
└───lib # Folder containing libraries used in the HRI experiments
│ # including library for PyQT,
│ # the Nao additional behaviors for emotions expression
│ # the vision recognition database
└───sensors # The sensor services that publish to MQTT topics data collected from robot's sensors
│ sensor.py # An abstract class implemented by all the sensors
│
└───utils # Utilities for MQTT-Nao-Interface
│
│ README.md # This file
│ main.py # Main file to run the MQTT-Nao-Interface.
│ # It defines the services to be run and starts them
│ # It can be used both with the virtual robot and with the real robot
│ requirements.txt # The list of libraries required to setup and run the MQTT-Nao-Interface
Software download page: https://www.aldebaran.com/fr/support/nao-6/downloads-softwares
-
Robot Settings. Useful for checking and changing settings of Nao (e.g., wifi connection, or updates)
Verify installation by inserting Nao's IP address (press chest button on Nao to get it) and pressing Enter
-
Chorégraphe Suite. Useful for creating and controlling behaviors for Nao; for installing behaviors on the robot; and for running the virtual robot.
-
Verify installation as follows:
- Go to Connection -> Connect to...
- Insert Nao's IP address (as per Robot Settings) in the field "Use fixed IP/hostname"
- Nao should appear in the robot view
- Try to execute a behavior: drag and drop from the Box libraries to the root field one animation (e.g.,the Animation->Moods->Positive->NAO->Happy animation), connect it to the onStart event, and press the green play button. Nao should execute the animation.
-
Setup the virtual robot as follows:
- Go to Edit -> Preferences -> Virtual Robot
- Select Robot model NAO H25 (V6)
- Note on the bottom of the panel the port on which NAOqi is running (important for interfacing with Python)
- Press OK, then press Connection -> Connect to virtual robot
- Press OK, then try to execute a behavior: drag and drop from the Box libraries to the root field one animation (e.g.,the Animation->Moods->Positive->NAO->Happy animation), connect it to the onStart event, and press the green play button. The virtual robot should execute the animation.
-
-
Python 2.7 NAOqi SDK. Required to control Nao via Python.
- Follow the installation instructions from Aldebaran here.
Communication between the (Python 2.7) MQTT-Nao-Interface and other external services (e.g., SONAR) happens via MQTT (a lightweight method of carrying out messaging using a publish/subscribe model, and the standard messaging protocol for the Internet of Things).
Below, it is reported a very quick tutorial on how to install Eclipse Mosquitto, an open source message broker that implements the MQTT protocol, on an Ubuntu distro installed on Windows WSL.
2.1.1. Install Linux on Windows with WSL (see Microsoft guidelines)
- Open Windows PowerShell with admin rights
- Run
wsl --install
- Reboot the system
- Open Microsoft Store and type and get Ubuntu
- Follow the instruction in the Ubuntu terminal to create a new UNIX user account.
- Run
sudo apt update && sudo apt upgrade
to update packages.
- In the Ubuntu terminal, as per step 6 of Sec 2.1.1., add the mosquitto-dev PPA by running first
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
and thensudo apt-get update
.- To install Mosquitto, run
sudo apt install mosquitto
and typeY
when requested.- To start Mosquitto, run
sudo service mosquitto start
MQTT-Nao-Interface is a python resource that runs on Python 2.7. Therefore the basic requirement is Python 2.7.
Secondly, the MQTT-Nao-Interface needs the Python 2.7 NAOqi SDK. See section 1 for details on installation.
The MQTT-Nao-Interface also requires a number of Python packages to be installed.
The list of requirements can be found in the requirements.txt
file.
A standard way to install all required libraries is to run command pip install -r /path/to/requirements.txt
.
Based on your environment you may adopt the most handy procedure.
MQTT-Nao-Interface relies on an MQTT broker. Follow steps in Section 2 to install it.
Finally, please download in folder MQTT-Nao-Interface/sensors/video/data
the following files (they are not provided to avoid overloading the repository):
- The pre-trained YOLO3 weight file
yolov3.weights
(used for object recognition with the COCO dataset). You can find the file here (237 MB), or follow the instructions from the YOLO webpage to download it in other ways. - The pre-trained YOLO3 weight file
yolov3-hat_2400.weights
(used for recognition of an helmet/hat). You can find the file here (240 MB) in the link called "model". Note that in the linked repository the file that will be downloaded is namedyolov3-obj_2400.weights
, so please rename it as indicated above. - The pre-trained shape predictor model
shape_predictor_68_face_landmarks.dat
(used for face detection and tracking). You can find a compressed archive version of the file here (100 MB). You need to decompress the file and place the.dat
file in the folder mentioned above. - The pre-trained model
emotion-ferplus-8.onnx
for emotion recognition from faces. You can find it here (34 MB).
SONAR can instruct the MQTT-Nao-Interface to execute a number of non-default behaviors on Nao (e.g., some particular movements).
These behaviors can be found in folder MQTT-Nao-Interface/lib/Nao_Additional_Behaviors
, which contains a Choreographe project.
In order to upload them on Nao and/or on a virtual robot follow the next steps.
- Open Choreographe
- Open the project (File -> Open project) contained in the
Nao_Additional_Behaviors
folder.- In the
Robot applications
panel in Choreographe press the buttonPackage and install current project to the robot
. An entry namedNao_Additional_Behaviors
should appear in the list of applications of the robot.- Run, on Choreographe, one of the behaviors (e.g., open
behaviors/anger/behavior.xar
and press play after connecting to the (virtual) robot). By doing so all behaviors in the project will be also automatically loaded in the.lastUploadedChoreographeBehavior
application, which is the only application available to the virtual robot.
- Start Mosquitto as per section 2.2.1
- Turn on Nao, or connect to a virtual robot.
- Determine the IP and port of the robot. For Nao, press the chest to obtain its IP address (the default port is
9559
). For the virtual robot in Choreographe, the IP islocalhost
if Choreographe is running on the same machine as the MQTT-Nao-Interface, and the port can be found in the preferences as per Section 1.- Assign the correct IP and port to variables
ip
andport
in moduleMQTT-Nao-Interface/main.py
.- Run MQTT-Nao-Interface via
python MQTT-Nao-Interface/main.py
.
4. Mini-Tutorial: Create a new MQTT-Nao-Interface sensor (Object Recognition using Nao buil-in functionality)
In this section we will see how to create a new sensor class which interfaces with NaoQi to collect data from the robot and publishes the collected data to the MQTT broker.
We will use, as an example, a sensor that meant to deal with objects recognition. Nao has built in functionality, which can be accessed via Choreographe, that allows it to quickly learn new objects. Follow this tutorial to know how.
In the following, it is assumed that Nao has learned at least one object.
In order to create a new MQTT-Nao-Interface sensor
follow the next steps (note that analogous procedure holds for actuators
).
For our example, we create a module detectobject.py
in folder MQTT-Nao-Interface/sensors/video/
.
4.2. In the newly created module, define a new class, representing the sensor, and extending the superclass Sensor
.
For our example, we define and initialize a class VisionRecognition
as follows.
class VisionRecognition(Sensor):
""" A simple class to react to object detection events. """
def __init__(self, nao_interface, id, mqtt_topic, freq, qi_app=None):
super(BuiltInObjectDetector, self).__init__(nao_interface, id, mqtt_topic, [Constants.NAO_SERVICE_MEMORY,
Constants.NAO_SERVICE_VISION_RECOGNITION], freq, qi_app)
self.subscribeToServices()
self.last_detected_object = ""
def subscribeToServices(self):
self.subscriber = self.services[Constants.NAO_SERVICE_MEMORY].subscriber(Constants.NAO_EVENT_PICTURE_DETECTED)
self.subscriber.signal.connect(self.on_picture_detected)
self.subscribe(Constants.NAO_SERVICE_VISION_RECOGNITION, self.id)
In the initialization, we call the constructor of the super class by indicating the reference to the NaoInterface
class (nao_interface
), an id for the sensor class (id
), the MQTT topic on which the sensor will publish data (mqtt_topic
), a list of NAOqi service to which we intend to subscribe ([...]
, note that this list is sensor-specific), the frequency at which we desire the sensor to publish new data (if any) to the MQTT broker (freq
), and finally a reference to the NAOqi Application (qi_app
) instantiated in the NaoInterface
.
For our example, the list of services that we are interested into includes NAO_SERVICE_MEMORY
and NAO_SERVICE_VISION_RECOGNITION
(i.e., "ALMemory"
and "ALVisionRecognition"
, respectively).
Furthermore, in the initialization, we invoke function subscribeToServices()
, which is also sensor-specific (i.e., it needs to be defined for the particular sensor class), and subscribes the class to events generated by relevant services.
In the case of the ALVisionRecognition
, the name of the event generated by the service is PictureDetected
(referred below as NAO_EVENT_PICTURE_DETECTED
).
Note that the signal from the event is connected to a callback class function on_picture_detected
to be defined.
Finally, note that during initialization we are creating a variable last_detected_object
, which will be used to store the detected objects (we keep the example for this tutorial simple, but more complex management of sensor data can be introduced)
This function will be invoked every time an object is detected. The function takes one parameter in input, i.e., the value contained in the event.
def on_picture_detected(self, value):
"""
Callback for event PictureDetected.
"""
# Here place your code.
# Simple example:
print(value)
self.last_detected_object = value
Note that in the example above, we are directly assigning the value returned by the event to the variable last_detected_object
.
However such a value does not only contain the name of the object detected but also several other information.
Please refer to ALVisionRecognition for details on the content of the variable.
Note also that event PictureDetected
is raised also when an object that is currently being detected disappears. In this case the content of value will be an empty list (if no object is visible).
This function will be regularly (at a frequency given by the class instance attribute freq
) invoked. See the run
function of the superclass Sensor
for more details.
The function should return a string to be published to the MQTT broker on topic mqtt_topic
.
If no message should be published, the function should return value None
.
def sense(self):
if self.last_detected_object=="":
return None
return self.last_detected_object
In the run
function of the NaoInterface
class in module MQTT-Nao-Interface/main.py
,
add a new instance of the new VisionRecognition
in the dictionary containing the services of the nao interface (i.e., to the dictionary self.services
) for the case of real robot (i.e., if not self.virtual
is true).
Since we are using built-in features of Nao, this service can only work with the real robot and not with the virtual one.
It is also possible to create other services that do not rely on the built-in features of Nao in an analogous way (see the already implemented set of services for examples).
self.services = {
# SENSORS
# ... other sensors ...
"VisionRecognition": VisionRecognition(self, "VisionRecognition", Constants.TOPIC_OBJECT_DETECTION, 1, self.app),
# ... other sensors ...
# ACTUATORS
# ... actuators
}
Test the sensor by executing steps from section 3.2.1. For this example you need to connect to the real robot.
Technische Universiteit Delft hereby disclaims all copyright interest in the program “MQTT-Nao-Interface”. MQTT-Nao-Interface is a python program to interface a Nao robot via MQTT written by D. Dell'Anna. Henri Werij, Dean of Faculty of Aerospace Engineering, Technische Universiteit Delft.
MIT License
Copyright (c) 2024, D. Dell'Anna
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.