Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ cmake --build . --config Release --target install
# :computer: Some utilities
The **bipedal-locomotion-framework** ships also some utilities that can help you in the everyday tests on a real robot. You can find them in the [`utilities` folder](./utilities). Each utility contains a well-documented` README` where you can find further details.

# :robot: Devices
The **bipedal-locomotion-framework** also provides YARP devices in the [`devices` folder](./devices).

| Device | Description |
| :--------------------------------------------: | :----------------------------------------------------------: |
| [`YarpRobotLoggerDevice`](./devices/YarpRobotLoggerDevice) | Logs robot sensor/actuator data, cameras, and exogenous signals to `.mat` files. Controllable via RPC (`record`, `saveData`, `stopRecording`). |

# :snake: Python
**bipedal-locomotion-framework** also provides Python bindings. Only a small set of the components implemented in the library have the corresponding Python bindings.

Expand Down
2 changes: 2 additions & 0 deletions bindings/python/YarpUtilities/src/VectorsCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ void CreateVectorsCollectionClient(pybind11::module& module)
py::arg("handler"))
.def("connect", &VectorsCollectionClient::connect)
.def("disconnect", &VectorsCollectionClient::disconnect)
.def("is_connected", &VectorsCollectionClient::isConnected)
.def("check_connection", &VectorsCollectionClient::checkConnection)
.def("get_metadata",
[](VectorsCollectionClient& impl)
-> BipedalLocomotion::YarpUtilities::VectorsCollectionMetadata {
Expand Down
234 changes: 122 additions & 112 deletions devices/YarpRobotLoggerDevice/README.md
Original file line number Diff line number Diff line change
@@ -1,140 +1,150 @@
# YARPRobotLoggerDevice

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.
The **YARPRobotLoggerDevice** is a YARP device based on `YarpSensorBridge` and [`robometry`](https://github.com/robotology/robometry) that logs data from robot sensors and actuators into `.mat` files. It also supports logging cameras (as `.mp4` videos or image frames), exogenous signals streamed over YARP ports, text logs, and frame transforms.

## Configuration Parameters
The logger is currently supported only for the robots listed in the [application folder](./app/robots). Each robot folder contains:
## Quick start

- `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:
Launch the logger with `yarprobotinterface`:

```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. All these files will be saved in the working directory in which `yarprobotinterface` has been launched.

## 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
<group name="ExogenousSignals">
<!-- List containing the names of exogenous signals. Each name should be associated to a sub-group -->
<param name="vectors_collection_exogenous_inputs">("balancing")</param>
<param name="vectors_exogenous_inputs">()</param>

<!-- Sub-group containing the information about the exogenous signal "balancing" -->
<group name="balancing">
<!-- Name of the port opened by the logger used to retrieve the exogenous signal data -->
<param name="local">"/yarp-robot-logger/exogenous_signals/balancing"</param>

<!-- Name of the port opened by the application used to stream the exogenous signal data -->
<param name="remote">"/balancing-controller/logger"</param>

<!-- Name of the exogenous signal (this will be the name of the matlab struct containing all the data associated to the exogenous signal) -->
<param name="signal_name">"balancing"</param>

<!-- Carrier used in the port connection -->
<param name="carrier">"udp"</param>
</group>
</group>
```

### 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 <BipedalLocomotion/YarpUtilities/VectorsCollectionServer.h>

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<BipedalLocomotion::ParametersHandler::YarpImplementation>(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
By default (`auto_start_logging: true`) the logger starts recording immediately. When you close `yarprobotinterface` (e.g. with `Ctrl+C`), the recorded data is **automatically saved** before the device shuts down. All output files (`.mat`, `.mp4`, `.md`) are written to the working directory.

## RPC commands

The logger exposes an RPC port at `<port_prefix>/commands/rpc:i` (default: `/yarp-robot-logger/commands/rpc:i`). You can control recording with the following commands using `yarp rpc`:

```console
yarp rpc /yarp-robot-logger/commands/rpc:i
```
In the main loop, add the following code to prepare and populate the data:

```c++
m_vectorsCollectionServer.prepareData(); // required to prepare the data to be sent
m_vectorsCollectionServer.clearData(); // optional see the documentation
| Command | Description |
|---|---|
| `record` | Start recording. Initializes sensor bridge, cameras, telemetry buffers and begins the periodic acquisition loop. |
| `saveData` | Save the recorded data to a `.mat` file and **stop recording**. The device returns to idle mode. Accepts an optional `tag` string that is appended to the filename (e.g. `saveData "walking_test"`). |
| `saveData "<tag>"` | Same as above, with the tag included in the output filename: `robot_logger_device_<tag>_<timestamp>.mat`. |
| `stopRecording` | Stop recording **without saving**. All buffered data is discarded and the device returns to idle mode. |

After `saveData` or `stopRecording`, you can call `record` again to start a new recording session.

// DCM
m_vectorsCollectionServer.populateData("dcm::position::measured", <signal>);
m_vectorsCollectionServer.populateData("dcm::position::desired", <signal>);
### Example session

m_vectorsCollectionServer.sendData();
```console
$ yarp rpc /yarp-robot-logger/commands/rpc:i
>> record
Response: [ok]
# ... robot performs some task ...
>> saveData "walking_trial_1"
Response: [ok]
# data saved to robot_logger_device_walking_trial_1_<timestamp>.mat
# logger is now idle
>> record
Response: [ok]
# ... another trial ...
>> stopRecording
Response: [ok]
# data discarded, no file saved
```

**Note:** Replace `<signal>` with the actual data you want to log.
### Auto-start mode

When `auto_start_logging` is set to `true` (the default), `record` is called automatically at device startup. If set to `false`, the device starts in idle mode and waits for an explicit `record` RPC command.

#### 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
## Configuration

The logger is currently supported for the robots listed in the [application folder](./app/robots). Each robot folder contains:

- `launch-yarp-robot-logger.xml`: `yarprobotinterface` configuration that launches the logger and associated devices.
- `yarp-robot-logger.xml`: Logger device parameters.
- `blf-yarp-robot-logger-interfaces/`: Interface configuration files for the sensor bridge.

### Key parameters

| Parameter | Default | Description |
|---|---|---|
| `sampling_period_in_s` | `0.01` | Logging period in seconds. |
| `port_prefix` | `/yarp-robot-logger` | Prefix for all YARP ports opened by the logger. |
| `auto_start_logging` | `true` | Start recording automatically on device startup. |
| `log_robot_data` | `true` | Log joint states, motor states, FT sensors, IMUs, etc. |
| `log_cameras` | `true` | Log camera images as video or frames. |
| `log_text` | `true` | Log YARP text logging messages. |
| `maximum_admissible_time_step` | - | Max time step between samples (skip logging on clock resets). |

## Logging exogenous data

class Module:
def __init__(self):
self.vectors_collection_server = blf.yarp_utilities.VectorsCollectionServer() # Logger server.
# all the other functions you need
The logger can also record exogenous data, i.e., signals not directly from robot sensors. To do this:

1. Configure the `ExogenousSignals` group in `yarp-robot-logger.xml`.
2. Stream data from your application using `VectorsCollectionServer`.

### Configuration

Add an `ExogenousSignals` group to `yarp-robot-logger.xml`:

```xml
<group name="ExogenousSignals">
<param name="vectors_collection_exogenous_inputs">("balancing")</param>
<param name="vectors_exogenous_inputs">()</param>

<group name="balancing">
<param name="local">"/yarp-robot-logger/exogenous_signals/balancing"</param>
<param name="remote">"/balancing-controller/logger"</param>
<param name="signal_name">"balancing"</param>
<param name="carrier">"udp"</param>
</group>
</group>
```
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.StdParametersHandler()
logger_option.set_parameter_string("remote", "/test/log")
if not self.vectors_collection_server.initialize(logger_option):
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

### Streaming from C++

```cpp
#include <BipedalLocomotion/YarpUtilities/VectorsCollectionServer.h>

// Configuration phase
BipedalLocomotion::YarpUtilities::VectorsCollectionServer server;
server.initialize(loggerOption->getGroup("LOGGER"));
server.populateMetadata("dcm::position::measured", {"x", "y"});
server.populateMetadata("dcm::position::desired", {"x", "y"});
server.finalizeMetadata();

// Main loop
server.prepareData();
server.clearData();
server.populateData("dcm::position::measured", measuredSignal);
server.populateData("dcm::position::desired", desiredSignal);
server.sendData();
```
In the main loop, add the following code to prepare and populate the data:

### Streaming from Python

```python
self.vectors_collection_server.prepare_data() # required to prepare the data to be sent
self.vectors_collection_server.clear_data() # optional see the documentation
self.vectors_collection_server.populate_data("dcm::position::measured", <signal>)
self.vectors_collection_server.populate_data("dcm::position::desired", <signal>)
self.vectors_collection_server.send_data()
import bipedal_locomotion_framework as blf

# Configuration phase
server = blf.yarp_utilities.VectorsCollectionServer()
handler = blf.parameters_handler.StdParametersHandler()
handler.set_parameter_string("remote", "/balancing-controller/logger")
server.initialize(handler)
server.populate_metadata("dcm::position::measured", ["x", "y"])
server.populate_metadata("dcm::position::desired", ["x", "y"])
server.finalize_metadata()

# Main loop
server.prepare_data()
server.clear_data()
server.populate_data("dcm::position::measured", measured_signal)
server.populate_data("dcm::position::desired", desired_signal)
server.send_data()
```
**Note:** Replace `<signal>` 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.
## Visualizing logged data

Use [robot-log-visualizer](https://github.com/ami-iit/robot-log-visualizer) to explore the `.mat` files:

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)
Then open the `.mat` file generated by the logger. See the [robot-log-visualizer README](https://github.com/ami-iit/robot-log-visualizer/blob/main/README.md) for details.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ BSD-3-Clause license. -->
<param name="port_prefix">/yarp-robot-logger</param>
<param name="log_text">true</param>
<param name="text_logging_subnames">("ergoCubGazeboV1/yarprobotinterface")</param>
<param name="log_code_status">true</param>
<param name="code_status_cmds">("bash ${ROBOTOLOGY_SUPERBUILD_SOURCE_DIR}/scripts/robotologyGitStatus.sh > {filename}_robotology.txt" "apt list --installed > {filename}_apt.txt")</param>
<param name="maximum_admissible_time_step">1.0</param>
<param name="log_code_status">true</param>
<param name="log_cameras">true</param>
<param name="log_frames">false</param>
<param name="log_robot_data">true</param>

<param name="auto_start_logging">true</param>

<param name="enable_real_time_logging" extern-name="enable_real_time_logging">false</param>
<group name="REAL_TIME_STREAMING">
<param name="remote">"/yarp-robot-logger/rt_logging"</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ BSD-3-Clause license. -->
<param name="port_prefix">/yarp-robot-logger</param>
<param name="log_text">true</param>
<param name="text_logging_subnames">("ergoCubGazeboV1/yarprobotinterface")</param>
<param name="log_code_status">true</param>
<param name="code_status_cmds">("bash ${ROBOTOLOGY_SUPERBUILD_SOURCE_DIR}/scripts/robotologyGitStatus.sh > {filename}_robotology.txt" "apt list --installed > {filename}_apt.txt")</param>
<param name="maximum_admissible_time_step">1.0</param>
<param name="log_cameras">true</param>
<param name="log_frames">false</param>
<param name="log_robot_data">true</param>

<param name="auto_start_logging">true</param>

<param name="enable_real_time_logging" extern-name="enable_real_time_logging">false</param>
<group name="REAL_TIME_STREAMING">
<param name="remote">"/yarp-robot-logger/rt_logging"</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ BSD-3-Clause license. -->
<param name="port_prefix">/yarp-robot-logger</param>
<param name="log_text">true</param>
<param name="text_logging_subnames">("ergocub-torso/yarprobotinterface")</param>
<param name="log_code_status">true</param>
<param name="code_status_cmd_prefixes">("ssh [email protected]" "ssh [email protected]")</param>
<param name="code_status_cmds">("ssh [email protected] 'bash ${ROBOTOLOGY_SUPERBUILD_SOURCE_DIR}/scripts/robotologyGitStatus.sh' > {filename}_robotology_10_0_2_2.txt" "ssh [email protected] 'apt list --installed' > {filename}_apt_10_0_2_2.txt" "ssh [email protected] 'bash ${ROBOTOLOGY_SUPERBUILD_SOURCE_DIR}/scripts/robotologyGitStatus.sh' > {filename}_robotology_10_0_2_3.txt" "ssh [email protected] 'apt list --installed' > {filename}_apt_10_0_2_3.txt")</param>
<param name="log_cameras">true</param>
<param name="log_frames">false</param>
<param name="log_robot_data">true</param>

<param name="auto_start_logging">true</param>

<param name="enable_real_time_logging" extern-name="enable_real_time_logging">false</param>
<group name="REAL_TIME_STREAMING">
<param name="remote">"/yarp-robot-logger/rt_logging"</param>
Expand Down

This file was deleted.

Loading
Loading