Interbotix / interbotix_ros_toolboxes

Support-level ROS Packages for Interbotix Robots
BSD 3-Clause "New" or "Revised" License
29 stars 68 forks source link

[Question]: Can the python API be accessed from a ROS2 node? #40

Closed ManuelKochETH closed 2 years ago

ManuelKochETH commented 2 years ago

Question

I'd like to use the Interbotix Python Arm Module from a custom node. The goal is to use the set_ee_pose_components function when a certain ROS message is received with x,y and z depending on the message content. But including the InterbotixManipulatorXS class in a custom node leads to the node crashing with RuntimeError.

Here the code for a minimal subscriber as in the ROS2 documentation:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from interbotix_xs_modules.xs_robot.arm import InterbotixManipulatorXS

class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__('minimal_subscriber')
        self.subscription = self.create_subscription(
            String,
            'Test_topic',
            self.listener_callback,
            10)
        self.subscription  # prevent unused variable warning

        self.bot = InterbotixManipulatorXS(
            robot_model='wx250s',
            group_name='arm',
            gripper_name='gripper'
        )
        self.bot.arm.go_to_sleep_pose(2.0)

    def listener_callback(self, msg):
        self.get_logger().info('I heard: "%s"' % msg.data)

def main(args=None):
    rclpy.init(args=args)
    minimal_subscriber = MinimalSubscriber()
    rclpy.spin(minimal_subscriber)

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_subscriber.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

And the error obtained when running the node:

mankoch@mk-ubuntu:~$ ros2 run custom_ctrl minimal_subscriber 
Traceback (most recent call last):
  File "/home/mankoch/project_ws/install/custom_ctrl/lib/custom_ctrl/minimal_subscriber", line 11, in <module>
    load_entry_point('custom-ctrl==0.0.0', 'console_scripts', 'minimal_subscriber')()
  File "/home/mankoch/project_ws/install/custom_ctrl/lib/python3.8/site-packages/custom_ctrl/minimal_subscriber.py", line 38, in main
    minimal_subscriber = MinimalSubscriber()
  File "/home/mankoch/project_ws/install/custom_ctrl/lib/python3.8/site-packages/custom_ctrl/minimal_subscriber.py", line 21, in __init__
    self.bot = InterbotixManipulatorXS(
  File "/home/mankoch/interbotix_ws/install/interbotix_xs_modules/lib/python3.8/site-packages/interbotix_xs_modules/xs_robot/arm.py", line 123, in __init__
    self.core = InterbotixRobotXSCore(
  File "/home/mankoch/interbotix_ws/install/interbotix_xs_modules/lib/python3.8/site-packages/interbotix_xs_modules/xs_robot/core.py", line 91, in __init__
    rclpy.init(args=args)
  File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/__init__.py", line 76, in init
    return context.init(args, domain_id=domain_id)
  File "/opt/ros/galactic/lib/python3.8/site-packages/rclpy/context.py", line 70, in init
    raise RuntimeError
RuntimeError

Is there a way of using the API this way?

Robot Model

wx250s

Operating System

Ubuntu 20.04

ROS Version

ROS2 Galactic

Anything Else

No response

lukeschmitt-tr commented 2 years ago

I assume this is because, in creating the InterbotixManipulatorXS object, you're creating another node in the same process or context. To get around this, take a look at the xsarm_robot script for an example of how to do this. Basically, you would sub-class the InterbotixManipulatorXS class and use its core (the actual node) to create subs/pubs, use parameters, get the logger, etc.

ManuelKochETH commented 2 years ago

Ah this makes sense. Thanks for the quick answer.