Skip to content

Commit

Permalink
feat: add sync and continue modes
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanwagnerdev committed Jan 21, 2025
1 parent 803ee99 commit 8e7b415
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 9 deletions.
122 changes: 122 additions & 0 deletions nova_rerun_bridge/examples/timing_mode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import asyncio

from nova import Controller, MotionSettings, Nova
from nova.actions import jnt, ptp
from nova.core.nova import Nova
from nova.types import Pose

from nova_rerun_bridge import NovaRerunBridge
from nova_rerun_bridge.trajectory import TimingMode

"""
Example: Move multiple robots simultaneously.
Prerequisites:
- A cell with two robots: one named "ur" and another named "kuka".
"""


async def move_robot(controller: Controller, nova_bridge: NovaRerunBridge):
async with controller[0] as motion_group:
home_joints = await motion_group.joints()
tcp_names = await motion_group.tcp_names()
tcp = tcp_names[0]

current_pose = await motion_group.tcp_pose(tcp)
target_pose = current_pose @ (100, 0, 0, 0, 0, 0)
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, timing_mode=TimingMode.SYNC)

await motion_group.plan_and_execute(actions, tcp)


async def main():
nova = Nova()
nova_bridge = NovaRerunBridge(nova)
await nova_bridge.setup_blueprint()

cell = nova.cell()
controllers = await cell.controllers()
controller = controllers[0]

# Connect to the controller and activate motion groups
async with controller[0] as motion_group:
home_joints = await motion_group.joints()
tcp_names = await motion_group.tcp_names()
tcp = tcp_names[0]

# Get current TCP pose and offset it slightly along the x-axis
current_pose = await motion_group.tcp_pose(tcp)
target_pose = current_pose @ Pose((1, 0, 0, 0, 0, 0))

actions = [
jnt(home_joints),
ptp(target_pose),
jnt(home_joints),
ptp(target_pose @ [100, 0, 0, 0, 0, 0]),
jnt(home_joints),
ptp(target_pose @ (100, 100, 0, 0, 0, 0)),
jnt(home_joints),
ptp(target_pose @ Pose((0, 100, 0, 0, 0, 0))),
jnt(home_joints),
]

# you can update the settings of the action
for action in actions:
action.settings = MotionSettings(tcp_velocity_limit=200)

joint_trajectory = await motion_group.plan(actions, tcp)

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)

cell = nova.cell()
ur = await cell.controller("ur")
kuka = await cell.controller("kuka")
await asyncio.gather(
move_robot(ur, nova_bridge=nova_bridge), move_robot(kuka, nova_bridge=nova_bridge)
)

# Connect to the controller and activate motion groups
async with controller[0] as motion_group:
home_joints = await motion_group.joints()
tcp_names = await motion_group.tcp_names()
tcp = tcp_names[0]

# Get current TCP pose and offset it slightly along the x-axis
current_pose = await motion_group.tcp_pose(tcp)
target_pose = current_pose @ Pose((1, 0, 0, 0, 0, 0))

actions = [
jnt(home_joints),
ptp(target_pose),
jnt(home_joints),
ptp(target_pose @ [100, 0, 0, 0, 0, 0]),
jnt(home_joints),
ptp(target_pose @ (100, 100, 0, 0, 0, 0)),
jnt(home_joints),
ptp(target_pose @ Pose((0, 100, 0, 0, 0, 0))),
jnt(home_joints),
]

# you can update the settings of the action
for action in actions:
action.settings = MotionSettings(tcp_velocity_limit=200)

joint_trajectory = await motion_group.plan(actions, tcp)

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()
await nova_bridge.cleanup()


if __name__ == "__main__":
asyncio.run(main())
27 changes: 18 additions & 9 deletions nova_rerun_bridge/trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ class TimingMode(Enum):

RESET = auto() # Start at time_offset
CONTINUE = auto() # Start after last trajectory
SYNC = auto() # Use exact time_offset provided
SYNC = auto() # Use exact time_offset, don't update last time
OVERRIDE = auto() # Use exact time_offset and reset last time


# Global variable to track last logged time
_last_logged_time = 0.0
# Track both last end time and last offset separately
_last_end_time = 0.0
_last_offset = 0.0


def log_motion(
Expand All @@ -32,7 +34,7 @@ def log_motion(
trajectory: List[models.TrajectorySample],
collision_scenes: Dict[str, models.CollisionScene],
time_offset: float = 0,
timing_mode: TimingMode = TimingMode.RESET,
timing_mode: TimingMode = TimingMode.CONTINUE,
):
"""
Fetch and process a single motion with timing control.
Expand All @@ -44,16 +46,19 @@ def log_motion(
CONTINUE: Start after last trajectory
SYNC: Use exact time_offset provided
"""
global _last_logged_time
global _last_end_time, _last_offset

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

# Initialize DHRobot and Visualizer
robot = DHRobot(optimizer_config.dh_parameters, optimizer_config.mounting)
Expand Down Expand Up @@ -84,9 +89,13 @@ def log_motion(
timer_offset=effective_offset,
)

# Update last logged time
# Update last times based on timing mode
if trajectory:
_last_logged_time = effective_offset + trajectory[-1].time
if timing_mode == TimingMode.SYNC:
_last_offset = trajectory[-1].time
else:
_last_offset = 0
_last_end_time = effective_offset + trajectory[-1].time


def log_trajectory_path(
Expand Down

0 comments on commit 8e7b415

Please sign in to comment.