import rclpy
from rclpy.node import Node
from sensor_msgs.msg import JointState
from rclpy.executors import SingleThreadedExecutor

class JointStateReader(Node):
    def __init__(self):
        super().__init__('JointStateReader')
        self.sub = self.create_subscription(JointState, 'joint_states', self.sub_callback, 1)
        self.joint_names = []
        self.got_msg = False
    
    def sub_callback(self, msg):
        """Callback to read joint names from the first received message."""
        if not self.joint_names:
            self.got_msg=True
            self.joint_names = list(msg.name)

def joint_names():
    """Fetch joint names using an existing ROS2 context and ensure proper cleanup."""
    rclpy.init()
    node = JointStateReader()
    executor = SingleThreadedExecutor()
    executor.add_node(node)
    while not node.got_msg:
        executor.spin_once(timeout_sec=0)
    joint_list = node.joint_names  # Store names before shutting down

    node.destroy_node()  # Properly destroy the node
    rclpy.shutdown()  # Shutdown ROS2 context to free memory

    return joint_list  # Return the joint names safely

def main():
    """Main function to fetch and print joint names."""
    joints = joint_names()
    
    for i, joint_name in enumerate(joints, start=1):
        print(f"Joint No. {i}: {joint_name}")

if __name__ == '__main__':
    main()
