Step 1
Your first ROS 2 node
Write a node whose timer publishes joint commands to the arm's controller, and make the base wave.
The ROS graph
A ROS 2 system is a set of nodes: programs that each do one job. Nodes talk over topics, named channels that carry messages of one type. A node publishes on a topic, and every node subscribed to it gets each message. Publishers and subscribers never know about each other: ROS connects them by the topic's name and type.
This arm already runs the nodes a real arm's driver would:
| Node | Topic | Message type | What it is |
|---|---|---|---|
/joint_state_broadcaster | publishes /joint_states | sensor_msgs/msg/JointState | where every joint is, 50 times a second |
/forward_position_controller | subscribes to /forward_position_controller/commands | std_msgs/msg/Float64MultiArray | targets [base, shoulder, elbow, wrist] in radians |
/robot_state_publisher | publishes /robot_description | std_msgs/msg/String | the arm's description |
A node is a class
class Waver(Node):
def __init__(self):
super().__init__("waver")
self.pub = self.create_publisher(Float64MultiArray, "/forward_position_controller/commands", 10)
self.timer = self.create_timer(0.05, self.tick)
Your class extends rclpy's Node, and super().__init__("waver") gives it its name. The 10 is the publisher's queue depth, a quality-of-service (QoS) setting. A timer calls self.tick every 0.05 s; self is how the methods share state. Message fields are typed as strictly as in rclpy: msg.data = [0.0, 0.3, 1.2, 1.0] works, an integer like 0 raises, and numpy arrays need .tolist().
main()
rclpy.init() starts ROS, rclpy.spin(node) runs its callbacks until shutdown, then destroy_node() and rclpy.shutdown() clean up. On a robot, ros2 run my_pkg waver calls main().
Here vs a real robot
- Everything runs in one process on simulated time, as with
use_sim_time, and callbacks take no time. spin()returns after 8 s, as if you'd pressed Ctrl+C. On a robot Ctrl+C raisesKeyboardInterrupt, so real code wrapsspinintry.- There's no
ros2command line: the checks playros2 node listandros2 topic hz.
Your task
Finish Waver: at 20 Hz, publish [0.6·sin(πt), 0.3, 1.2, 1.0], where t is the seconds since the node started. The base waves ±0.6 rad every 2 s while the other joints hold still. Log "Waving" once when the node starts, with self.get_logger().info.