Bird
Raised Fist0
ROSframework~10 mins

Joystick control with joy package in ROS - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Joystick control with joy package
Start ROS Node
Initialize joy Node
Subscribe to /joy topic
Receive Joystick Messages
Process axes and buttons
Publish control commands
Repeat on new joystick input
Shutdown Node
The joystick node starts, subscribes to joystick messages, processes inputs, publishes commands, and repeats until shutdown.
Execution Sample
ROS
import rospy
from sensor_msgs.msg import Joy

def joy_callback(data):
    rospy.loginfo(f"Axes: {data.axes}, Buttons: {data.buttons}")

rospy.init_node('joy_listener')
rospy.Subscriber('joy', Joy, joy_callback)
rospy.spin()
This code listens to joystick messages and prints axes and button states each time a message arrives.
Execution Table
StepActionInput Data (axes, buttons)Callback OutputNode State
1Node initialized--Node running, waiting for messages
2Joystick message received[0.0, 1.0, -0.5], [0, 1, 0]Print axes and buttonsProcessed first joystick input
3Joystick message received[0.5, 0.0, 0.0], [1, 0, 0]Print axes and buttonsProcessed second joystick input
4Joystick message received[-1.0, -1.0, 1.0], [0, 0, 1]Print axes and buttonsProcessed third joystick input
5No more messages--Node waiting or shutdown
💡 Node stops when ROS is shut down or interrupted.
Variable Tracker
VariableStartAfter 1After 2After 3Final
data.axes-[0.0, 1.0, -0.5][0.5, 0.0, 0.0][-1.0, -1.0, 1.0]-
data.buttons-[0, 1, 0][1, 0, 0][0, 0, 1]-
Key Moments - 3 Insights
Why does the callback function run multiple times?
Because each joystick message triggers the callback, as shown in execution_table rows 2, 3, and 4 where new data arrives and is processed.
What happens if no joystick is connected?
No messages arrive, so the node stays waiting at step 1 or 5 in the execution_table, not processing any input.
How do axes and buttons data relate to joystick movement?
Axes are float values representing joystick position; buttons are integers showing pressed (1) or not (0), as seen in variable_tracker changes.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what are the axes values at Step 3?
A[0.5, 0.0, 0.0]
B[0.0, 1.0, -0.5]
C[-1.0, -1.0, 1.0]
D[1.0, 0.0, 0.0]
💡 Hint
Check the 'Input Data (axes, buttons)' column at Step 3 in execution_table.
At which step does the node process the joystick button press [0, 0, 1]?
AStep 2
BStep 3
CStep 4
DStep 5
💡 Hint
Look at the 'Input Data (axes, buttons)' column for buttons data in execution_table.
If the joystick sends no messages, what happens to the node state?
ANode shuts down immediately
BNode waits without processing input
CNode processes default data
DNode crashes
💡 Hint
Refer to execution_table Step 1 and Step 5 node states.
Concept Snapshot
Joystick control with joy package in ROS:
- Initialize ROS node
- Subscribe to 'joy' topic
- Receive sensor_msgs/Joy messages
- Process axes (float array) and buttons (int array)
- Use callback to handle input
- Publish commands or log data
- Node runs until shutdown
Full Transcript
This visual execution trace shows how a ROS node using the joy package works. The node starts and subscribes to the 'joy' topic. Each time a joystick message arrives, the callback function runs, printing the axes and buttons data. The axes represent joystick positions as floats, and buttons show pressed states as integers. The node processes multiple messages, updating its state each time. If no joystick is connected, the node waits without processing input. The node continues running until ROS is shut down.

Practice

(1/5)
1. What is the main purpose of the joy package in ROS?
easy
A. To read joystick inputs and publish them as ROS messages
B. To control robot motors directly
C. To visualize sensor data in RViz
D. To simulate robot movements in Gazebo

Solution

  1. Step 1: Understand the role of the joy package

    The joy package reads input from a joystick device and converts it into ROS messages.
  2. Step 2: Identify what the package publishes

    It publishes joystick data on the /joy topic for other nodes to use.
  3. Final Answer:

    To read joystick inputs and publish them as ROS messages -> Option A
  4. Quick Check:

    joy package = joystick input publisher [OK]
Hint: Remember joy package publishes joystick data on /joy topic [OK]
Common Mistakes:
  • Confusing joy package with motor control packages
  • Thinking joy package visualizes data
  • Assuming joy package simulates robots
2. Which ROS topic should you subscribe to in order to receive joystick data from the joy package?
easy
A. /scan
B. /cmd_vel
C. /odom
D. /joy

Solution

  1. Step 1: Identify the topic published by joy package

    The joy package publishes joystick messages on the /joy topic.
  2. Step 2: Match the topic to subscription

    To get joystick data, subscribe to /joy, not other topics like /cmd_vel or /odom.
  3. Final Answer:

    /joy -> Option D
  4. Quick Check:

    Subscribe to /joy for joystick data [OK]
Hint: Joystick data is always on /joy topic [OK]
Common Mistakes:
  • Subscribing to /cmd_vel instead of /joy
  • Confusing sensor topics like /scan with joystick
  • Using /odom which is for odometry
3. Given the following Python callback for joystick data, what will be printed if the joystick's first axis value is 0.5 and the first button is pressed (value 1)?
def joy_callback(data):
    print(f"Axis 0: {data.axes[0]}")
    print(f"Button 0: {data.buttons[0]}")
medium
A. Axis 0: 1 Button 0: 0.5
B. Axis 0: 0.5 Button 0: 1
C. Axis 0: 0 Button 0: 0
D. Axis 0: 1 Button 0: 1

Solution

  1. Step 1: Understand data.axes and data.buttons arrays

    The axes array holds float values for joystick axes; buttons holds integers for button states.
  2. Step 2: Match given values to print statements

    Given axis 0 is 0.5 and button 0 is pressed (1), the print outputs match exactly those values.
  3. Final Answer:

    Axis 0: 0.5 Button 0: 1 -> Option B
  4. Quick Check:

    axes[0]=0.5, buttons[0]=1 [OK]
Hint: Axes are floats, buttons are integers in joystick messages [OK]
Common Mistakes:
  • Mixing axes and buttons values
  • Assuming buttons are floats
  • Confusing index positions
4. What is wrong with this ROS Python subscriber code for joystick data?
import rospy
from sensor_msgs.msg import Joy

def callback(data):
    print(data.axes[0])

rospy.init_node('joy_listener')
rospy.Subscriber('/joy', Joy, callback)
rospy.spin()
medium
A. The subscriber topic name should be '/joy_data' not '/joy'
B. The callback function is missing the 'self' parameter
C. The code is correct and will print the first axis value
D. The message type should be Twist, not Joy

Solution

  1. Step 1: Check topic and message type correctness

    The joy package publishes on '/joy' topic with message type Joy, which matches the subscriber.
  2. Step 2: Verify callback function signature and usage

    The callback takes one argument (data) and prints the first axis value correctly.
  3. Final Answer:

    The code is correct and will print the first axis value -> Option C
  4. Quick Check:

    Subscriber to /joy with Joy message and callback is correct [OK]
Hint: Callback for subscriber needs one argument, no self unless in class [OK]
Common Mistakes:
  • Using wrong topic name
  • Adding 'self' in non-class callback
  • Using wrong message type
5. You want to control a robot's forward speed using the joystick's vertical axis (axis 1). Which of these code snippets correctly converts the joystick input to a velocity command published on /cmd_vel topic using the joy package data?
hard
A. velocity.linear.x = data.axes[1]; pub.publish(velocity)
B. velocity.linear.x = data.buttons[1]; pub.publish(velocity)
C. velocity.angular.z = data.axes[1]; pub.publish(velocity)
D. velocity.linear.y = data.axes[0]; pub.publish(velocity)

Solution

  1. Step 1: Identify joystick axis for forward speed

    Vertical axis is usually axis 1, which controls forward/backward movement.
  2. Step 2: Assign axis value to linear.x velocity

    Forward speed is controlled by linear.x in Twist messages, so assign data.axes[1] to velocity.linear.x.
  3. Final Answer:

    velocity.linear.x = data.axes[1]; pub.publish(velocity) -> Option A
  4. Quick Check:

    Forward speed = linear.x = axes[1] [OK]
Hint: Forward speed maps to linear.x and vertical joystick axis [OK]
Common Mistakes:
  • Using buttons instead of axes for speed
  • Assigning to angular.z instead of linear.x
  • Using wrong axis index