lsnu's picture
Add files using upload-large-folder tool
912c7e2 verified
import torch
import trimesh
import numpy as np
import pypose as pp
import rerun as rr
def rr_init(name: str, addr: str = None):
rr.init(name)
if addr is None:
addr = "127.0.0.1"
port = ":9876"
rr.connect(addr + port)
rr.log("vis", rr.Clear(recursive=True))
return
def rr_add_axis(name: str, pose: np.ndarray, size: float = 0.004, timeless: bool = False):
mesh = trimesh.creation.axis(origin_size=size, transform=pose)
# Handle colors
if mesh.visual.kind in ["vertex", "face"]:
vertex_colors = mesh.visual.vertex_colors
elif mesh.visual.kind == "texture":
vertex_colors = mesh.visual.to_color().vertex_colors
else:
vertex_colors = None
# Log mesh
rr_mesh = rr.Mesh3D(
vertex_positions=mesh.vertices,
vertex_colors=vertex_colors,
vertex_normals=mesh.vertex_normals,
indices=mesh.faces,
)
rr.log(name, rr_mesh, timeless=timeless)
return
# Print random twists
for _ in range(50):
euler = torch.FloatTensor(1, 3).uniform_(-torch.pi / 2, torch.pi / 2)
twist = pp.Log(pp.euler2SO3(euler))
# print(euler)
# print(twist)
# Exp-map: se3 -> SE3
# Identity (SE3) + twist (se3) = pose (SE3)
twist = pp.randn_se3(1)
pose = pp.Exp(twist)
del twist, pose
# Log-map: SE3 -> se3
# pose (SE3) - Identity (SE3) = twist (se3)
pose = pp.randn_SE3(1)
twist = pp.Log(pose)
del pose, twist
# Right-plus operator: SE3 + se3 = SE3
# This is in local frame, i.e. in the tangent space of the start pose
start_pose = pp.randn_SE3(1)
twist = pp.randn_se3(1)
end_pose = start_pose @ pp.Exp(twist)
del start_pose, twist, end_pose
# Right-minus operator: SE3 - SE3 = se3
# This is in local frame, i.e. in the tangent space of the start pose
start_pose = pp.randn_SE3(1)
end_pose = pp.randn_SE3(1)
twist = pp.Log(pp.Inv(start_pose) @ end_pose)
del start_pose, end_pose, twist
# Left-plus operator: SE3 + se3 = SE3
# This is in global frame, i.e. in the tangent space of the identity pose
start_pose = pp.randn_SE3(1)
twist = pp.randn_se3(1)
end_pose_a = start_pose + twist
end_pose_b = pp.Retr(start_pose, twist)
end_pose_c = pp.Exp(twist) @ start_pose
assert torch.allclose(end_pose_a, end_pose_b)
assert torch.allclose(end_pose_a, end_pose_c)
del start_pose, twist, end_pose_a, end_pose_b, end_pose_c
# Left-minus operator: SE3 - SE3 = se3
# This is in global frame, i.e. in the tangent space of the identity pose
start_pose = pp.randn_SE3(1)
end_pose = pp.randn_SE3(1)
twist = pp.Log(end_pose @ pp.Inv(start_pose))
del start_pose, end_pose, twist
# Simple simulation
rr_init("sandbox")
T0_th = torch.eye(4).unsqueeze(0)
T0_th[:, :3, 3] = torch.tensor([0.5, 0, 0])
# Rotate -90 degrees
T0_th[:, :3, 0] = torch.tensor([0, -1, 0])
T0_th[:, :3, 1] = torch.tensor([1, 0, 0])
T1_th = torch.eye(4).unsqueeze(0)
T1_th[:, :3, 3] = torch.tensor([0, 0.5, 0])
T1_th[:, :3, 0], T1_th[:, :3, 1] = T1_th[:, :3, 1], -T1_th[:, :3, 0] # Rotate 90 degrees
rr_add_axis("vis/origin", np.eye(4), size=0.01, timeless=True)
rr_add_axis("vis/T0", T0_th[0].numpy(), timeless=True)
rr_add_axis("vis/T1", T1_th[0].numpy(), timeless=True)
T0_pp = pp.mat2SE3(T0_th)
T1_pp = pp.mat2SE3(T1_th)
vel_right = pp.Log(pp.Inv(T0_pp) @ T1_pp)
vel_left = pp.Log(T1_pp @ pp.Inv(T0_pp))
k_steps = 50
dt = 1 / k_steps
pose_pp_right = T0_pp
pose_pp_left = T0_pp
for k_step in range(k_steps):
pose_pp_right: pp.LieTensor = pose_pp_right @ pp.Exp(vel_right * dt)
pose_pp_left: pp.LieTensor = pp.Exp(vel_left * dt) @ pose_pp_left
rr.set_time_sequence("k_step", k_step)
rr_add_axis("vis/pose_se3_right", pose_pp_right.matrix().squeeze().numpy())
rr_add_axis("vis/pose_se3_left", pose_pp_left.matrix().squeeze().numpy())
# SO3 x R3
t0 = T0_th[0, :3, 3]
t1 = T1_th[0, :3, 3]
R0_pp = pp.mat2SO3(T0_th[:, :3, :3])
R1_pp = pp.euler2SO3(torch.tensor([0, 0, np.pi / 2 - 0.001]))
xyz_vel = t1 - t0
R_vel_right = pp.Log(pp.Inv(R0_pp) @ R1_pp)
R_vel_left = pp.Log(R1_pp @ pp.Inv(R0_pp))
xyz = t0
R_pp_right = R0_pp
R_pp_left = R0_pp
for k_step in range(k_steps):
xyz = xyz + xyz_vel * dt
R_pp_right = R_pp_right @ pp.Exp(R_vel_right * dt)
R_pp_left = pp.Exp(R_vel_left * dt) @ R_pp_left
rr.set_time_sequence("k_step", k_step)
pose_right = torch.eye(4)
pose_right[:3, :3] = R_pp_right.matrix().squeeze()
pose_right[:3, 3] = xyz
pose_left = torch.eye(4)
pose_left[:3, :3] = R_pp_left.matrix().squeeze()
pose_left[:3, 3] = xyz
rr_add_axis("vis/pose_so3", pose_right.numpy())
rr_add_axis("vis/pose_so3_left", pose_left.numpy())
print(f"{R_vel_right=}")
print(f"{R_vel_left=}")
print("done")