Using ROS from Python code [2425] - LCAS/RBT1001 GitHub Wiki
On VSCode, open the file RBT1001/src/week1/turtles_controller.py. This is a template that is already pre-filled with some definitions and statements to make it easier to write your first ROS node.
Node definition
A python ROS should start with a main function, such as:
def main(args=None):
    rclpy.init(args=args)
    turtles_controller = TurtlesController()
    rclpy.spin(turtles_controller)
    turtles_controller.destroy_node()
    rclpy.shutdown()
where rclpy.spin() is a blocking function that starts the node and waits until it terminates.
The node itself, is a class that inherits the Node object:
class TurtlesController(Node):
    def __init__(self):
        # Defines the name of the node
        super().__init__('turtles_controller')
        ...
:arrow_forward: :desktop_computer: Make sure the turtlesim node is running - if not, relaunch it.
:arrow_forward: :desktop_computer: From a terminal, navigate to the location of the script (e.g. cd src/week1) and launch the script:
python3 turtles_controller.py
:arrow_forward: :technologist: Once this is launched, you will be able to see the turtles_controller node in the ROS network - try it!
How does it work? Subscribing and publishing to topics
from geometry_msgs.msg import Twist
class TurtlesController(Node):
    def __init__(self):
        ...
        self.t1_cmd_pub = self.create_publisher(
            Twist, 
            '/turtle1/cmd_vel', 
            10
        )
create_publisher declares that the node publishes messages of type Twist (imported from the geometry_msgs.msg module), over a topic named /turtle1/cmd_vel, and that the “queue size” is 10. Queue size is a required QoS (quality of service) setting that limits the amount of queued messages if a subscriber is not receiving them fast enough.
To publish a message, we need to create a Twist message object first and then call the publisher's publish() function. For example:
        ...
        msg = Twist()
        msg.angular.z = 0.7 * self.t1_rot_direction
        self.t1_cmd_pub.publish(msg)
        ...     
In a similar way, subscribing to receive a topic's messages can be done by calling the create_subscription method. This time, we also need to pass a callback function, called t1_pose_cb in the example below, which receives the messages.
class TurtlesController(Node):
    def __init__(self):
        ...
        self.t1_pose_sub = self.create_subscription(
            Pose,
            "/turtle1/pose",
            self.t1_pose_cb,
            10
        )
    ...
    def t1_pose_cb(self, msg):
        self.get_logger().debug('I got turtle1 pose: "%s"' % msg)
        self.t1_pose = msg
Your Task
:arrow_forward: Goal: make the robot arm move to random joint configurations every 2 seconds.
If you open the script RBT1001/src/week1/random_arm_controller.py, you will find a template ready for you.
:arrow_forward: :technologist: Identify all the ## TODO in the code and complete as instructed to achieve the objective.
:arrow_forward: :technologist: Ensuring the mecharm node is running, close the Joint State Publisher window from the graphical interface (otherwise it will override the joint_state messages of your code) and launch your random_arm_controller!