Persistence¶
The Persistable class is a mixin for objects that need to be persisted.
It provides a persistent method that can be used to make the object persistent.
Derived classes must implement the backup_to_dict and restore_from_dict methods.
Note that the persistence module contains a number of helper functions:
to_dict: converts (dictionaries or lists of) dataclasses into a dictionary (or list)from_dict: converts a dictionary into a dataclass of given typereplace_dict: replaces the content of a dictionary usingfrom_dictfor each itemreplace_list: replaces the content of a list usingfrom_dictfor each itemreplace_set: replaces the content of a set usingfrom_dictfor each itemreplace_dataclass: replaces the attributes of a dataclass with the values of a dictionary
Further helper functions can be used for importing and exporting all persistable objects:
- The
export_allmethod can be used to export all persistable objects to a dictionary. - The
import_allmethod can be used to import all persistable objects from a dictionary. - Likewise,
export_buttonandimport_buttonare UI elements based on these two methods that can be added to a page.
By default, data is stored in the ~/.rosys directory.
The filename is derived from the module name.
Both can be changed by setting the path and key parameters of the persistent method.
If you want to automatically keep daily backups, you can use the BackupSchedule module.
It will backup all the contents of your ~/.rosys directory at a configurable directory and at a given time each day.
When a maximum number of backup files is reached (specified with backup_count), it will delete the oldest file.
You should choose wisely which values to persist. In particular, avoid to persist volatile things like wheel odometry or other sensor readings to save CPU and IO bandwidth.
#!/usr/bin/env python3
import os
from typing import Any
from nicegui import ui
import rosys
class MySteerer(rosys.persistence.Persistable, rosys.driving.Steerer):
def backup_to_dict(self) -> dict[str, Any]:
print('Backup')
return {'speed_scaling': self.speed_scaling}
def restore_from_dict(self, data: dict[str, Any]) -> None:
print('Restore')
self.speed_scaling = data['speed_scaling']
shape = rosys.geometry.Prism.default_robot_shape()
wheels = rosys.hardware.WheelsSimulation()
steerer = MySteerer(wheels).persistent()
odometer = rosys.driving.Odometer(wheels)
robot = rosys.hardware.RobotSimulation([wheels])
@ui.page('/')
def page():
rosys.driving.keyboard_control(steerer)
with ui.row():
with ui.scene(width=600, height=400):
rosys.driving.robot_object(shape, odometer)
with ui.column(align_items='stretch'):
rosys.driving.joystick(steerer, size=50, color='blue')
with ui.row():
ui.label().bind_text_from(wheels, 'linear_velocity', lambda v: f'{v:.2f} m/s')
ui.label().bind_text_from(wheels, 'angular_velocity', lambda v: f'{v:.2f} rad/s')
ui.slider(min=0, max=5).props('label-always') \
.bind_value(steerer, 'speed_scaling') \
.on_value_change(steerer.request_backup)
ui.button('Restart RoSys', on_click=lambda: os.utime('main.py')).props('flat')
rosys.persistence.export_button().props('flat icon="download"')
rosys.persistence.import_button().props('flat icon="upload_file"')
ui.run(title='RoSys - Persistence')
Migration from the old PersistentModule class¶
The PersistentModule class has been replaced by the Persistable mixin in version 0.24.0.
To migrate, follow these steps:
- Replace
PersistentModulewithPersistablein the class definition. - Rename the
backupandrestoremethods tobackup_to_dictandrestore_from_dict. - Use the
persistentmethod to make objects persistent which used to be derived fromPersistentModule:KpiLogger,Schedule,PathPlanner,CameraProviderand derived classes. - If you called
PersistentModulewith apersistence_key, remove it and use thekeyparameter of thepersistentmethod instead.