How-to: Log and retrieve data from the robot#

ARI already has a ROS package that enables publishing log data that is then written to an internal CSV file, named node_pal_interaction_logger. pal_interaction_logger logs the interactions between the robot and the user. For example, the package can log the interactions with the touchscreen or the results of speech recognition.

The logger subscribes to a generic std_msgs/String message that contains information about the interaction. The saved log consists of the description of the interaction and the corresponding timestamp.

Note

Another popular option to log data is to use the ROS bag tool to record (and later, replay) arbitrary ROS topic. This is fully supported on the ARI platform.

ROS bag is more flexible (it can record any ROS topic), but data analysis is also often more time consuming (the recorded topics typically needs to be replayed and converted to CSV or JSON before analysis). As such, pal_interaction_logger is a good alternative for simple logging needs.

Read more about ROS bag.

Launch pal_interaction_logger#

pal_interaction_logger can be launched with the following command:

roslaunch pal_interaction_logger pal_interaction_logger.launch

By default pal_interaction_logger subscribes to the topic /interaction_logger. The log is saved in the following folder: ${HOME}/.pal/pal_interaction_logger/ under the name interaction_logger_YYYY_MM_DD.csv. The default values for the log location and topic can be set as arguments when launching the logger.

roslaunch pal_interaction_logger pal_interaction_logger.launch log_folder:=/path/to/desired/folder logger_topic:=/custom_topic_name

Publish log data#

Caution

Be mindful of the privacy implications of data logging. We generally recommend not to log data that could uniquely identify people interacting with the robot.

Please only do so after carefully consideration, and, where applicable, approval by your ethics committee.

Learn more on Data management, security, data privacy.

Publish to the /interaction_logger topic:

rostopic pub /interaction_logger std_msgs/String "data: 'game completed'"

Check that the log has been correctly written to the CSV file:

ssh pal@ari-0c
cd /home/pal/.pal/pal_interaction_logger/
cat interaction_logger_2022_11_15.csv

Each new log will result in a new line.

Time,Log
2022-11-15-12:39,game completed

Add pal_interaction_logger to the robot’s startup#

By default, this node is not running on the robot. If you wish to add it as a startup, follow the instructions in Configure an application to launch at start-up. Specifically, create the following files:

First create a new app:

ssh pal@ari-0c

cd /home/pal/.pal/pal_startup/apps/
nano interaction_logger.yaml

Paste the following content so that it launches the corresponding node:

roslaunch: "pal_interaction_logger pal_interaction_logger.launch"
dependencies: []

Create a new control file, or add it to an existing one, that defines custom programs the robot will execute on boot:

ssh pal@ari-0c
cd /home/pal/.pal/pal_startup/control/
nano my_demo_startup.yaml

Add the interaction logger startup:

- interaction_logger

Reboot the robot for changes to take effect.

Create a custom data logger#

You can easily create your own ROS data logger, to record custom data to a CSV file or to send it to an external database.

While pal_interaction_logger specifically subscribes to a std_msgs/String message, you might want to record other topics and message types. You might as well want additional fields in your CSV file, or the data received transferred to database such as MySQL<https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html>.

Note

As indicated above, you can also use ROS bag tool to record and replay arbitrary ROS topic.

Read more about ROS bag.

The following script implements a simple Python data logger. You can adjust it to your needs. Remember to deploy the code on the robot following instructions of Tutorial: Deploying ROS packages on the robot

import rospy
from std_msgs.msg import String
import os.path
import csv
from datetime import datetime

class InteractionLogger():
    _csv_filename = ""
    _logger_topic = ""
    _log_folder = ""

    def __init__(self):
        self._log_file = None
        self.config()

        self._logger_sub = rospy.Subscriber(
            self._logger_topic, String, self.interaction_callback
        )

    def config(self):
        # Get params
        self._log_folder = rospy.get_param("~log_folder", "log")
        self._logger_topic = rospy.get_param("~logger_topic", "logging_topic")

        # Create the CSV file
        self._csv_filename = (
            self._log_folder
            + "/interaction_logger_"
            + datetime.now().strftime("%Y_%m_%d")
            + ".csv"
        )

        # If folder does not exist, create folder
        if not os.path.exists(self._log_folder):
            os.makedirs(self._log_folder)

        # Create csv file with right headers
        if not os.path.exists(self._csv_filename):
            self.create_log_file()

    def open_log(self):

        f = open(self._csv_filename, "w")
        self._log_file = csv.writer(f)

    def interaction_callback(self, msg):

        log_data = msg.data
        log_time = datetime.now().strftime("%Y-%m-%d-%H:%M")
        self.write_log(log_data, log_time)

    def create_log_file(self):

        self.open_log()

        header = ["time", "message"]
        self._log_file.writerow(header)

    def write_log(self, log, log_time):

        if not os.path.exists(self._csv_filename):
            self.create_log_file()

        if not self._log_file:
            self.open_log()

        self._log_file.writerow([log_time, log])


if __name__ == "__main__":
    rospy.init_node("my_custom_data_logger")
    logger = InteractionLogger()
    rospy.spin()

See also#