rerun data/droid-example.rrdrerun server -d data/droidrerun rerun+http://localhost:51234rerun data/droid/droid-example.rrd data/droid/droid-blueprint.rbl| import rerun as rr | |
| from numpy.random import default_rng | |
| def main(): | |
| rr.init("step1_hello_rerun", spawn=True) | |
| instructions = """# 🎯 Step 1: Hello, Rerun! | |
| Welcome to your first Rerun visualization! | |
| ## What's happening: | |
| 1. We initialized Rerun with `rr.init()` | |
| 2. We generated random 2D and 3D points with colors and radii | |
| 3. We logged both 2D and 3D point clouds to the viewer | |
| 4. The viewer automatically opened to show our data | |
| """ | |
| rr.log( | |
| "instructions", | |
| rr.TextDocument(instructions, media_type=rr.MediaType.MARKDOWN), | |
| static=True, | |
| ) | |
| rng = default_rng(12345) | |
| n_bubbles = 10 | |
| positions_d3 = rng.uniform(-3, 3, size=[n_bubbles, 3]) | |
| positions_d2 = positions_d3[:, :2] | |
| colors = rng.uniform(0, 255, size=[n_bubbles, 4]) | |
| radii = rng.uniform(0, 1, size=[n_bubbles]) | |
| rr.log("points/2d", rr.Points2D(positions_d2, colors=colors, radii=radii)) | |
| rr.log("points/3d", rr.Points3D(positions_d3, colors=colors, radii=radii)) | |
| if __name__ == "__main__": | |
| main() |
| import math | |
| import rerun as rr | |
| def new_location(center_x, center_y, x, y, angle): | |
| cos_a = math.cos(angle) | |
| sin_a = math.sin(angle) | |
| # Translate to origin | |
| translated_x = x - center_x | |
| translated_y = y - center_y | |
| # Rotate | |
| new_x = translated_x * cos_a - translated_y * sin_a + center_x | |
| new_y = translated_x * sin_a + translated_y * cos_a + center_y | |
| return new_x, new_y | |
| def main(): | |
| rr.init("step2_points_animation_colors", spawn=True) | |
| square_points = [ | |
| [0, 0], | |
| [1, 0], | |
| [1, 1], | |
| [0, 1], | |
| ] | |
| center = [0.5, 0.5] | |
| point_names = [f"Point_{x}" for x in range(4)] | |
| rr.log( | |
| "animated_square/origin", | |
| rr.Points2D( | |
| [center], | |
| colors=[[0, 0, 0]], | |
| radii=[0.1], | |
| show_labels=True, | |
| labels=["Origin"], | |
| ), | |
| static=True, | |
| ) | |
| for frame in range(360): | |
| rr.set_time("frame", sequence=frame) | |
| angle = frame * 0.05 | |
| rotated_points = [] | |
| for point in square_points: | |
| new_x, new_y = new_location(center[0], center[1], point[0], point[1], angle) | |
| rotated_points.append([new_x, new_y]) | |
| dynamic_colors = [] | |
| for i in range(len(square_points)): | |
| hue = (frame * 2 + i * 90) % 360 | |
| c = 1.0 | |
| x_color = c * (1 - abs((hue / 60) % 2 - 1)) | |
| if 0 <= hue < 60: | |
| r, g, b = c, x_color, 0 | |
| elif 60 <= hue < 120: | |
| r, g, b = x_color, c, 0 | |
| elif 120 <= hue < 180: | |
| r, g, b = 0, c, x_color | |
| elif 180 <= hue < 240: | |
| r, g, b = 0, x_color, c | |
| elif 240 <= hue < 300: | |
| r, g, b = x_color, 0, c | |
| else: | |
| r, g, b = c, 0, x_color | |
| dynamic_colors.append([int(r * 255), int(g * 255), int(b * 255)]) | |
| dynamic_radii = [] | |
| for i in range(len(square_points)): | |
| base_size = 0.04 | |
| pulse_amplitude = 0.025 | |
| pulse_rate = 0.15 + i * 0.03 | |
| pulse_factor = math.sin(frame * pulse_rate) | |
| radius = base_size + pulse_amplitude * pulse_factor | |
| dynamic_radii.append(max(radius, 0.01)) | |
| rr.log( | |
| "animated_square/points", | |
| rr.Points2D( | |
| rotated_points, | |
| colors=dynamic_colors, | |
| radii=dynamic_radii, | |
| labels=point_names, | |
| show_labels=True, | |
| ), | |
| ) | |
| for i, (point, name) in enumerate(zip(rotated_points, point_names)): | |
| x, y = point | |
| rr.log(f"position/{name}/x", rr.Scalars(x)) | |
| rr.log(f"position/{name}/y", rr.Scalars(y)) | |
| rr.log("overall/position/rotation_angle_radians", rr.Scalars(angle)) | |
| if __name__ == "__main__": | |
| main() |
| import math | |
| import numpy as np | |
| import rerun as rr | |
| def main(): | |
| rr.init("step3_3d_transforms", spawn=True) | |
| rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) | |
| rr.log("sun", rr.Points3D([0.0, 0.0, 0.0], radii=1.0, colors=[255, 200, 10])) | |
| rr.log("sun/planet", rr.Points3D([0.0, 0.0, 0.0], radii=0.4, colors=[40, 80, 200])) | |
| rr.log( | |
| "sun/planet/moon", | |
| rr.Points3D([0.0, 0.0, 0.0], radii=0.15, colors=[180, 180, 180]), | |
| ) | |
| rr.log( | |
| "sun/planet/moon2", | |
| rr.Points3D([0.0, 0.0, 0.0], radii=0.12, colors=[150, 120, 100]), | |
| ) | |
| # log the circle | |
| input("Press Enter to continue...") | |
| d_planet = 6.0 | |
| d_moon = 1.75 | |
| d_moon2_x = 2.5 | |
| d_moon2_y = 1.5 | |
| angles = np.arange(0.0, 1.01, 0.01) * np.pi * 2 | |
| circle = np.array( | |
| [np.sin(angles), np.cos(angles), angles * 0.0], dtype=np.float32 | |
| ).transpose() | |
| # Create oval path for second moon | |
| oval = np.array( | |
| [np.sin(angles) * d_moon2_x, np.cos(angles) * d_moon2_y, angles * 0.0], | |
| dtype=np.float32, | |
| ).transpose() | |
| rr.log( | |
| "sun/planet_path", rr.LineStrips3D(circle * d_planet, colors=[100, 100, 255]) | |
| ) | |
| rr.log( | |
| "sun/planet/moon_path", rr.LineStrips3D(circle * d_moon, colors=[200, 200, 200]) | |
| ) | |
| rr.log("sun/planet/moon2_path", rr.LineStrips3D(oval, colors=[150, 120, 100])) | |
| # log the circle | |
| input("Press Enter to continue...") | |
| total_frames = 6 * 360 | |
| for frame in range(total_frames): | |
| time = frame / 120.0 | |
| r_planet = time * 2.0 | |
| r_moon = time * 5.0 | |
| r_moon2 = time * 3.5 | |
| planet_x = math.sin(r_planet) * d_planet | |
| planet_y = math.cos(r_planet) * d_planet | |
| planet_z = 0.0 | |
| rr.log( | |
| "sun/planet", | |
| rr.Transform3D( | |
| translation=[planet_x, planet_y, planet_z], | |
| rotation=rr.RotationAxisAngle(axis=(1, 0, 0), degrees=20), | |
| ), | |
| ) | |
| moon_x = math.cos(r_moon) * d_moon | |
| moon_y = math.sin(r_moon) * d_moon | |
| moon_z = 0.0 | |
| rr.log( | |
| "sun/planet/moon", | |
| rr.Transform3D( | |
| translation=[moon_x, moon_y, moon_z], | |
| relation=rr.TransformRelation.ChildFromParent, | |
| ), | |
| ) | |
| moon2_x = math.sin(r_moon2) * d_moon2_x | |
| moon2_y = math.cos(r_moon2) * d_moon2_y | |
| moon2_z = 0.0 | |
| rr.log( | |
| "sun/planet/moon2", | |
| rr.Transform3D( | |
| translation=[moon2_x, moon2_y, moon2_z], | |
| relation=rr.TransformRelation.ChildFromParent, | |
| ), | |
| ) | |
| if frame == 0: | |
| input("Press Enter to continue...") | |
| if __name__ == "__main__": | |
| main() |
| from __future__ import annotations | |
| import argparse | |
| import os | |
| import tarfile | |
| from pathlib import Path | |
| import numpy as np | |
| import pandas as pd | |
| import requests | |
| import rerun as rr | |
| from rerun import blueprint as rrb | |
| from tqdm.auto import tqdm | |
| DATA_DIR = Path(__file__).parent / "dataset" | |
| DATASET_URL = "https://storage.googleapis.com/rerun-example-datasets/imu_signals/tum_vi_corridor4_512_16.tar" | |
| DATASET_NAME = "dataset-corridor4_512_16" | |
| XYZ_AXIS_NAMES = ["x", "y", "z"] | |
| XYZ_AXIS_COLORS = [[(231, 76, 60), (39, 174, 96), (52, 120, 219)]] | |
| def main() -> None: | |
| dataset_path = DATA_DIR / DATASET_NAME | |
| if not dataset_path.exists(): | |
| _download_dataset(DATA_DIR) | |
| parser = argparse.ArgumentParser( | |
| description="Visualizes the TUM Visual-Inertial dataset using the Rerun SDK." | |
| ) | |
| parser.add_argument( | |
| "--seconds", | |
| type=float, | |
| default=float("inf"), | |
| help="If specified, limits the number of seconds logged", | |
| ) | |
| rr.script_add_args(parser) | |
| args = parser.parse_args() | |
| blueprint = rrb.Horizontal( | |
| rrb.Vertical( | |
| rrb.TimeSeriesView( | |
| origin="gyroscope", | |
| name="Gyroscope", | |
| overrides={ | |
| "/gyroscope": rr.SeriesLines.from_fields( | |
| names=XYZ_AXIS_NAMES, colors=XYZ_AXIS_COLORS | |
| ), | |
| }, | |
| ), | |
| rrb.TimeSeriesView( | |
| origin="accelerometer", | |
| name="Accelerometer", | |
| overrides={ | |
| "/accelerometer": rr.SeriesLines.from_fields( | |
| names=XYZ_AXIS_NAMES, colors=XYZ_AXIS_COLORS | |
| ), | |
| }, | |
| ), | |
| ), | |
| rrb.Spatial3DView(origin="/", name="World position"), | |
| column_shares=[0.45, 0.55], | |
| ) | |
| rr.script_setup(args, "rerun_example_imu_signals", default_blueprint=blueprint) | |
| _log_imu_data(args.seconds) | |
| _log_image_data(args.seconds) | |
| _log_gt_imu(args.seconds) | |
| def _download_dataset(root: Path, dataset_url: str = DATASET_URL) -> None: | |
| os.makedirs(root, exist_ok=True) | |
| tar_path = os.path.join(root, f"{DATASET_NAME}.tar") | |
| response = requests.get(dataset_url, stream=True) | |
| total_size = int(response.headers.get("content-length", 0)) | |
| block_size = 1024 | |
| with tqdm( | |
| desc="Downloading dataset", total=total_size, unit="B", unit_scale=True | |
| ) as pb: | |
| with open(tar_path, "wb") as file: | |
| for data in response.iter_content(chunk_size=block_size): | |
| pb.update(len(data)) | |
| file.write(data) | |
| if total_size != 0 and pb.n != total_size: | |
| raise RuntimeError("Failed to download complete dataset!") | |
| print("Extracting dataset…") | |
| with tarfile.open(tar_path, "r:") as tar: | |
| tar.extractall(path=root) | |
| os.remove(tar_path) | |
| def _log_imu_data(max_time_sec: float) -> None: | |
| imu_data = pd.read_csv( | |
| DATA_DIR / DATASET_NAME / "dso/imu.txt", | |
| sep=" ", | |
| header=0, | |
| names=[ | |
| "timestamp", | |
| "gyro.x", | |
| "gyro.y", | |
| "gyro.z", | |
| "accel.x", | |
| "accel.y", | |
| "accel.z", | |
| ], | |
| comment="#", | |
| ) | |
| timestamps = imu_data["timestamp"].to_numpy() | |
| max_time_ns = imu_data["timestamp"][0] + max_time_sec * 1e9 | |
| selected = imu_data[imu_data["timestamp"] <= max_time_ns] | |
| timestamps = selected["timestamp"].astype("datetime64[ns]") | |
| times = rr.TimeColumn("timestamp", timestamp=timestamps) | |
| gyro = selected[["gyro.x", "gyro.y", "gyro.z"]].to_numpy() | |
| rr.send_columns( | |
| "/gyroscope", indexes=[times], columns=rr.Scalars.columns(scalars=gyro) | |
| ) | |
| accel = selected[["accel.x", "accel.y", "accel.z"]] | |
| rr.send_columns( | |
| "/accelerometer", indexes=[times], columns=rr.Scalars.columns(scalars=accel) | |
| ) | |
| def _log_image_data(max_time_sec: float) -> None: | |
| times = pd.read_csv( | |
| DATA_DIR / DATASET_NAME / "dso/cam0/times.txt", | |
| sep=" ", | |
| header=0, | |
| names=["filename", "timestamp", "exposure_time"], | |
| comment="#", | |
| dtype={"filename": str}, | |
| ) | |
| rr.set_time("timestamp", timestamp=times["timestamp"][0]) | |
| rr.log( | |
| "/world", | |
| rr.Transform3D( | |
| rotation_axis_angle=rr.RotationAxisAngle(axis=(1, 0, 0), angle=-np.pi / 2) | |
| ), | |
| static=True, | |
| ) | |
| rr.log( | |
| "/world/cam0", | |
| rr.Pinhole( | |
| focal_length=(0.373 * 512, 0.373 * 512), | |
| resolution=(512, 512), | |
| image_plane_distance=0.4, | |
| ), | |
| static=True, | |
| ) | |
| max_time_sec = times["timestamp"][0] + max_time_sec | |
| for _, (filename, timestamp, _) in times.iterrows(): | |
| if timestamp > max_time_sec: | |
| break | |
| image_path = DATA_DIR / DATASET_NAME / "dso/cam0/images" / f"{filename}.png" | |
| rr.set_time("timestamp", timestamp=timestamp) | |
| rr.log("/world/cam0/image", rr.EncodedImage(path=image_path)) | |
| def _log_gt_imu(max_time_sec: float) -> None: | |
| gt_imu = pd.read_csv( | |
| DATA_DIR / DATASET_NAME / "dso/gt_imu.csv", | |
| sep=",", | |
| header=0, | |
| names=["timestamp", "t.x", "t.y", "t.z", "q.w", "q.x", "q.y", "q.z"], | |
| comment="#", | |
| ) | |
| timestamps = gt_imu["timestamp"].to_numpy() | |
| max_time_ns = gt_imu["timestamp"][0] + max_time_sec * 1e9 | |
| selected = gt_imu[gt_imu["timestamp"] <= max_time_ns] | |
| timestamps = selected["timestamp"].astype("datetime64[ns]") | |
| times = rr.TimeColumn("timestamp", timestamp=timestamps) | |
| translations = selected[["t.x", "t.y", "t.z"]] | |
| quaternions = selected[ | |
| [ | |
| "q.x", | |
| "q.y", | |
| "q.z", | |
| "q.w", | |
| ] | |
| ] | |
| rr.send_columns( | |
| "/world/cam0", | |
| indexes=[times], | |
| columns=rr.Transform3D.columns( | |
| translation=translations, | |
| quaternion=quaternions, | |
| ), | |
| ) | |
| if __name__ == "__main__": | |
| main() |
| import math | |
| import time | |
| import rerun as rr | |
| def main(): | |
| rr.init("step4_multiple_timelines", recording_id="example_timeline") | |
| # expects to be run from the gentle-intro directory | |
| rr.save("data/example_timeline/step4.rrd") | |
| start_time = time.time() | |
| for frame in range(60): | |
| current_time = start_time + frame * 0.1 | |
| rr.set_time("imu_time", sequence=frame) | |
| rr.set_time("simulation_time", timestamp=current_time) | |
| imu_angle_x = frame * 0.08 | |
| imu_angle_y = frame * 0.05 | |
| imu_angle_z = frame * 0.12 | |
| orientation_points = [] | |
| for i in range(3): | |
| x = i * 0.5 - 0.5 | |
| y = math.sin(imu_angle_x) * 0.3 | |
| z = math.cos(imu_angle_y) * 0.3 | |
| new_x = x * math.cos(imu_angle_z) - y * math.sin(imu_angle_z) | |
| new_y = x * math.sin(imu_angle_z) + y * math.cos(imu_angle_z) | |
| orientation_points.append([new_x, new_y, z]) | |
| rr.log( | |
| "drone/imu_orientation", | |
| rr.Points3D(orientation_points, colors=[[255, 100, 100]], radii=0.08), | |
| ) | |
| if frame % 5 == 0: | |
| gps_frame = frame // 5 | |
| rr.set_time("gps_time", sequence=gps_frame) | |
| rr.set_time("simulation_time", timestamp=current_time) | |
| gps_angle = gps_frame * 0.3 | |
| gps_x = math.cos(gps_angle) * 2 | |
| gps_y = math.sin(gps_angle) * 2 | |
| gps_z = 0.5 + math.sin(gps_frame * 0.2) * 0.3 | |
| rr.log( | |
| "drone/gps_position", | |
| rr.Points3D( | |
| [[gps_x, gps_y, gps_z]], colors=[[100, 255, 100]], radii=0.12 | |
| ), | |
| ) | |
| if frame % 10 == 0: | |
| obstacle_frame = frame // 10 | |
| rr.set_time("obstacle_time", sequence=obstacle_frame) | |
| rr.set_time("simulation_time", timestamp=current_time) | |
| obstacle_points = [] | |
| obstacle_colors = [] | |
| for i in range(3): | |
| obs_angle = obstacle_frame * 0.4 + i * 2.1 | |
| obs_distance = 3 + i * 0.5 | |
| obs_x = math.cos(obs_angle) * obs_distance | |
| obs_y = math.sin(obs_angle) * obs_distance | |
| obs_z = 0.2 + i * 0.3 | |
| obstacle_points.append([obs_x, obs_y, obs_z]) | |
| obstacle_colors.append([255, 150, 50]) | |
| rr.log( | |
| "environment/detected_obstacles", | |
| rr.Points3D(obstacle_points, colors=obstacle_colors, radii=0.15), | |
| ) | |
| rr.set_time("frame", sequence=frame) | |
| if __name__ == "__main__": | |
| main() |
rerun data/droid-example.rrdrerun server -d data/droidrerun rerun+http://localhost:51234rerun data/droid/droid-example.rrd data/droid/droid-blueprint.rbl