Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

Commit

Permalink
feat: add timing_mode
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanwagnerdev committed Jan 21, 2025
1 parent 891623e commit 803ee99
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 9 deletions.
4 changes: 3 additions & 1 deletion nova_rerun_bridge/examples/02_plan_and_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ async def test():

joint_trajectory = await motion_group.plan(actions, tcp)

await nova_bridge.log_trajectory(joint_trajectory, tcp, motion_group, time_offset=0)
await nova_bridge.log_trajectory(joint_trajectory, tcp, motion_group)
await nova_bridge.log_trajectory(joint_trajectory, tcp, motion_group)

await motion_group.execute(joint_trajectory, tcp, actions=actions)

await nova.close()
Expand Down
3 changes: 2 additions & 1 deletion nova_rerun_bridge/examples/04_move_multiple_robots.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from nova.actions import jnt, ptp

from nova_rerun_bridge import NovaRerunBridge
from nova_rerun_bridge.trajectory import TimingMode

"""
Example: Move multiple robots simultaneously.
Expand All @@ -24,7 +25,7 @@ async def move_robot(controller: Controller, nova_bridge: NovaRerunBridge):
actions = [jnt(home_joints), ptp(target_pose), jnt(home_joints)]

trajectory = await motion_group.plan(actions, tcp)
await nova_bridge.log_trajectory(trajectory, tcp, motion_group, time_offset=0)
await nova_bridge.log_trajectory(trajectory, tcp, motion_group, timing_mode=TimingMode.SYNC)

await motion_group.plan_and_execute(actions, tcp)

Expand Down
16 changes: 12 additions & 4 deletions nova_rerun_bridge/nova_reun_bridge.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime
from typing import Dict

import rerun as rr
Expand All @@ -9,7 +10,7 @@
from nova_rerun_bridge.blueprint import send_blueprint
from nova_rerun_bridge.collision_scene import log_collision_scenes
from nova_rerun_bridge.consts import RECORDING_INTERVAL
from nova_rerun_bridge.trajectory import log_motion
from nova_rerun_bridge.trajectory import TimingMode, log_motion


class NovaRerunBridge:
Expand Down Expand Up @@ -39,7 +40,8 @@ async def main():
def __init__(self, nova: Nova, spawn: bool = True) -> None:
self.nova = nova
if spawn:
rr.init(application_id="nova", recording_id="nova_live", spawn=True)
recording_id = f"nova_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
rr.init(application_id="nova", recording_id=recording_id, spawn=True)
logger.add(sink=rr.LoggingHandler("logs/handler"))

async def setup_blueprint(self) -> None:
Expand Down Expand Up @@ -98,7 +100,9 @@ async def fetch_and_log_collision_scene(
def log_collision_scene(self, collision_scenes: Dict[str, models.CollisionScene]) -> None:
log_collision_scenes(collision_scenes=collision_scenes)

async def log_motion(self, motion_id: str, time_offset: float = 0) -> None:
async def log_motion(
self, motion_id: str, timing_mode=TimingMode.CONTINUE, time_offset: float = 0
) -> None:
# Fetch motion details from api
motion = await self.nova._api_client.motion_api.get_planned_motion(
self.nova.cell()._cell_id, motion_id
Expand Down Expand Up @@ -133,17 +137,21 @@ async def log_motion(self, motion_id: str, time_offset: float = 0) -> None:
trajectory=trajectory.trajectory,
collision_scenes=collision_scenes,
time_offset=time_offset,
timing_mode=timing_mode,
)

async def log_trajectory(
self,
joint_trajectory: models.JointTrajectory,
tcp: str,
motion_group: MotionGroup,
timing_mode=TimingMode.CONTINUE,
time_offset: float = 0,
) -> None:
load_plan_response = await motion_group._load_planned_motion(joint_trajectory, tcp)
await self.log_motion(load_plan_response.motion, time_offset=time_offset)
await self.log_motion(
load_plan_response.motion, timing_mode=timing_mode, time_offset=time_offset
)

async def __aenter__(self) -> "NovaRerunBridge":
"""Context manager entry point.
Expand Down
41 changes: 38 additions & 3 deletions nova_rerun_bridge/trajectory.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from enum import Enum, auto
from typing import Dict, List

import numpy as np
Expand All @@ -11,6 +12,18 @@
from nova_rerun_bridge.robot_visualizer import RobotVisualizer


class TimingMode(Enum):
"""Controls how trajectories are timed relative to each other."""

RESET = auto() # Start at time_offset
CONTINUE = auto() # Start after last trajectory
SYNC = auto() # Use exact time_offset provided


# Global variable to track last logged time
_last_logged_time = 0.0


def log_motion(
motion_id: str,
model_from_controller: str,
Expand All @@ -19,10 +32,28 @@ def log_motion(
trajectory: List[models.TrajectorySample],
collision_scenes: Dict[str, models.CollisionScene],
time_offset: float = 0,
timing_mode: TimingMode = TimingMode.RESET,
):
"""
Fetch and process a single motion if not processed already.
Fetch and process a single motion with timing control.
Args:
...existing args...
timing_mode: Controls how trajectory timing is handled
RESET: Start at time_offset (default)
CONTINUE: Start after last trajectory
SYNC: Use exact time_offset provided
"""
global _last_logged_time

# Calculate start time based on timing mode
if timing_mode == TimingMode.CONTINUE:
effective_offset = _last_logged_time
elif timing_mode == TimingMode.SYNC:
effective_offset = time_offset
else: # TimingMode.RESET
effective_offset = time_offset
_last_logged_time = 0.0

# Initialize DHRobot and Visualizer
robot = DHRobot(optimizer_config.dh_parameters, optimizer_config.mounting)
Expand All @@ -40,7 +71,7 @@ def log_motion(
collision_tcp=collision_tcp,
)

rr.set_time_seconds(TIME_INTERVAL_NAME, time_offset)
rr.set_time_seconds(TIME_INTERVAL_NAME, effective_offset)

# Process trajectory points
log_trajectory(
Expand All @@ -50,9 +81,13 @@ def log_motion(
visualizer=visualizer,
trajectory=trajectory,
optimizer_config=optimizer_config,
timer_offset=time_offset,
timer_offset=effective_offset,
)

# Update last logged time
if trajectory:
_last_logged_time = effective_offset + trajectory[-1].time


def log_trajectory_path(
motion_id: str, trajectory: List[models.TrajectorySample], motion_group: str
Expand Down

0 comments on commit 803ee99

Please sign in to comment.