Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support std::chrono types for set_time on rerun::RecordingStream #4134

Merged
merged 4 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion docs/code-examples/timelines_example.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
for (auto frame : read_sensor_frames()) {
rec.set_time_sequence("frame_idx", frame.idx);
rec.set_time_seconds("sensor_time", frame.timestamp);
rec.set_time("sensor_time", frame.timestamp);

rec.log("sensor/points", rerun::Points3D(&frame.points));
}
9 changes: 5 additions & 4 deletions docs/content/getting-started/logging-cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ Starting our `main.cpp`:
#include <vector>

using namespace rerun::demo;
using namespace std::chrono_literals;

static constexpr size_t NUM_POINTS = 100;
```
Expand Down Expand Up @@ -278,12 +279,12 @@ Let's add our custom timeline.
Replace the section that logs the beads with a loop that logs the beads at different timestamps:
```cpp
for (int t = 0; t < 400; t++) {
float time = static_cast<float>(t) * 0.01f;
auto time = std::chrono::duration<float>(t) * 0.01f;

rec.set_time_seconds("stable_time", time);
rec.set_time("stable_time");

for (size_t i = 0; i < lines.size(); ++i) {
float time_offset = time + offsets[i];
float time_offset = time.count() + offsets[i];
auto c = static_cast<uint8_t>(bounce_lerp(80.0f, 230.0f, time_offset * 2.0f));

beads_positions[i] = rerun::Position3D(
Expand Down Expand Up @@ -357,7 +358,7 @@ for (int t = 0; t < 400; t++) {
"dna/structure",
rerun::archetypes::Transform3D(rerun::RotationAxisAngle(
{0.0f, 0.0f, 1.0f},
rerun::Angle::radians(time / 4.0f * TAU)
rerun::Angle::radians(time.count() / 4.0f * TAU)
))
);
}
Expand Down
1 change: 1 addition & 0 deletions docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"camino",
"Carreira",
"Chao",
"chrono",
"Clément",
"clippy",
"codegen",
Expand Down
12 changes: 7 additions & 5 deletions examples/cpp/clock/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@
#include <cmath>
#include <string>

using namespace std::chrono;

constexpr float TAU = 6.28318530717958647692528676655900577f;

void log_hand(
const rerun::RecordingStream& rec, const char* name, int step, float angle, float length,
const rerun::RecordingStream& rec, const char* name, seconds step, float angle, float length,
float width, uint8_t blue
) {
const auto tip = rerun::Vec3D{length * sinf(angle * TAU), length * cosf(angle * TAU), 0.0f};
const auto c = static_cast<uint8_t>(angle * 255.0f);
const auto color =
rerun::Color{static_cast<uint8_t>(255 - c), c, blue, std::max<uint8_t>(128, blue)};

rec.set_time_seconds("sim_time", step);
rec.set_time("sim_time", step);

rec.log(
std::string("world/") + name + "_pt",
Expand Down Expand Up @@ -47,8 +49,8 @@ int main() {
rec.log_timeless("world/frame", rerun::Boxes3D::from_half_sizes({{LENGTH_S, LENGTH_S, 1.0f}}));

for (int step = 0; step < num_steps; step++) {
log_hand(rec, "seconds", step, (step % 60) / 60.0f, LENGTH_S, WIDTH_S, 0);
log_hand(rec, "minutes", step, (step % 3600) / 3600.0f, LENGTH_M, WIDTH_M, 128);
log_hand(rec, "hours", step, (step % 43200) / 43200.0f, LENGTH_H, WIDTH_H, 255);
log_hand(rec, "seconds", seconds(step), (step % 60) / 60.0f, LENGTH_S, WIDTH_S, 0);
log_hand(rec, "minutes", seconds(step), (step % 3600) / 3600.0f, LENGTH_M, WIDTH_M, 128);
log_hand(rec, "hours", seconds(step), (step % 43200) / 43200.0f, LENGTH_H, WIDTH_H, 255);
}
}
11 changes: 6 additions & 5 deletions examples/cpp/dna/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <vector>

using namespace rerun::demo;
using namespace std::chrono_literals;

static constexpr size_t NUM_POINTS = 100;

Expand All @@ -18,7 +19,7 @@ int main() {
color_spiral(NUM_POINTS, 2.0f, 0.02f, 0.0f, 0.1f, points1, colors1);
color_spiral(NUM_POINTS, 2.0f, 0.02f, TAU * 0.5f, 0.1f, points2, colors2);

rec.set_time_seconds("stable_time", 0.0f);
rec.set_time("stable_time", 0s);

rec.log(
"dna/structure/left",
Expand Down Expand Up @@ -48,12 +49,12 @@ int main() {
std::vector<rerun::Color> beads_colors(lines.size());

for (int t = 0; t < 400; t++) {
float time = static_cast<float>(t) * 0.01f;
auto time = std::chrono::duration<float>(t) * 0.01f;

rec.set_time_seconds("stable_time", time);
rec.set_time("stable_time", time);

for (size_t i = 0; i < lines.size(); ++i) {
float time_offset = time + offsets[i];
float time_offset = time.count() + offsets[i];
auto c = static_cast<uint8_t>(bounce_lerp(80.0f, 230.0f, time_offset * 2.0f));

beads_positions[i] = rerun::Position3D(
Expand All @@ -73,7 +74,7 @@ int main() {
"dna/structure",
rerun::archetypes::Transform3D(rerun::RotationAxisAngle(
{0.0f, 0.0f, 1.0f},
rerun::Angle::radians(time / 4.0f * TAU)
rerun::Angle::radians(time.count() / 4.0f * TAU)
))
);
}
Expand Down
48 changes: 44 additions & 4 deletions rerun_cpp/src/rerun/recording_stream.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <chrono>
#include <cstdint> // uint32_t etc.
#include <optional>
#include <string_view>
Expand Down Expand Up @@ -177,9 +178,48 @@ namespace rerun {
/// For example: `rec.set_time_sequence("frame_nr", frame_nr)`.
///
/// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
/// @see set_timepoint, set_time_seconds, set_time_nanos, reset_time, disable_timeline
/// @see set_timepoint, set_time_seconds, set_time_nanos, reset_time, set_time, disable_timeline
void set_time_sequence(std::string_view timeline_name, int64_t sequence_nr) const;

/// Set the current time of the recording, for the current calling thread.
///
/// Used for all subsequent logging performed from this same thread, until the next call
/// to one of the time setting methods.
///
/// For example: `rec.set_time("sim_time", sim_time_secs)`.
///
/// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
/// @see set_timepoint, set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
template <typename TClock>
void set_time(std::string_view timeline_name, std::chrono::time_point<TClock> time) const {
set_time(timeline_name, time.time_since_epoch());
}

/// Set the current time of the recording, for the current calling thread.
///
/// Used for all subsequent logging performed from this same thread, until the next call
/// to one of the time setting methods.
///
/// For example: `rec.set_time("sim_time", sim_time_secs)`.
///
/// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
/// @see set_timepoint, set_time_sequence, set_time_seconds, set_time_nanos, reset_time, disable_timeline
template <typename TRep, typename TPeriod>
void set_time(std::string_view timeline_name, std::chrono::duration<TRep, TPeriod> time)
const {
if constexpr (std::is_floating_point<TRep>::value) {
set_time_seconds(
timeline_name,
std::chrono::duration_cast<std::chrono::duration<double>>(time).count()
);
} else {
set_time_nanos(
timeline_name,
std::chrono::duration_cast<std::chrono::nanoseconds>(time).count()
);
}
}

/// Set the current time of the recording, for the current calling thread.
///
/// Used for all subsequent logging performed from this same thread, until the next call
Expand All @@ -188,7 +228,7 @@ namespace rerun {
/// For example: `rec.set_time_seconds("sim_time", sim_time_secs)`.
///
/// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
/// @see set_timepoint, set_time_sequence, set_time_nanos, reset_time, disable_timeline
/// @see set_timepoint, set_time_sequence, set_time_nanos, reset_time, set_time, disable_timeline
void set_time_seconds(std::string_view timeline_name, double seconds) const;

/// Set the current time of the recording, for the current calling thread.
Expand All @@ -199,7 +239,7 @@ namespace rerun {
/// For example: `rec.set_time_nanos("sim_time", sim_time_nanos)`.
///
/// You can remove a timeline from subsequent log calls again using `rec.disable_timeline`.
/// @see set_timepoint, set_time_sequence, set_time_seconds, reset_time, disable_timeline
/// @see set_timepoint, set_time_sequence, set_time_seconds, reset_time, set_time, disable_timeline
void set_time_nanos(std::string_view timeline_name, int64_t nanos) const;

/// Stops logging to the specified timeline for subsequent log calls.
Expand All @@ -208,7 +248,7 @@ namespace rerun {
///
/// No-op if the timeline doesn't exist.
///
/// @see set_timepoint, set_time_sequence, set_time_seconds, reset_time
/// @see set_timepoint, set_time_sequence, set_time_seconds, set_time, reset_time
void disable_timeline(std::string_view timeline_name) const;

/// Clears out the current time of the recording, for the current calling thread.
Expand Down
8 changes: 8 additions & 0 deletions rerun_cpp/tests/recording_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,14 @@ SCENARIO("RecordingStream can set time without errors", TEST_TAG) {
SECTION("Setting time nanos does not log errors") {
check_logged_error([&] { stream.set_time_nanos("my sequence", 1); });
}
SECTION("Setting time via chrono duration does not log errors") {
using namespace std::chrono_literals;
check_logged_error([&] { stream.set_time("duration", 1.0s); });
check_logged_error([&] { stream.set_time("duration", 1000ms); });
}
SECTION("Setting time via chrono duration does not log errors") {
check_logged_error([&] { stream.set_time("timepoint", std::chrono::system_clock::now()); });
}
SECTION("Resetting time does not log errors") {
check_logged_error([&] { stream.reset_time(); });
}
Expand Down
Loading