Skip to content

Commit 4750d36

Browse files
Merge pull request #21 from WATonomous/ros2_bridge
Ros2 bridge
2 parents 50b9a14 + 4725658 commit 4750d36

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import argparse
2+
from isaaclab.app import AppLauncher
3+
4+
parser = argparse.ArgumentParser(description="Humanoid Hand Testing")
5+
AppLauncher.add_app_launcher_args(parser)
6+
args_cli = parser.parse_args()
7+
8+
app_launcher = AppLauncher(args_cli)
9+
simulation_app = app_launcher.app
10+
11+
import torch
12+
import rclpy
13+
14+
import isaaclab.sim as sim_utils
15+
from isaaclab.assets import AssetBaseCfg
16+
from isaaclab.managers import SceneEntityCfg
17+
from isaaclab.scene import InteractiveScene, InteractiveSceneCfg
18+
from isaaclab.utils import configclass
19+
20+
from HumanoidRL.HumanoidRLPackage.HumanoidRLSetup.modelCfg.humanoid import HAND_CFG
21+
from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR
22+
from test_publisher import TestFloatPublisher
23+
from test_subscriber import HandPoseSubscriber
24+
25+
@configclass
26+
class HandSceneCfg(InteractiveSceneCfg):
27+
ground = AssetBaseCfg(
28+
prim_path="/World/defaultGroundPlane",
29+
spawn=sim_utils.GroundPlaneCfg(),
30+
init_state=AssetBaseCfg.InitialStateCfg(pos=(0.0, 0.0, -1.05)),
31+
)
32+
33+
dome_light = AssetBaseCfg(
34+
prim_path="/World/Light",
35+
spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
36+
)
37+
38+
robot = HAND_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
39+
40+
def run_simulator(sim: sim_utils.SimulationContext, scene: InteractiveScene, node, test_node):
41+
robot = scene["robot"]
42+
robot_entity_cfg = SceneEntityCfg("robot", joint_names=[".*"], body_names=[".*"])
43+
robot_entity_cfg.resolve(scene)
44+
45+
# Debug joint configuration
46+
print(f"Number of joints: {len(robot_entity_cfg.joint_ids)}")
47+
print(f"Joint IDs: {robot_entity_cfg.joint_ids}")
48+
print(f"Default joint positions shape: {robot.data.default_joint_pos.shape}")
49+
50+
sim_dt = sim.get_physics_dt()
51+
joint_position = robot.data.default_joint_pos.clone()
52+
joint_vel = robot.data.default_joint_vel.clone()
53+
robot.write_joint_state_to_sim(joint_position, joint_vel)
54+
55+
while simulation_app.is_running():
56+
if rclpy.ok():
57+
rclpy.spin_once(node, timeout_sec=0.01)
58+
rclpy.spin_once(test_node, timeout_sec=0.01)
59+
60+
joint_values = node.get_latest_joint_positions()
61+
if joint_values and len(joint_values) == 15:
62+
print(f"[INFO]: Received joint values: {joint_values}")
63+
# Ensure joint_values is a list of floats
64+
joint_tensor = torch.tensor(joint_values, device=sim.device)
65+
joint_pos_des = joint_tensor.unsqueeze(0)[:, :len(robot_entity_cfg.joint_ids)].clone()
66+
robot.reset()
67+
robot.set_joint_position_target(joint_pos_des, joint_ids=robot_entity_cfg.joint_ids)
68+
else:
69+
print("[INFO]: No valid joint values received, using default positions.")
70+
joint_position_list = [[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]
71+
joint_position = torch.tensor(joint_position_list[0], device=sim.device)
72+
robot.reset()
73+
joint_pos_des = joint_position.unsqueeze(0)[:, robot_entity_cfg.joint_ids].clone()
74+
robot.set_joint_position_target(joint_pos_des, joint_ids=robot_entity_cfg.joint_ids)
75+
76+
77+
scene.write_data_to_sim()
78+
sim.step()
79+
scene.update(sim_dt)
80+
81+
def main():
82+
# Initialize ROS2
83+
rclpy.init()
84+
node = HandPoseSubscriber()
85+
test_node = TestFloatPublisher()
86+
87+
# Initialize simulation
88+
sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device)
89+
sim = sim_utils.SimulationContext(sim_cfg)
90+
sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
91+
92+
scene_cfg = HandSceneCfg(num_envs=1, env_spacing=2.0)
93+
scene = InteractiveScene(scene_cfg)
94+
sim.reset()
95+
96+
print("[INFO]: Setup complete...")
97+
run_simulator(sim, scene, node, test_node)
98+
99+
# Cleanup
100+
node.destroy_node()
101+
test_node.destroy_node()
102+
rclpy.shutdown()
103+
simulation_app.close()
104+
105+
if __name__ == "__main__":
106+
main()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import rclpy
2+
from rclpy.node import Node
3+
from std_msgs.msg import Float32MultiArray
4+
5+
class TestFloatPublisher(Node):
6+
def __init__(self):
7+
super().__init__('test_float_publisher')
8+
self.publisher_ = self.create_publisher(Float32MultiArray, '/hand_joint_positions', 10)
9+
self.timer = self.create_timer(0.1, self.timer_callback)
10+
self.get_logger().info('Test Float Publisher initialized')
11+
12+
def timer_callback(self):
13+
msg = Float32MultiArray()
14+
# Publish a list of 15 floats (e.g., all 1.0 for testing)
15+
msg.data = [2.0] * 15
16+
self.publisher_.publish(msg)
17+
self.get_logger().info(f'Published joint positions: {msg.data}')
18+
19+
def main(args=None):
20+
rclpy.init(args=args)
21+
node = TestFloatPublisher()
22+
try:
23+
rclpy.spin(node)
24+
except KeyboardInterrupt:
25+
pass
26+
node.destroy_node()
27+
rclpy.shutdown()
28+
29+
if __name__ == '__main__':
30+
main()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import rclpy
2+
from rclpy.node import Node
3+
from std_msgs.msg import Float32MultiArray
4+
5+
class HandPoseSubscriber(Node):
6+
def __init__(self):
7+
super().__init__('hand_pose_subscriber')
8+
self.subscription = self.create_subscription(
9+
Float32MultiArray,
10+
'/hand_joint_positions',
11+
self.listener_callback,
12+
10)
13+
self.joint_positions = None
14+
self.get_logger().info('Hand Pose Subscriber initialized')
15+
16+
def listener_callback(self, msg):
17+
if len(msg.data) == 15:
18+
self.joint_positions = list(msg.data)
19+
self.get_logger().info(f'Received joint positions: {self.joint_positions}')
20+
else:
21+
self.get_logger().warn(f'Received invalid joint positions: expected 15 floats, got {len(msg.data)}')
22+
23+
def get_latest_joint_positions(self):
24+
return self.joint_positions
25+
26+
def main(args=None):
27+
rclpy.init(args=args)
28+
node = HandPoseSubscriber()
29+
try:
30+
rclpy.spin(node)
31+
except KeyboardInterrupt:
32+
pass
33+
node.destroy_node()
34+
rclpy.shutdown()
35+
36+
if __name__ == '__main__':
37+
main()

0 commit comments

Comments
 (0)