主要内容

ros2bagrecorder

Record live topic data from ROS 2 network to bag file

Since R2026a

    Description

    Use the ros2bagrecorder object to record live topic data from a connected ROS 2 network into a bag file. Use the startRecording function to begin capturing and writing ROS 2 messages to the bag file. You can configure the recorder to capture topics by name, type, or regex patterns, or to exclude specific topics. During recording, you can pause and resume logging as needed. After stopping, you can restart recording on the same object by deleting the previous bag file and calling startRecording again with a new set of filters. To change recorder properties, create a new ros2bagrecorder object. By default, the recorder uses the rmw_fastrtps_cpp RMW implementation, unless you set the RMW_IMPLEMENTATION environment variable before creating the object.

    Creation

    Description

    bagRecorder = ros2bagrecorder(path) creates a ROS 2 bag recorder object that records messages into a ROS 2 bag file. Use the path input argument to set the Path property.

    The ROS 2 bag file takes its name from the parent folder. If the folders specified in path do not exist, the object automatically creates them and places the bag file in the specified location.

    bagRecorder = ros2bagrecorder(path, Name=Value) sets the storage and recorder settings using name-value arguments.

    Note

    • For improved and faster performance, it is recommended to use the MCAP storage format when creating a ROS 2 bag file for recording messages to it.

    • Properties containing include and exclude filters are not configured in the object. You can apply and modify these properties only by calling the startRecording function.

    example

    Properties

    expand all

    Node Data

    This property becomes a read-only after creation of the object.

    Output path to the ROS 2 bag file, specified as a string scalar or character vector.

    Data Types: char | string

    This property becomes a read-only after creation of the object.

    Name of the recorder node, specified as a string scalar or character vector. The recorder node takes the name of the created ros2bagrecorder object by default.

    Data Types: char | string

    This property becomes a read-only after creation of the object.

    Domain ID of the connected ROS 2 network, specified as a numeric scalar.

    Data Types: numeric

    This property is read-only.

    Current status of the recorder, represented as "Idle", "Recording", or "Paused".

    Data Types: char | string

    Storage Settings

    This property becomes a read-only after creation of the object.

    Size of the cache for writing messages to the ROS 2 bag file, specified as a positive integer in bytes. This value specifies the size of all messages combined that the cache can hold in its internal buffer.. If you reduce this value, the object writes more messages to the disk, which consumes more time and decreases performance of the drive.

    Data Types: uint64

    This property becomes a read-only after creation of the object.

    Storage format of the ROS 2 bag file, specified as "sqlite3" or "mcap".

    Data Types: char | string

    Configuration profile to write messages to ROS 2 bag file, specified as one of the following options:

    • "none" – No configuration profile is in use.

    • "fastwrite" – Configure the MCAP writer for the highest possible write throughput and lowest resource utilization.

    • "zstd_fast" – Configure the MCAP writer to use chunk compression with "zstd" compression. Chunk compression yields file sizes comparable to bags compressed with file-level compression, but allows tools to efficiently read messages without decompressing the entire bag. Chunk compression makes the file sizes about the same as if you compressed the whole bag file at once. However, it efficiently allows tools to read individual messages quickly without needing to decompress the whole file.

    • "zstd_small" – Configure the MCAP writer to write 4 MB chunks of message to the bag file, which are compressed using highest compression ratio of "zstd". This option produces very small bags, but can be high on resource usage to write.

    • "custom" – Configure MCAP writer with customized settings by providing the path to a storage configuration file.

    To set this property, set the StorageFormat property to "mcap".

    Data Types: char | string

    Configuration file path to customize settings to configure MCAP writer, specified as a string or character vector. The configuration file must be a .yaml file containing the configuration settings for the MCAP storage writer.

    To set this property, set the StorageConfigurationProfile property to "custom".

    Data Types: char | string

    This property is read-only.

    Serialization format of messages in the ROS 2 bag file, represented as 'cdr'. This value is the default binary serialization format used by Data Distribution Service (DDS), which is the default middleware of ROS 2.

    Data Types: char | string

    Size of the ROS 2 bag file which acts as a threshold value to enable splitting, specified as a nonzero positive numeric scalar in kilobytes (kB). The specified value must be greater than 84 kB.

    For example, if SplitSize is set to 100 kB, it creates a new bag after the size of the logged data equals to 100 kB. The default value Inf writes data to a single file.

    Data Types: double | uint64

    Time elapsed in writing a message to a ROS 2 bag file, which acts as a threshold value to enable splitting, specified as one of these values:

    • Nonzero positive numeric scalar – Time elapsed in seconds.

    • Structure – ros2message entity of builtin_interfaces/Time and builtin_interfaces/Duration message types.

    For example, if SplitDuration is set to 5 seconds, it creates a new bag after every 5 seconds of duration. If you specify a non-integer value, it rounds to the nearest integer such as, 2.3 becomes 2 and 2.6 becomes 3. The default value Inf writes data to a single file.

    Data Types: double | uint64 | struct

    Compression format for creating a ROS 2 bag file, specified as "none" or "zstd". To not use a compression format, set this property to "none". To use the ZSTD compression format, set this property to "zstd" and the CompressionMode to "file" or "message".

    Data Types: char | string

    Compression mode for the ROS 2 bag file, specified as "none", "file" or "message". To not use a compression format, set this property and the CompressionFormat property to "none". To use the ZSTD compression format, set the CompressionFormat property to "zstd" and CompressionMode to "file" to compress each bag file or "message" to compress each message in the bag file.

    Data Types: char | string

    Recorder Settings

    This property becomes a read-only after creation of the object.

    Flag to enable the recorder to automatically detect and subscribe to new topics on the ROS 2 network during runtime, specified as "true" (1) or "false" (0). This option is useful in dynamic environments where topics can appear or disappear. Set this property to "true" (1) to use the UseSimTime property.

    Data Types: logical

    This property becomes a read-only after creation of the object.

    Flag enabling the recorder to use simulation time from the /clock topic instead of system time, specified as "false" (0) or "true" (1). To enable this property, you must set EnableDiscovery to "true".

    Data Types: logical

    This property becomes a read-only after creation of the object.

    Interval, in milliseconds, at which the recorder polls the ROS 2 network for available topics, specified as a numeric scalar value. A shorter interval enables faster detection of new or removed topics, while a longer interval reduces resource overhead.

    Data Types: uint32 | uint64

    Include Filters

    Name of topics to include during recording, specified as a string scalar, character vector, or a cell array.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Name of topic types to include during recording, specified as a string scalar, character vector, or a cell array.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Name of topics to include during recording, that matches regular expressions, specified as a string scalar or character vector.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Option to record hidden topics, specified as "false" (0) or "true" (1).

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Option to record unpublished topics, specified as "false" (0) or "true" (1).

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Exclude Filters

    Name of topics to exclude from recording, specified as a string scalar, character vector, or a cell array.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Name of topic types to exclude from recording, specified as a string scalar, character vector, or a cell array.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Name of topics to exclude from recording, that matches regular expressions, specified as a string scalar or character vector.

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Option to exclude leaf topics from recording, specified as "false" (0) or "true" (1).

    You can apply or modify these settings only through the startRecording function when you start a new recording on the same object after deleting the previous bag file.

    Object Functions

    startRecordingStart recording live topic data from ROS 2 network into bag file
    pauseRecordingPause recording live topic data from ROS 2 network without closing bag writer
    resumeRecordingResume recording live topic data from a ROS 2 network after pausing
    stopRecordingStop recording live topic data from ROS 2 network

    Examples

    collapse all

    Configure a ros2bagrecorder object to capture a subset of ROS 2 topics by filtering the topics using topic names, topic (message) types, and regular expressions (regex). The object records a topic only if matches the conditions specified in the filters.

    Create a ROS 2 node to host publishers for simulated sensor data.

    sensorNode = ros2node('SensorNode');

    Create publishers for different message types, such as string, laser, image, and lidar.

    sensorChatterPub = ros2publisher(sensorNode,'/chatter','std_msgs/String');
    laserPub         = ros2publisher(sensorNode,'/laser','sensor_msgs/LaserScan');
    cameraPub        = ros2publisher(sensorNode,'/camera_image','sensor_msgs/Image');
    lidarPub         = ros2publisher(sensorNode,'/lidar_points','sensor_msgs/PointCloud2');

    Create a recorder and start recording by filtering by topic, topic types, and regex patterns. You shall see the filters to include topics operate on OR logic by matching chatter and laser topics by topic name, image topics by topic type, and lidar topics by regex.

    bagName = "TargetedTopicsBag" + string(datetime("now",Format="_yyyyMMdd_HHmmss"));
    recorder = ros2bagrecorder(bagName);
    startRecording(recorder, ...
        IncludeTopics={'/chatter','/laser'}, ...
        IncludeTopicTypes={'sensor_msgs/Image'}, ...
        IncludeRegex='/lidar*');
    disp("Recording started...");
    Recording started...
    

    Prepare message instances to publish data for each topic.

    textMsg = ros2message(sensorChatterPub);
    imageMsg = ros2message(cameraPub);
    laserMsg = ros2message(laserPub);
    lidarMsg = ros2message(lidarPub);

    Publish messages on each topic to simulate sensor activity.

    for k = 1:5
        textMsg.data = sprintf('Sensor log entry %d', k);
        send(sensorChatterPub,textMsg);
        send(laserPub,laserMsg);
        send(cameraPub,imageMsg);
        send(lidarPub,lidarMsg);
        fprintf("Published all messages for iteration %d\n", k);
        pause(0.3)
    end
    Published all messages for iteration 1
    Published all messages for iteration 2
    Published all messages for iteration 3
    Published all messages for iteration 4
    Published all messages for iteration 5
    

    Stop recording.

    stopRecording(recorder);
    disp("Recording stopped.");
    Recording stopped.
    

    View the recorded messages.

    bagReader = ros2bagreader(bagName);
    disp(bagReader.AvailableTopics(:,1:2))
                         NumMessages          MessageType      
                         ___________    _______________________
    
        /camera_image         5         sensor_msgs/Image      
        /chatter              5         std_msgs/String        
        /laser                5         sensor_msgs/LaserScan  
        /lidar_points         5         sensor_msgs/PointCloud2
    

    Record only lightweight topics while excluding high-bandwidth data such as images and point clouds. The filters to exclude topics take priority by default, which means if a topic matches both include and exclude criteria, the object excludes that topic. To optimize storage and make long-term logging efficient, enable MCAP storage, compression, and file splitting.

    Create a node to simulate telemetry and sensor data sources.

    telemetryNode = ros2node('TelemetryNode');

    Create publishers for various message types, such as status, image, laser, point cloud, and altitude.

    statusPub   = ros2publisher(telemetryNode,'/system_status','std_msgs/String');
    imagePub    = ros2publisher(telemetryNode,'/front_camera','sensor_msgs/Image');
    laserPub    = ros2publisher(telemetryNode,'/laser','sensor_msgs/LaserScan');
    lidarPub    = ros2publisher(telemetryNode,'/lidar_cloud','sensor_msgs/PointCloud2');
    altitudePub = ros2publisher(telemetryNode,'/altitude','std_msgs/UInt64');

    Configure recorder with MCAP storage format and file compression profile, with 5‑second bag splitting.

    bagName = "OptimizedStorageBag" + string(datetime("now",Format="_yyyyMMdd_HHmmss"));
    
    recorder = ros2bagrecorder(bagName, ...
        StorageFormat="mcap", ...
        StorageConfigurationProfile="zstd_fast", ...
        SplitDuration=5);

    Start recording while excluding topics carrying large data, such as images, lasers, and point clouds.

    startRecording(recorder, ...
        ExcludeTopics={'/front_camera','/laser'}, ...
        ExcludeTopicTypes={'sensor_msgs/Image','sensor_msgs/PointCloud2'});
    
    disp("Recording started...");
    Recording started...
    

    Prepare messages for all publishers.

    statusMsg   = ros2message(statusPub);
    altitudeMsg = ros2message(altitudePub);
    imageMsg    = ros2message(imagePub);
    laserMsg    = ros2message(laserPub);
    lidarMsg    = ros2message(lidarPub);

    Simulate publishing for 30 cycles.

    for k = 1:30
        % Status and altitude
        statusMsg.data = sprintf('System OK, cycle %d', k);
        altitudeMsg.data = uint64(100 + 5*k);
    
        % Image message
        imageMsg.header.stamp.sec = int32(k);
        imageMsg.height = uint32(480);
        imageMsg.width  = uint32(640);
        imageMsg.encoding = 'rgb8';
        imageMsg.data = uint8(zeros(1, imageMsg.height * imageMsg.width * 3));
    
        % LaserScan message
        laserMsg.angle_min = single(-1.57);
        laserMsg.angle_max = single(1.57);
        laserMsg.angle_increment = single(0.0314);
        laserMsg.time_increment = single(0.0);
        laserMsg.scan_time = single(0.1);
        laserMsg.range_min = single(0.0);
        laserMsg.range_max = single(10.0);
        laserMsg.ranges = single(rand(1,100));
    
        % PointCloud2 message
        lidarMsg.header.frame_id = 'lidar_frame';
        lidarMsg.height = uint32(1);
        lidarMsg.width  = uint32(100);
        lidarMsg.data   = uint8(zeros(1, lidarMsg.width * 16));
    
        % Publish all
        send(statusPub,statusMsg);
        send(altitudePub,altitudeMsg);
        send(imagePub,imageMsg);
        send(laserPub,laserMsg);
        send(lidarPub,lidarMsg);
    
        fprintf("Published all message types, cycle %d\n", k);
        pause(0.5);
    end
    Published all message types, cycle 1
    Published all message types, cycle 2
    Published all message types, cycle 3
    Published all message types, cycle 4
    Published all message types, cycle 5
    Published all message types, cycle 6
    Published all message types, cycle 7
    Published all message types, cycle 8
    Published all message types, cycle 9
    Published all message types, cycle 10
    Published all message types, cycle 11
    Published all message types, cycle 12
    Published all message types, cycle 13
    Published all message types, cycle 14
    Published all message types, cycle 15
    Published all message types, cycle 16
    Published all message types, cycle 17
    Published all message types, cycle 18
    Published all message types, cycle 19
    Published all message types, cycle 20
    Published all message types, cycle 21
    Published all message types, cycle 22
    Published all message types, cycle 23
    Published all message types, cycle 24
    Published all message types, cycle 25
    Published all message types, cycle 26
    Published all message types, cycle 27
    Published all message types, cycle 28
    Published all message types, cycle 29
    Published all message types, cycle 30
    

    Stop recording.

    stopRecording(recorder);
    disp("Recording stopped.");
    Recording stopped.
    

    View the recorded topics and message types.

    You can also verify in the example working folder that the recorded bag has been split into 3 files.

    bagReader = ros2bagreader(bagName);
    disp(bagReader.AvailableTopics(:,1:2))
                               NumMessages               MessageType            
                               ___________    __________________________________
    
        /altitude                  30         std_msgs/UInt64                   
        /events/write_split         2         rosbag2_interfaces/WriteSplitEvent
        /parameter_events           0         rcl_interfaces/ParameterEvent     
        /random_topic               0         std_msgs/String                   
        /rosout                     9         rcl_interfaces/Log                
        /system_status             30         std_msgs/String                   
    

    Start, pause, resume, and stop a recording session dynamically while messages are being published from multiple data sources. The publishing continues uninterrupted, and you can control recording manually or based on external conditions.

    Create a node for a vehicle system that publishes telemetry, camera, and lidar data.

    vehicleNode = ros2node('/VehicleNode');
    telemetryPub = ros2publisher(vehicleNode,'/car_telemetry','std_msgs/String');
    cameraPub    = ros2publisher(vehicleNode,'/car_camera_feed','sensor_msgs/Image');
    temperaturePub     = ros2publisher(vehicleNode,'/temperature','sensor_msgs/Temperature');

    By default, the recorder captures all topics. In this example, you record topics using IncludeRegex and ExcludeTopics filters. It includes all topics matching /car* but excludes the back camera feed.

    bagName = "DynamicRecordingBag" + string(datetime("now",Format="_yyyyMMdd_HHmmss"));
    recorder = ros2bagrecorder(bagName);
    
    startRecording(recorder,IncludeRegex='/car*',ExcludeTopics='/car_camera_feed');
    disp("Recording started.");
    Recording started.
    

    Set up message structures for telemetry, camera, and temperature data.

    % Set up for callback structure
    pubStruct.telemetryPub = telemetryPub;
    pubStruct.cameraPub = cameraPub;
    pubStruct.temperaturePub = temperaturePub;
    
    % Set up for sample image message structure
    telemetryMsg = ros2message(telemetryPub);
    temperatureMsg = ros2message(temperaturePub);
    imageMsg = ros2message(cameraPub);
    imageMsg.height = uint32(480);
    imageMsg.width = uint32(640);
    imageMsg.step = uint32(imageMsg.width * 3); 
    imageMsg.encoding = 'rgb8';
    
    pubStruct.telemetryMsg = telemetryMsg;
    pubStruct.imageMsg = imageMsg;
    pubStruct.temperatureMsg = temperatureMsg;

    Publishing continues regardless of the recording state. The callback function sends telemetry, camera, and temperature messages at regular intervals until all messages are published or the script ends.

    function publishCallback(timerObj, pubStruct)
        idx = timerObj.UserData.idx;
        totalMsgs = timerObj.UserData.totalMsgs;
    
        if idx <= totalMsgs
            % Telemetry
            pubStruct.telemetryMsg.data = sprintf('Telemetry data message %d', idx);
            send(pubStruct.telemetryPub, pubStruct.telemetryMsg);
    
            % Back Camera
            pubStruct.imageMsg.data = randi([0 255], pubStruct.imageMsg.height, pubStruct.imageMsg.width, 3, 'uint8');
            send(pubStruct.cameraPub, pubStruct.imageMsg);
    
            % Temperature
            pubStruct.temperatureMsg.temperature = randi([0 100]);
            send(pubStruct.temperaturePub, pubStruct.temperatureMsg);
    
            timerObj.UserData.idx = idx + 1;
        else
            stop(timerObj);
        end
    end

    Create and start a timer to publish messages at a fixed rate.

    timerObj = timer('ExecutionMode','fixedRate','Period',0.5,...
        'TimerFcn', @(timerObj,~)publishCallback(timerObj,pubStruct));
    timerObj.UserData.idx = 1;
    timerObj.UserData.totalMsgs = 2000;
    start(timerObj);

    You can pause, resume, or stop recording manually at any time or based on external conditions. These options enable you to control the recording during a live session.

    pauseRecording(recorder);
    disp("Paused recording");
    Paused recording
    
    resumeRecording(recorder);
    disp("Resumed recording");
    Resumed recording
    
    stopRecording(recorder);
    disp("Recording stopped.")
    Recording stopped.
    

    After stopping the recording, inspect the recorded topics and message types.

    bagReader = ros2bagreader(bagName);
    disp(bagReader.AvailableTopics(:,1:2))
                          NumMessages      MessageType  
                          ___________    _______________
    
        /car_telemetry         1         std_msgs/String
    

    You can see that messages published when the recording was active are stored in the bag file, while those published when the recording was paused are not recorded.

    Version History

    Introduced in R2026a