diff --git a/devices/YarpRobotLoggerDevice/README.md b/devices/YarpRobotLoggerDevice/README.md index 22d2380943..e217093336 100644 --- a/devices/YarpRobotLoggerDevice/README.md +++ b/devices/YarpRobotLoggerDevice/README.md @@ -1,71 +1,137 @@ # YARPRobotLoggerDevice -The **YARPRobotLoggerDevice** is a YARP device based on `YarpSensorBridge` and `matioCpp` to record dataset from a YARP-based robot. - - - -## :running: How to use the device - -- Launch `yarprobotinterface` on the robot. - - Depending on your logger configuration file and on the data you want to collect you should run the main `yarprobotinterface` with a different option. In order to use the [defaul logger configuration files](./app/robots), use the following commands: - - **iCubGenova04** - - launch the `yarprobotinterface` with the `root_imu` device on the robot head - ``` - yarprobotinterface --config icub_wbd_inertials.xml - ``` - - **iCubGazeboV3** - - open the robot model in gazebo and launch `whole-body-dynamics` - ``` - YARP_ROBOT_NAME=iCubGazeboV3 yarprobotinterface --config launch-wholebodydynamics.xml - ``` - in case you started gazebo with the real-time clock option (`gazebo -slibgazebo_yarp_clock.so`) add `YARP_CLOCK=/clock` to the previous command. - ``` - YARP_CLOCK=/clock YARP_ROBOT_NAME=iCubGazeboV3 yarprobotinterface --config launch-wholebodydynamics.xml - ``` - -- Launch the logger device. - - In order to use the [defaul logger configuration files](./app/robots), set the `YARP_ROBOT_NAME` environment variable and launch the `yarprobotinterface` as follow - ``` - yarprobotinterface --config launch-yarp-robot-logger.xml - ``` - -- Press Ctrl+c to close the device, and the dataset is stored as the device is closed. - -## 💾 Data - - Depending on the configuration file, each dataset can contain: - - `time` vector with the YARP clock time stamps. - - `joint_state` that containins - - `joints`: name of the joints - - `joint_positions` - - `joint_velocities` - - `joint_torques` -- `Motor_state` that contains - - `motor_currents` - - `motor_velocities` - - `motor_positions` -- `PID` -- `Motor_PWM` -- `Accelerometer` struct containing data for each selected source. -- `CartesianWrench` struct containing data for each selected source. -- `FT` struct containing data for each selected source. -- `Gyros` struct containing data for each selected source. -- `Orientation` struct containing data for each selected source as roll-pitch-yaw euler angles. - -## 🏷️ Migrate mat files -### v0.6.0 -> v0.7.0 - -To migrate an existing `mat` file saved with the device version `v0.6.0` to `v0.7.0` you can run the matlab script `scripts/migrate_0_6_0_to_0_7_0.m` as -```matlab -% name of the robot -robot_name = 'iCubGenova09'; - -% path of the folder containing the mat files that will migrate -files_path = './dataset'; -migrate_0_6_0_to_0_7_0(files_path, robot_name); +The **YARPRobotLoggerDevice** is a YARP device based on `YarpSensorBridge` and [`robometry`](https://github.com/robotology/robometry) that allows logging data from robot sensors and actuators in a mat file. + +## Configuration Parameters +The logger is currently supported only for the robots listed in the [application folder](./app/robots). Each robot folder contains: + +- `launch-yarp-robot-logger.xml`: Configuration parameters for the `yarprobotinterface` to launch the logger device and associated devices. +- `yarp-robot-logger.xml`: Configuration parameters for the logger device. +- `blf-yarp-robot-logger-interfaces`: Folder containing all interfaces used by the logger device to log data. + +## How to Use the Logger +To use the logger, launch the `yarprobotinterface` with the `launch-yarp-robot-logger.xml` configuration file: + +```console +yarprobotinterface --config launch-yarp-robot-logger.xml +``` +When you close the yarprobotinterface, the logger will save the logged data in a mat file. Additionally, a md file will contain information about the software version in the robot setup. If video recording is enabled, a mp4 file with the video recording will also be generated. + +## How to log exogenous data +The `YarpRobotLoggerDevice` can also log exogenous data, i.e., data not directly provided by the robot sensors and actuators. To do this: +1. modify the `yarp-robot-logger.xml` file to specify the exogenous data to log +2. modify the application that streams the exogenous data + +### Modification `yarp-robot-logger.xml` configuration file +Modify the [`ExogenousSignalGroup` in the `yarp-robot-logger.xml` file](https://github.com/ami-iit/bipedal-locomotion-framework/blob/a3a8e9cb8a0c3532db81d814d4851009f8134195/devices/YarpRobotLoggerDevice/app/robots/ergoCubSN000/yarp-robot-logger.xml#L27-L37) to log the data streamed by an application that allows the robot to balance: + ```xml + + + ("balancing") + () + + + + + "/yarp-robot-logger/exogenous_signals/balancing" + + + "/balancing-controller/logger" + + + "balancing" + + + "udp" + + + ``` + +### Stream exogenous data +You need to modify the application that streams the exogenous data to open a port with the name specified in the `remote` parameter of the `balancing` sub-group. For example, if you want to stream the data from the your `balancing` application you need to use `BipedalLocomotion::YarpUtilities::VectorsCollectionServer` class as follows +#### C++ +If your application is written in C++ you can use the `BipedalLocomotion::YarpUtilities::VectorsCollectionServer` class as follows + +```c++ +#include + +class Module +{ + BipedalLocomotion::YarpUtilities::VectorsCollectionServer m_vectorsCollectionServer; /**< Logger server. */ +public: + // all the other functions you need +} +``` +The `m_vectorsCollectionServer` helps you to handle the data you want to send and to populate the metadata. To use this functionality, call `BipedalLocomotion::YarpUtilities::VectorsCollectionServer::populateMetadata` during the configuration phase. Once you have finished populating the metadata you should call `BipedalLocomotion::YarpUtilities::VectorsCollectionServer::finalizeMetadata` +```c++ +//This code should go into the configuration phase +auto loggerOption = std::make_shared(rf); +if (!m_vectorsCollectionServer.initialize(loggerOption->getGroup("LOGGER"))) +{ + log()->error("[BalancingController::configure] Unable to configure the server."); + return false; +} + +m_vectorsCollectionServer.populateMetadata("dcm::position::measured", {"x", "y"}); +m_vectorsCollectionServer.populateMetadata("dcm::position::desired", {"x", "y"}); + +m_vectorsCollectionServer.finalizeMetadata(); // this should be called only once ``` -You will find the new datasets in `/v070` +In the main loop, add the following code to prepare and populate the data: + +```c++ +m_vectorsCollectionServer.clearData(); // optional see the documentation + +// DCM +m_vectorsCollectionServer.populateData("dcm::position::measured", ); +m_vectorsCollectionServer.populateData("dcm::position::desired", ); + +m_vectorsCollectionServer.sendData(); +``` + +**Note:** Replace `` with the actual data you want to log. + + +#### Python +If your application is written in Python you can use the `BipedalLocomotion.yarp_utilities.VectorsCollectionServer` class as follows +```python +import bipedal_locomotion_framework as blf + +class Module: + def __init__(self): + self.vectors_collection_server = blf.yarp_utilities.VectorsCollectionServer() # Logger server. + # all the other functions you need +``` +The `vectors_collection_server` helps you to handle the data you want to send and to populate the metadata. To use this functionality, call `BipedalLocomotion.yarp_utilities.VectorsCollectionServer.populate_metadata` during the configuration phase. Once you have finished populating the metadata you should call `BipedalLocomotion.yarp_utilities.VectorsCollectionServer.finalize_metadata` +```python +#This code should go into the configuration phase +logger_option = blf.parameters_handler.YarpImplementation(rf) +if not self.vectors_collection_server.initialize(logger_option.get_group("LOGGER")): + blf.log().error("[BalancingController::configure] Unable to configure the server.") + raise RuntimeError("Unable to configure the server.") + +# populate the metadata +self.vectors_collection_server.populate_metadata("dcm::position::measured", ["x", "y"]) +self.vectors_collection_server.populate_metadata("dcm::position::desired", ["x", "y"]) + +self.vectors_collection_server.finalize_metadata() # this should be called only once when the metadata are ready +``` +In the main loop, add the following code to prepare and populate the data: +```python +self.vectors_collection_server.clear_data() # optional see the documentation +self.vectors_collection_server.populate_data("dcm::position::measured", ) +self.vectors_collection_server.populate_data("dcm::position::desired", ) +self.vectors_collection_server.send_data() +``` +**Note:** Replace `` with the actual data you want to log. + +## How to visualize the logged data +To visualize the logged data you can use [robot-log-visualizer](https://github.com/ami-iit/robot-log-visualizer). To use the `robot-log-visualizer` you can follow the instructions in the [README](https://github.com/ami-iit/robot-log-visualizer/blob/main/README.md) file. + +Once you have installed the `robot-log-visualizer` you can open it from the command line with the following command: +```console +robot-log-visualizer +``` +Then, you can open the mat file generated by the logger and explore the logged data as in the following video: + +[robot-log-visualizer.webm](https://github.com/ami-iit/robot-log-visualizer/assets/16744101/3fd5c516-da17-4efa-b83b-392b5ce1383b)