8.1 KiB
LifecycleManager (assignments::two::g2_2025_lifecycle_node)
Overview
The LifecycleManager is the lifecycle node responsible for receiving the data of the ESP32-IMU combination via serial/MQTT and publishing that data to the database management node. For the functionality outside of the lifecycle see HardwareInterface.md
Implementation Details
Parameters
device_path(string, default: "/dev/ttyUSB0"): Serial device path for hardware connection (e.g., USB serial adapter).baudrate(int, default: 115200): Serial communication baud rate in bits per second.comm_t(string, default: "serial"): Communication type selector—either "serial" or "mqtt".
Constructor
LifecycleManager()
- Initializes ROS2 lifecycle node with name
lifecycle_manager - Declares and reads configuration parameters:
device_path,baudrate, andcomm_t - Creates a shared instance of
HardwareInterfacefor managing all hardware operations - Logs initialization status and readiness
Core Functions
CallbackReturn on_configure(const State&)
- Enters the Unconfigured → Inactive transition
- Checks the
comm_tparameter to route initialization:- MQTT mode: Calls
hw_interface->mqtt_configure()to set up the MQTT client and broker connection - Serial mode: Calls
hw_interface->open_device(device_path_, baudrate_)to open and configure the serial port
- MQTT mode: Calls
- Returns
SUCCESSif device initialization succeeds,FAILUREif serial/MQTT setup fails - Logs configuration status and any errors
- Example test code (currently commented) demonstrates direct JSON parsing for validation
CallbackReturn on_activate(const State&)
- Enters the Inactive → Active transition
- Checks the
comm_tparameter to start the appropriate reader:- MQTT mode: Calls
hw_interface->mqtt_reader()to attach MQTT callbacks and begin receiving messages - Serial mode: Calls
hw_interface->start_read()to spawn a background thread that continuously reads from the serial device
- MQTT mode: Calls
- Returns
SUCCESSafter reader startup - Logs activation status and selected communication type
CallbackReturn on_deactivate(const State&)
- Enters the Active → Inactive transition
- Checks the
comm_tparameter to cleanly stop operations:- MQTT mode: Calls
hw_interface->close_mqtt_conn()to disconnect from the broker and clean up resources - Serial mode:
- Verifies device state with
hw_interface->is_device_open() - Calls
hw_interface->stop_read()to signal the reader thread to exit and joins it - Calls
hw_interface->close_device()to release the serial port
- Verifies device state with
- MQTT mode: Calls
- Returns
SUCCESSafter cleanup completes - Logs deactivation and resource release
CallbackReturn on_shutdown(const State&)
- Enters the Inactive → Finalized transition
- Performs final shutdown logging
- Returns
SUCCESS
CallbackReturn on_cleanup(const State&)
- Called during error recovery or explicit cleanup commands
- Performs resource cleanup and state logging
- Returns
SUCCESS
Communication Architecture
The LifecycleManager switches communication type depending on the comm_t parameter:
Serial Communication
-
Configuration Phase (
on_configure):- Opens the serial device at the path specified by
device_pathand baudrate
- Opens the serial device at the path specified by
-
Activation Phase (
on_activate):- Spawns a background reader thread via
hw_interface->start_read() - Continuously polls the serial device with a timeout
- Reads are accumulated in a partial buffer, split on newline, and parsed as JSON
- Each valid JSON IMU payload is parsed into a
sensor_msgs::msg::Imuand published to the ROS topicimu/data
- Spawns a background reader thread via
-
Deactivation Phase (
on_deactivate):- Signals the reader thread to stop via atomic flag
- Joins the thread to ensure clean termination
- Closes the serial device
MQTT Communication
-
Configuration Phase (
on_configure):- Creates a persistent MQTT async client pointing to the broker at
SERVER_ADDRESS(default:tcp://localhost:1883) - Initializes MQTT callback infrastructure
- Creates a persistent MQTT async client pointing to the broker at
-
Activation Phase (
on_activate):- Attaches MQTT callbacks to the client
- Subscribes to the topic specified by
TOPIC(default:esp32/imu) - The async client runs background threads to receive messages
-
Deactivation Phase (
on_deactivate):- Disconnects from the broker
- Cleans up MQTT client and callback resources
Lifecycle Commands
To interact with the LifecycleManager from the command line, use the following ROS2 lifecycle service calls:
# List current lifecycle state
ros2 lifecycle list /lifecycle_manager
# Transition: UNCONFIGURED -> INACTIVE
ros2 lifecycle set /lifecycle_manager configure
# Transition: INACTIVE -> ACTIVE
ros2 lifecycle set /lifecycle_manager activate
# Transition: ACTIVE -> INACTIVE
ros2 lifecycle set /lifecycle_manager deactivate
# Transition: INACTIVE -> FINALIZED
ros2 lifecycle set /lifecycle_manager shutdown
Data Flow
Serial Data Flow
Hardware Device
↓
Serial Port (/dev/ttyUSB0)
↓
Background Reader Thread (start_read)
↓
Partial Buffer Accumulation
↓
JSON Line Extraction & Sanitization
↓
parse_data() ← Deserializes JSON to sensor_msgs::msg::Imu
↓
imu_publisher → ROS2 Topic (`imu_data`)
MQTT Data Flow
MQTT Broker (localhost:1883)
↓
MQTT Async Client (Background Thread)
↓
Subscription to Topic (esp32/imu)
↓
MQTT Callback Handler
↓
parse_data() ← Deserializes JSON to sensor_msgs::msg::Imu
↓
imu_publisher → ROS2 Topic (`imu_data`)
Error Handling
- Serial Device Failures: If
open_device()fails during configuration,on_configure()returnsFAILUREand the system remains in theUNCONFIGUREDstate - Communication Errors: JSON parse errors from invalid payloads are caught and logged without crashing the node; the reader continues listening for the next message
- Thread Safety: The reader thread uses an atomic flag (
reading_) for clean stop signaling and ensures all resources are properly joined before returning fromon_deactivate()
Design Patterns
- Strategy Pattern: The
comm_tparameter enables runtime selection of communication backend without changing node code - Lifecycle Pattern: Follows ROS2 managed node pattern for predictable initialization, startup, and shutdown sequences
- Thread Safety: Atomic flags and resource cleanup ensure the reader thread can be safely started and stopped
- Buffer Accumulation: Partial message buffering handles fragmented serial reads and ensures complete JSON objects are parsed
Integration with HardwareInterface
The LifecycleManager delegates all hardware operations to the HardwareInterface class:
| Operation | Method | Lifecycle Phase |
|---|---|---|
| Open serial device | open_device(path, baud) |
on_configure |
| Start reading | start_read() |
on_activate |
| Stop reading | stop_read() |
on_deactivate |
| Close serial device | close_device() |
on_deactivate |
| Configure MQTT | mqtt_configure() |
on_configure |
| Start MQTT reading | mqtt_reader() |
on_activate |
| Close MQTT connection | close_mqtt_conn() |
on_deactivate |
| Parse JSON payload | parse_data(json_string) |
on_activate (continuous) |
| Publish IMU message | publish_imu_data(imu_msg) |
on_activate (continuous) |
Usage Example
# Launch the node with serial communication at /dev/ttyUSB0, 115200 baud
ros2 run g2_2025_imu_reader_pkg g2_2025_lifecycle_node \
--ros-args \
-p device_path:=/dev/ttyUSB0 \
-p baudrate:=115200 \
-p comm_t:=serial
# Alternatively, launch with MQTT communication
ros2 run g2_2025_imu_reader_pkg g2_2025_lifecycle_node \
--ros-args \
-p comm_t:=mqtt
# In another terminal, configure and activate the lifecycle
ros2 lifecycle set /lifecycle_manager configure
ros2 lifecycle set /lifecycle_manager activate
# Subscribe to published IMU data
ros2 topic echo /imu_data
# Deactivate and shutdown
ros2 lifecycle set /lifecycle_manager deactivate
ros2 lifecycle set /lifecycle_manager shutdown