You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.7 KiB
138 lines
4.7 KiB
from contextlib import contextmanager
|
|
import pickle
|
|
import time
|
|
|
|
import click
|
|
import numpy as np
|
|
from scipy.spatial.transform import Rotation as R
|
|
import zmq
|
|
|
|
from decoupled_wbc.control.teleop.device.SDKClient_Linux import ManusServer
|
|
|
|
manus_idx = {
|
|
"left": ["3822396207", "3998055887", "432908014"],
|
|
"right": ["3762867141", "831307785", "3585023564"],
|
|
}
|
|
|
|
|
|
class Manus:
|
|
def __init__(self, port=5556):
|
|
# Storage for the latest finger data
|
|
self.latest_finger_data = {
|
|
"left_fingers": {"angle": np.zeros([40]), "position": np.zeros([25, 4, 4])},
|
|
"right_fingers": {"angle": np.zeros([40]), "position": np.zeros([25, 4, 4])},
|
|
}
|
|
self.manus_server = None
|
|
self.port = port
|
|
|
|
def process_finger_pose(self, raw_position, raw_orientation, dir):
|
|
raw_position = np.asarray(raw_position).reshape([-1, 3])
|
|
raw_orientation = np.asarray(raw_orientation).reshape([-1, 4])
|
|
|
|
def reorder(data):
|
|
return np.concatenate(
|
|
[
|
|
data[0:1], # root
|
|
data[21:25], # thumb
|
|
data[1:6], # index
|
|
data[6:11], # middle
|
|
data[16:21], # ring
|
|
data[11:16], # pinky
|
|
]
|
|
)
|
|
|
|
raw_position = reorder(raw_position)
|
|
raw_orientation = reorder(raw_orientation)
|
|
|
|
transformation_matrix = np.zeros([25, 4, 4])
|
|
rot_matrix = R.from_quat(raw_orientation[0][[1, 2, 3, 0]]).as_matrix()
|
|
transformation_matrix[:, :3, :3] = rot_matrix
|
|
transformation_matrix[:, :3, 3] = raw_position
|
|
transformation_matrix[:, 3, 3] = 1.0
|
|
|
|
T_root = transformation_matrix[0]
|
|
T_root_inv = np.linalg.inv(T_root)
|
|
transformation_matrix = np.matmul(T_root_inv[None], transformation_matrix)
|
|
|
|
T_manus2avp = np.identity(4)
|
|
if dir == "right":
|
|
T_manus2avp[:3, :3] = R.from_euler("zx", [180, -90], degrees=True).as_matrix()
|
|
else:
|
|
T_manus2avp[:3, :3] = R.from_euler("x", [90], degrees=True).as_matrix()
|
|
transformation_matrix = np.matmul(T_manus2avp[None], transformation_matrix)
|
|
|
|
return transformation_matrix
|
|
|
|
def process_finger_angle(self, raw_finger_data, dir):
|
|
if dir == "right":
|
|
non_zero_data = [value for value in raw_finger_data if value != 0.0]
|
|
trailing_zeros_count = len(raw_finger_data) - len(non_zero_data)
|
|
raw_finger_data = non_zero_data + [0.0] * trailing_zeros_count
|
|
|
|
return raw_finger_data
|
|
|
|
def request_finger_data(self):
|
|
output = ManusServer.get_latest_state()
|
|
for dir, val in manus_idx.items():
|
|
for id in val:
|
|
angle_name = f"{id}_angle"
|
|
if angle_name in output and len(output[angle_name]) > 0:
|
|
self.latest_finger_data[f"{dir}_fingers"]["angle"] = self.process_finger_angle(
|
|
np.asarray(output[angle_name]), dir
|
|
)
|
|
|
|
position_name = f"{id}_position"
|
|
orientation_name = f"{id}_orientation"
|
|
if (
|
|
position_name in output
|
|
and orientation_name in output
|
|
and len(output[position_name]) > 0
|
|
and len(output[orientation_name]) > 0
|
|
):
|
|
self.latest_finger_data[f"{dir}_fingers"]["position"] = (
|
|
self.process_finger_pose(
|
|
output[position_name], output[orientation_name], dir
|
|
)
|
|
)
|
|
|
|
return self.latest_finger_data
|
|
|
|
@contextmanager
|
|
def activate(self):
|
|
try:
|
|
ManusServer.init()
|
|
self.context = zmq.Context()
|
|
self.socket = self.context.socket(zmq.REP)
|
|
self.socket.bind(f"tcp://*:{self.port}")
|
|
yield self
|
|
finally:
|
|
ManusServer.shutdown()
|
|
|
|
def run(self):
|
|
while True:
|
|
# Wait for a request from the client
|
|
_ = self.socket.recv()
|
|
# Process finger data
|
|
data = self.request_finger_data()
|
|
data["timestamp"] = time.time()
|
|
|
|
# Serialize the data to send back
|
|
serialized_data = pickle.dumps(data)
|
|
|
|
# Send the serialized data back to the client
|
|
self.socket.send(serialized_data)
|
|
|
|
|
|
@click.command()
|
|
@click.option("--port", type=int, default=5556)
|
|
def main(port):
|
|
print("... starting manus server ... at port", port, flush=True)
|
|
manus = Manus(port=port)
|
|
print("... manus server activating ...")
|
|
with manus.activate():
|
|
print("==> Manus server is running at port", port, flush=True)
|
|
manus.run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|