Skip to content

Commit e130402

Browse files
authored
Separate timelines for message timestamps with a custom epoch (#11179)
1 parent 5ffd2de commit e130402

File tree

14 files changed

+226
-98
lines changed

14 files changed

+226
-98
lines changed

crates/utils/re_mcap/src/layers/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,12 @@ impl McapChunkDecoder {
111111

112112
let channel = msg.channel.as_ref();
113113
let channel_id = ChannelId(channel.id);
114+
let log_time_cell = crate::util::TimestampCell::guess_from_nanos(msg.log_time, "log_time");
115+
let publish_time_cell =
116+
crate::util::TimestampCell::guess_from_nanos(msg.publish_time, "publish_time");
114117
let timepoint = re_chunk::TimePoint::from([
115-
("log_time", crate::util::guess_epoch(msg.log_time)),
116-
("publish_time", crate::util::guess_epoch(msg.publish_time)),
118+
("log_time", log_time_cell.into_time_cell()),
119+
("publish_time", publish_time_cell.into_time_cell()),
117120
]);
118121

119122
if let Some((ctx, parser)) = self.parsers.get_mut(&channel_id) {

crates/utils/re_mcap/src/parsers/decode.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use re_chunk::{
66
};
77
use re_log_types::TimeCell;
88

9+
use crate::util::TimestampCell;
10+
911
/// Trait for parsing MCAP messages of a specific schema into Rerun chunks.
1012
///
1113
/// This trait defines the interface for converting MCAP messages into Rerun's internal
@@ -104,6 +106,22 @@ impl ParserContext {
104106
self
105107
}
106108

109+
/// Add a timestamp to the timeline using the provided timestamp cell.
110+
///
111+
/// The timeline name and [`TimeCell`] are automatically determined from the timestamp cell.
112+
/// For Unix epochs, creates a timestamp cell. For custom epochs, creates a duration cell.
113+
pub fn add_timestamp_cell(&mut self, timestamp_cell: TimestampCell) -> &mut Self {
114+
let timeline_name = TimelineName::from(timestamp_cell.timeline_name());
115+
let cell = timestamp_cell.into_time_cell();
116+
117+
self.timelines
118+
.entry(timeline_name)
119+
.or_insert_with(|| TimeColumn::builder(Timeline::new(timeline_name, cell.typ)))
120+
.with_row(cell.value);
121+
122+
self
123+
}
124+
107125
/// Consume this context and build all timelines into [`TimeColumn`]s.
108126
pub fn build_timelines(self) -> IntMap<TimelineName, TimeColumn> {
109127
self.timelines

crates/utils/re_mcap/src/parsers/ros2msg/rcl_interfaces/log.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,11 @@ use re_types::{
88
datatypes::Rgba32,
99
};
1010

11-
use crate::{
12-
parsers::{
13-
cdr,
14-
decode::{MessageParser, ParserContext},
15-
ros2msg::definitions::rcl_interfaces::{self, LogLevel},
16-
util::fixed_size_list_builder,
17-
},
18-
util::guess_epoch,
11+
use crate::parsers::{
12+
cdr,
13+
decode::{MessageParser, ParserContext},
14+
ros2msg::definitions::rcl_interfaces::{self, LogLevel},
15+
util::fixed_size_list_builder,
1916
};
2017

2118
/// Plugin that parses `rcl_interfaces/msg/Log` messages.
@@ -81,7 +78,10 @@ impl MessageParser for LogMessageParser {
8178
.context("Failed to decode `rcl_interfaces::Log` message from CDR data")?;
8279

8380
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
84-
ctx.add_time_cell("timestamp", guess_epoch(stamp.as_nanos() as u64));
81+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
82+
stamp.as_nanos() as u64,
83+
msg.channel.topic.clone(),
84+
));
8585

8686
self.text_entries.push(format!("[{name}] {log_msg}"));
8787
self.levels.push(level.to_string());

crates/utils/re_mcap/src/parsers/ros2msg/scalar_parser.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ impl<T: ScalarExtractor> MessageParser for ScalarMessageParser<T> {
8484
})?;
8585

8686
// Add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
87-
ctx.add_time_cell(
88-
"timestamp",
89-
crate::util::guess_epoch(message.header().stamp.as_nanos() as u64),
90-
);
87+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
88+
message.header().stamp.as_nanos() as u64,
89+
msg.channel.topic.clone(),
90+
));
9191

9292
let scalar_values = message.extract_scalars();
9393

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/camera_info.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ impl MessageParser for CameraInfoMessageParser {
9696
} = cdr::try_decode_message::<sensor_msgs::CameraInfo>(&msg.data)?;
9797

9898
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
99-
ctx.add_time_cell(
100-
"timestamp",
101-
crate::util::guess_epoch(header.stamp.as_nanos() as u64),
102-
);
99+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
100+
header.stamp.as_nanos() as u64,
101+
msg.channel.topic.clone(),
102+
));
103103

104104
self.distortion_models
105105
.values()

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/compressed_image.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ use re_types::{
1010
reflection::ComponentDescriptorExt as _,
1111
};
1212

13-
use crate::parsers::{
14-
cdr,
15-
decode::{MessageParser, ParserContext},
13+
use crate::{
14+
parsers::{
15+
cdr,
16+
decode::{MessageParser, ParserContext},
17+
},
18+
util::TimestampCell,
1619
};
1720

1821
/// Plugin that parses `sensor_msgs/msg/CompressedImage` messages.
@@ -47,10 +50,10 @@ impl MessageParser for CompressedImageMessageParser {
4750
} = cdr::try_decode_message::<sensor_msgs::CompressedImage<'_>>(&msg.data)?;
4851

4952
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
50-
ctx.add_time_cell(
51-
"timestamp",
52-
crate::util::guess_epoch(header.stamp.as_nanos() as u64),
53-
);
53+
ctx.add_timestamp_cell(TimestampCell::guess_from_nanos(
54+
header.stamp.as_nanos() as u64,
55+
msg.channel.topic.clone(),
56+
));
5457

5558
self.blobs.push(data.into_owned());
5659

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/image.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ impl MessageParser for ImageMessageParser {
7272
.context("Failed to decode sensor_msgs::Image message from CDR data")?;
7373

7474
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
75-
ctx.add_time_cell(
76-
"timestamp",
77-
crate::util::guess_epoch(header.stamp.as_nanos() as u64),
78-
);
75+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
76+
header.stamp.as_nanos() as u64,
77+
msg.channel.topic.clone(),
78+
));
7979

8080
let dimensions = [width, height];
8181
let img_format = decode_image_format(&encoding, dimensions)

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/imu.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ impl MessageParser for ImuMessageParser {
7272
.map_err(|err| Error::Other(anyhow::anyhow!(err)))?;
7373

7474
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
75-
ctx.add_time_cell(
76-
"timestamp",
77-
crate::util::guess_epoch(imu.header.stamp.as_nanos() as u64),
78-
);
75+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
76+
imu.header.stamp.as_nanos() as u64,
77+
msg.channel.topic.clone(),
78+
));
7979

8080
self.orientation.values().append_slice(&[
8181
imu.orientation.x,

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/joint_state.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ impl MessageParser for JointStateMessageParser {
4545
.map_err(|err| Error::Other(anyhow::anyhow!(err)))?;
4646

4747
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
48-
ctx.add_time_cell(
49-
"timestamp",
50-
crate::util::guess_epoch(header.stamp.as_nanos() as u64),
51-
);
48+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
49+
header.stamp.as_nanos() as u64,
50+
msg.channel.topic.clone(),
51+
));
5252

5353
for name in &name {
5454
self.joint_names.values().append_value(name);

crates/utils/re_mcap/src/parsers/ros2msg/sensor_msgs/magnetic_field.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ impl MessageParser for MagneticFieldMessageParser {
3939
.map_err(|err| Error::Other(anyhow::anyhow!(err)))?;
4040

4141
// add the sensor timestamp to the context, `log_time` and `publish_time` are added automatically
42-
ctx.add_time_cell(
43-
"timestamp",
44-
crate::util::guess_epoch(magnetic_field.header.stamp.as_nanos() as u64),
45-
);
42+
ctx.add_timestamp_cell(crate::util::TimestampCell::guess_from_nanos(
43+
magnetic_field.header.stamp.as_nanos() as u64,
44+
msg.channel.topic.clone(),
45+
));
4646

4747
// Convert magnetic field vector to Vector3D and store
4848
self.vectors.push(Vec3D([

0 commit comments

Comments
 (0)