diff --git a/doc/how_to_guides/controller_teleoperation/controller_teleoperation.rst b/doc/how_to_guides/controller_teleoperation/controller_teleoperation.rst
new file mode 100644
index 0000000000..d8235ef21a
--- /dev/null
+++ b/doc/how_to_guides/controller_teleoperation/controller_teleoperation.rst
@@ -0,0 +1,89 @@
+How to Teleoperate a Robotic Arm with a Gamepad
+===============================================
+
+This guide will introduce you to using a gamepad to move the panda arm.
+
+Prerequisites
+-------------
+Make sure your workspace has the required packages installed and that you
+have a gamepad supported by ROS2 joy. This can be tested by launching a
+``joy`` node and then running ``ros2 topic echo /joy`` to ensure your
+gamepad is detected by ``joy``.
+
+Requirements
+------------
+- Ubuntu 22.04
+- ROS 2 Humble
+- MoveIt 2
+- MoveIt 2 Tutorials
+- `ROS2 joy `_
+
+Steps
+-----
+
+1. Build the MoveIt2 workspace
+
+ First, ``cd`` to the root directory of the moveit2 workspace. (if you followed the :doc:`Getting Started ` tutorial, this will be ``~/ws_moveit/``).
+
+ Then, run ``colcon build``.
+
+2. Plug in your gamepad.
+3. Source the install script and run the ``moveit_servo`` example file.
+
+ Run ``source install/setup.bash``, then ``ros2 launch moveit_servo servo_example.launch.py``
+
+4. Move the arm around, using the below image as a guide.
+
+ .. image:: xboxcontroller.png
+ :width: 600px
+
+The drawio document can be seen `here `__.
+
+Explanation
+-----------
+
+This section explains the launch file and the node that translates gamepad inputs to motion commands.
+
+Launch File
+^^^^^^^^^^^
+
+The file that launches this example is
+``ws_moveit2/src/moveit2/moveit_ros/moveit_servo/launch/servo_example.launch.py``
+
+This launch file launches everything needed for the panda arm planning, and also launches the ``joy`` node and the ``JoyToServoPub`` node (which is explained below).
+
+Of primary interest is the section of code that launches the joy and ``JoyToServoPub`` nodes.
+They are both created as ``ComposableNode``\s. More information about ``ComposableNode``\s can be found `here `__ and `here `__.
+
+.. code-block:: python
+
+ ComposableNode(
+ package="moveit_servo",
+ plugin="moveit_servo::JoyToServoPub",
+ name="controller_to_servo_node",
+ ),
+ ComposableNode(
+ package="joy",
+ plugin="joy::Joy",
+ name="joy_node",
+ )
+
+JoyToServoPub
+^^^^^^^^^^^^^
+
+The node that translates gamepad inputs to motion commands is
+``ws_moveit2/src/moveit2/moveit_ros/moveit_servo/src/teleop_demo/joystick_servo_example.cpp``
+
+This node subscribes to the joy node (which publishes messages giving the state of the gamepad). It publishes ``TwistStamped`` messages, ``JointJog`` messages, and ``PlanningScene`` messages.
+
+The ``PlanningScene`` message is only published once, when the JoyToServoPub is first constructed. It simply adds some obstacles into the planning scene.
+
+The difference between the ``JointJog`` and ``TwistStamped`` messages is
+that the inverse kinematic solver moves the joints to achieve the end
+effector motions defined by the ``TwistStamped`` messages, while the
+``JointJog`` messages directly move individual joints.
+
+The ``joyCB`` function is called when a message is published to the ``joy``
+topic, and translates the button presses from the gamepad into commands
+for the arm. If both ``JointJog`` and ``TwistStamped`` messages would be
+published by the inputs, only ``JointJog`` messages are published.
diff --git a/doc/how_to_guides/controller_teleoperation/xboxcontroller.png b/doc/how_to_guides/controller_teleoperation/xboxcontroller.png
new file mode 100644
index 0000000000..163db74267
Binary files /dev/null and b/doc/how_to_guides/controller_teleoperation/xboxcontroller.png differ
diff --git a/doc/how_to_guides/how_to_guides.rst b/doc/how_to_guides/how_to_guides.rst
index a0793f3758..ddeceefaab 100644
--- a/doc/how_to_guides/how_to_guides.rst
+++ b/doc/how_to_guides/how_to_guides.rst
@@ -11,3 +11,4 @@ These how-to guides will help you quickly solve specific problems using MoveIt.
how_to_setup_docker_containers_in_ubuntu
how_to_write_doxygen
using_ompl_constrained_planning/ompl_constrained_planning
+ controller_teleoperation/controller_teleoperation
diff --git a/doc/how_to_guides/how_to_write_doxygen.rst b/doc/how_to_guides/how_to_write_doxygen.rst
index c3b1a1dfab..d2f539210b 100644
--- a/doc/how_to_guides/how_to_write_doxygen.rst
+++ b/doc/how_to_guides/how_to_write_doxygen.rst
@@ -17,6 +17,8 @@ One of the primary benefits of Doxygen is that it allows for automatic generatio
Plugins exist to automate the creation of Doxygen documentation for
+
+
- `SublimeText `_
- `VIM `_
- `VSCode `_