GO2 Steamdeck
=============

Quick Start
-----------

This guide provides instructions for interfacing with the **Unitree GO2 Edu** robot using **Ubuntu 20.04** and **ROS2 Foxy**.


.. image:: media/figures/go2_foxy_1.jpg
    :alt: Go2 
    :width: 50%
    :align: center
    :class: mbsrounded  

|

.. note::

   - Ensure that you have already completed the setup and pairing with your GO2 Edu.  
   - Verify all functionality using the mobile app before continuing.  
   - Initial setup instructions can be found in the **GO2 Docs**.  
   - This guide builds upon the information available in those docs.

.. warning::

   The documentation below is valid **only for the GO2 Edu version** (tested until 08-July-2025).

.. warning::

   Unitree is constantly updating their firmware, and at times changing naming conventions may cause breakage in some newer firmwares.  
   If this occurs, either **submit an issue** or **create a pull request** with the correct feature updates.


Static Network Connection
-------------------------

For the **first-time connection**, you must configure the robot’s network via a LAN cable.

1. On your **PC** (not on the robot), open:

   **Settings → Network → Add (+) New Connection**

2. In the **IPv4** settings:

   - Change the method to **Manual**  
   - Set the **IP Address**: ``192.168.123.51``  
   - Set the **Netmask**: ``24``  
   - Save and restart your network connection

3. Confirm that the host's local IP is configured correctly:

   .. code-block:: bash

      ifconfig

4. Ping the robot to verify the connection:

   .. code-block:: bash

      ping 192.168.123.18

5. Access the robot via **SSH**:

   .. code-block:: bash

      ssh -X unitree@192.168.123.18

   Default password:

   .. code-block:: none

      123


IP Addresses
------------

.. list-table::
   :header-rows: 1
   :widths: 20 25 20 20

   * - **IP Address**
     - **Device**
     - **Username**
     - **Password**
   * - 192.168.123.161
     - GO2 MCU
     - x
     - x
   * - 192.168.123.18
     - GO2 Auxiliary PC
     - unitree
     - 123
   * - 192.168.123.18:9000
     - GO2 Webserver MBS
     - x
     - mybotshop

.. warning::

   Other active networks may interfere with your connection.  
   For best results, disconnect from all other networks and connect **only** to the GO2.


Network Connection
------------------

**Connection via LAN:**

.. code-block:: bash

   ssh -X unitree@192.168.123.18

When starting up, keep in mind:

- The **Go2 wrapper** operates on ``ROS_DOMAIN_ID=10``.  
  Launch files automatically use **Domain ID 10**.  

- The **namespace** can be changed to match your robot’s ID for multi-robot systems.  


Drivers Startup
---------------

- After completing installation, the ROS2 packages will run in the background (if pre-installed by the **mybotshop** team).  

.. important::

   - To check which packages must run, see the ``go2_bringup`` startup script.  
   - Service names are mentioned there and can be referenced directly.  

   Example:

   .. code-block:: bash

      sudo service go2-webserver status
      ros2 launch go2_webserver webserver.launch.py

   - Ensure duplicate services are not running simultaneously.  
     Close unnecessary services before launching new ones.


.. image:: media/figures/go2_steamdeck_2.jpg
    :alt: Go2 
    :width: 80%
    :align: center
    :class: mbsrounded  

|


Gaits
-----

Available gait modes:

**Normal Trot** (recommended for Nav2, SLAM applications):

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'gait_type_classic'}"

**Flat Terrain Mode** (for flat environments):

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'gait_type_flat_terrain'}"

**Economic Trot** (long runs, battery conservation):

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'gait_type_economic'}"

**Fast Trot:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'gait_type_trot_run'}"

**A.I Trot:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'gait_type_agile'}"


Sports Mode
-----------

.. important::

   The **Sports Mode** feature is **deprecated** in **GO2 v2.2.1+**  
   or with the latest firmware update.

Switch to sports mode:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/modes go2_interface/srv/Go2Modes "{request_data: 'sports_mode'}"


Visualization
-------------

Launch **RViz** visualization:

.. code-block:: bash

   ros2 launch go2_viz view_robot.launch.py


GO2 Tele-operation
------------------

Run teleoperation with keyboard:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args --remap cmd_vel:=/go2_unit_21576/cmd_vel


ROS2 Modules
------------

This section describes the **ROS2 modules** available for the Unitree GO2 platform, their usage, and example commands.


Webserver
---------

The **GO2 Webserver** module comes pre-installed for heavy integration projects.  

It can be accessed directly via:

- **LAN**: http://192.168.123.18:9000/  
- **Wi-Fi**: The IP assigned to the robot  

The configuration file is located at:

``/opt/mybotshop/src/mybotshop/go2_webserver/config/robot_webserver.yaml``

Login
^^^^^

The login page allows authorized access to the GO2 webserver interface.  

.. image:: media/figures/web_login.png
   :alt: GO2 Webserver Login

Dashboard
^^^^^^^^^

The **Dashboard** provides key system controls:

- Enable or disable the GO2 ROS2 services.  
- Record system logs for debugging or analysis.  

.. image:: media/figures/web_dashboard.png
   :alt: GO2 Webserver Dashboard

System
^^^^^^

The **System** page displays the external PC status of the Unitree GO2.  
- Battery status is only active when ROS2 drivers are enabled from the Dashboard.  

.. image:: media/figures/web_system.png
   :alt: GO2 Webserver System Status

Console
^^^^^^^

The **Console** allows direct control over the Unitree GO2:

- Move the robot and switch between different gaits.  
- Adaptable to new ROS2 services.  
- Record ROS2 bags for later playback.  
- Access the GO2 external speaker if available.  

.. image:: media/figures/web_console.png
   :alt: GO2 Webserver Console

Remote Desktop
^^^^^^^^^^^^^^

Access the on-board screen of the GO2’s computer directly via the webserver.

.. image:: media/figures/web_vnc.png
   :alt: GO2 Webserver Remote Desktop

Navi Indoor
^^^^^^^^^^^

This feature is **coming soon**.  

.. image:: media/figures/web_nav_indoor.png
   :alt: GO2 Webserver Navi Indoor

Navi Outdoor
^^^^^^^^^^^^

This feature is **coming soon**.

LLM Interface
^^^^^^^^^^^^^

This feature is **coming soon**.


Mode Activation
---------------

The following **modes** are available via ROS2 services:

- balance_stand
- recovery_stand
- stand_down
- stand_up
- stretch
- damp
- sit
- rise_sit
- front_jump
- front_pounce
- front_flip
- stop_move

.. note::

   These functions can be extended in the ``go2_platform.cpp`` file  
   to support new firmware features from the Unitree team.

**Available functionalities via ROS2 services:**

- **Light level:**  0–10  
- **Volume level:** 0–10  

Example — **Activating stand-up mode**:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_001/modes go2_interface/srv/Go2Modes "{request_data: 'stand_up'}"

Wait a few seconds, then switch to balance stand:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_001/modes go2_interface/srv/Go2Modes "{request_data: 'balance_stand'}"

Example — **Standing down**:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_001/modes go2_interface/srv/Go2Modes "{request_data: 'stand_up'}"

.. note::

   First use ``stand_up`` to remove balance mode,  
   then ``stand_down``. This is required for the latest firmware and GO2-W.

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_001/modes go2_interface/srv/Go2Modes "{request_data: 'stand_down'}"

Example — **Changing light level (0–10):**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/light go2_interface/srv/Go2Light "{light_level: 10}"

Example — **Changing volume level (0–10):**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 service call /go2_unit_21576/volume go2_interface/srv/Go2Volume "{volume_level: 4}"

.. note::

   Sometimes modes (e.g., ``stand``) may fail to activate.  
   In such cases, use the **recovery stand** mode.


Realsense Depth Cameras
-----------------------

.. warning::

   If running **both Realsense cameras**, launch them in **separate terminals** with a **10s delay** to avoid conflicts.

**Realsense D405**:

.. code-block:: bash

   ros2 launch go2_depth_camera realsense_d405.launch.py

**Realsense D435i**:

.. code-block:: bash

   ros2 launch go2_depth_camera realsense_d435i.launch.py

.. note::

   - By default, both **Realsense D435i** and **D405** are disabled.  
   - The launch file is preconfigured to stream depth data continuously from D435i without lag.  
     Modify parameters in: ``go2_depth_camera/launch/realsense_d4XX.launch.py``

.. image:: media/figures/go2_steamdeck_3.jpg
    :alt: Go2 
    :width: 50%
    :align: center
    :class: mbsrounded  

|


Lidar Modules
-------------

**Livox Mid360**:

.. code-block:: bash

   ros2 launch go2_lidars livox_mid360.launch.py

**Hesai Pandar XT-16**:

.. code-block:: bash

   ros2 launch go2_lidars hesai.launch.py

After launching, access the sensor’s web UI and configure:

- **Spin rate**: 300  
- **Return mode**: strongest return  
- **Azimuth**: 30 → 330  


Fixposition Setup
-----------------

Install dependencies:

.. code-block:: bash

   sudo apt update
   sudo apt install libyaml-cpp-dev libboost-all-dev zlib1g-dev libeigen3-dev linux-libc-dev nlohmann-json3-dev

**Build Fixposition:**

.. code-block:: bash

   distrobox enter ros2_humble
   rm /opt/mybotshop/src/third_party/gps/07Aug2025_fixposition_humble/COLCON_IGNORE
   cp -r /opt/mybotshop/src/third_party/gps/07Aug2025_fixposition_humble /home/unitree/fixposition_humble
   cd /home/unitree/fixposition_humble 
   source /opt/ros/humble/setup.bash
   ./setup_ros_ws.sh -r 2
   ./create_ros_ws.sh /home/unitree/fixposition_humble_ws
   cd /home/unitree/fixposition_humble_ws
   colcon build --symlink-install --cmake-args -DBUILD_TESTING=OFF && source install/setup.bash

**Run Fixposition:**

.. code-block:: bash

   distrobox enter ros2_humble
   source /opt/ros/humble/setup.bash
   source /home/unitree/fixposition_humble_ws/install/setup.bash
   ros2 launch fixposition_driver_ros2 fixposition_humble.launch.py

**Run converter (new terminal):**

.. code-block:: bash

   ros2 launch odom_to_tf_ros2 odom_to_tf.launch.py


Open Manipulator Control
------------------------

**Start the custom ROS driver:**

.. code-block:: bash

   ros2 launch go2_manipulation openmanipulator.launch.py

.. note::

   This driver must always be running when using **MoveIt** or joint trajectories.

**Launch MoveIt & State Publisher:**

.. code-block:: bash

   ros2 launch go2_manipulation moveit2.launch.py


Open Manipulator Commands
-------------------------

.. note::

   Update the namespace accordingly if required.

**Test driver:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_001/open_manipulator/joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [joint1, joint2, joint3, joint4],
       points: [
         { positions: [0.1, 0.1, 0.1, 0.1], time_from_start: { sec: 2 } },
         { positions: [-0.1, -0.1, -0.1, -0.1], time_from_start: { sec: 4 } },
         { positions: [0, 0, 0, 0], time_from_start: { sec: 6 } }
       ]
     }
   }"

**Home position (before turning off, GO2 prior to 06 Mar 2025):**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_001/open_manipulator/joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [joint1, joint2, joint3, joint4],
       points: [
         { positions: [0.0, -1.4, 1.2, 1.2], time_from_start: { sec: 2 } },
       ]
     }
   }"

**Stand position:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_21576/open_manipulator/joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [joint1, joint2, joint3, joint4],
       points: [
         { positions: [0.0, -0.2, -0.1, -0.24], time_from_start: { sec: 1 } },
       ]
     }
   }"

**Home position (GO2 after 06 Mar 2025):**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_21576/open_manipulator/joint_trajectory_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [joint1, joint2, joint3, joint4],
       points: [
         { positions: [0.0, -1.7, 1.4, 1.2], time_from_start: { sec: 2 } },
       ]
     }
   }"

**Close gripper (before turning off):**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_21576/open_manipulator/gripper_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [gripper],
       points: [
         { positions: [1.0], time_from_start: { sec: 2 } },
       ]
     }
   }"

**Open gripper:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 action send_goal /go2_unit_21576/open_manipulator/gripper_controller/follow_joint_trajectory control_msgs/action/FollowJointTrajectory -f "{
     trajectory: {
       joint_names: [gripper],
       points: [
         { positions: [-1.0], time_from_start: { sec: 2 } },
       ]
     }
   }"


Navigation
----------

This section covers **SLAM**, **navigation**, **startup services**, and **simulation tools** for the Unitree GO2 robot.


SLAM (Simultaneous Localization and Mapping)
--------------------------------------------

.. warning::

   The SLAM feature is **not yet ported** to the new system.

1. Ensure ``go2_bringup`` is running.  
2. Launch SLAM:

   .. code-block:: bash

      ros2 launch go2_navigation slam.launch.py

3. Begin mapping using teleoperation at **0.2 m/s** (keyboard control recommended).  
4. Once satisfied with your map, export it:

   .. code-block:: bash

      ROS_DOMAIN_ID=10 ros2 run nav2_map_server map_saver_cli -f /opt/mybotshop/src/mybotshop/go2_navigation/maps/custom_map

5. Rebuild so that custom maps can be located (required if the map name is **not `map_`**):

   .. code-block:: bash

      cd /opt/mybotshop/ && colcon build --symlink-install && source /opt/mybotshop/install/setup.bash


Odometric Navigation
--------------------

.. note::

   The **Nav2 Goal Tool** and **Nav2 Goal Plugin** do not work due to namespace issues.  
   Instead, use **2D Goal Pose** in RViz or custom scripts.

Launch odometric navigation:

.. code-block:: bash

   ros2 launch go2_navigation odom_navi.launch.py


Map Navigation
--------------

.. note::

   The **Nav2 Goal Tool** and **Nav2 Goal Plugin** do not work due to namespace issues.  
   Use **2D Goal Pose** or scripts instead.

1. Ensure a map is generated and available in the ROS package.  
   (After saving, place the map in the correct location and rebuild with ``colcon build``.)  

2. Launch map-based navigation:

   .. code-block:: bash

      ros2 launch go2_navigation map_navi.launch.py


Startup Services
----------------

By default, the GO2 does **not** include a startup job unless explicitly configured.  
It only launches:

``go2_bringup/system.launch.py``

To verify if a startup service exists:

.. code-block:: bash

   sudo service go2-<ros2 module name> status

- **Error message**: ``Unit <ros2 module name>.service could not be found.`` → No startup service is installed.  
- **Markers**:  

  +-----------+--------------------------------------------------+
  | **Color** | **Meaning**                                      |
  +===========+==================================================+
  | Red       | Startup job has **failed**                       |
  +-----------+--------------------------------------------------+
  | Green     | Service is **running correctly**                 |
  +-----------+--------------------------------------------------+
  | Grey      | Service has **not yet started**                  |
  +-----------+--------------------------------------------------+

Restart a service if red/grey:

.. code-block:: bash

   sudo service go2-<ros2 module name> restart

To modify or extend startup jobs, edit:

``go2_bringup/startup_installer.py``

Then update:

.. code-block:: bash

   ros2 run go2_bringup startup_installer.py


GO2 Steamdeck
-------------

.. image:: media/gifs/steamdeck.webp
    :alt: Go2
    :width: 100%
    :class: mbsrounded  

|

Follow the initialization guide:

`Steamdeck Initialization Docs <https://www.docs.mybotshop.de/projects/product_steamdeck/html/steamdeck_initialization.html>`_

1. Connect to the **custom router** of the GO2 (startup may take several minutes).  

**Default IP addresses:**

+-------------------------+----------------------+
| **Device**              | **IP Address**       |
+=========================+======================+
| Steamdeck               | 192.168.123.150      |
+-------------------------+----------------------+
| Router                  | 192.168.123.100      |
+-------------------------+----------------------+
| Unitree GO2             | 192.168.123.18       |
+-------------------------+----------------------+

2. Once the joystick opens, hold **L1** and use the **left/right joysticks** to move the robot.  
3. Change gaits via the **web browser console** (opens automatically at ``192.168.123.18:9000``).  
4. By default, **ROS2 drivers are off**. Use *Restart All* to enable services for Steamdeck + ROS2 control.  
5. Additional services can be added via:

   ``/opt/mybotshop/src/mybotshop/go2_webserver/go2_webserver/libroscustom.py``


+---------------------------------------------------+---------------------------------------------------+
| .. figure:: media/gifs/steamdeck_1.webp           | .. figure:: media/gifs/steamdeck_2.webp           |
|    :width: 100%                                   |    :width: 100%                                   |
|    :align: center                                 |    :align: center                                 |
|                                                   |                                                   |
+---------------------------------------------------+---------------------------------------------------+

GO2 Camera
----------

**Camera Calibration**

.. note::

   Calibration is already provided. Requires a **7x6 checkerboard**.

Run calibration:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 run camera_calibration cameracalibrator --size 8x6 --square 0.025 --camera /go2_unit_001/sensor/camera


GO2 Isaac Sim
-------------

.. note::

   Instructions for usage are located in the **humble branch**: ``qre-go2-humble``.


GO2 Gazebo Classic (Under Development)
--------------------------------------

Launch Gazebo simulation:

.. code-block:: bash

   ros2 launch go2_gazebo_classic simulation.launch.py

Example — controlling GO2 in Gazebo:

.. code-block:: bash

   ros2 run go2_platform go2_gazebo_demo


GO2 Gazebo Citadel
------------------

.. important::

   **Deprecated**

Debugging & Miscellaneous
-------------------------

This section provides instructions for **debugging, network setup, camera streaming, manipulator control, and recommended hardware enhancements**.


Debugging
---------

RQT GUI
--------

Launch the RQT GUI for ROS2:

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 run rqt_gui rqt_gui --ros-args --remap tf:=/go2_unit_21576/tf --ros-args --remap tf_static:=/go2_unit_21576/tf_static

TF Visualization
----------------

**View TF tree in RQT:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 run rqt_tf_tree rqt_tf_tree --force-discover --ros-args --remap tf:=/go2_unit_21576/tf --ros-args --remap tf_static:=/go2_unit_21576/tf_static

**Generate TF frames diagram:**

.. code-block:: bash

   ROS_DOMAIN_ID=10 ros2 run tf2_tools view_frames.py --force-discover --ros-args --remap tf:=/go2_unit_21576/tf --ros-args --remap tf_static:=/go2_unit_21576/tf_static


Miscellaneous
-------------

Internet via LAN
----------------

Connect the GO2 to a router with internet access via LAN:

.. code-block:: bash

   sudo ip link set eth0 down && sudo ip link set eth0 up
   sudo dhclient eth0

Wait 10–30 seconds, then update packages:

.. code-block:: bash

   sudo apt-get update

Update date and time automatically:

.. code-block:: bash

   sudo date -s "$(wget --method=HEAD -qSO- --max-redirect=0 google.com 2>&1 | sed -n 's/^ *Date: *//p')"

Fix GO2 USB 2.0 → 3.0 Port (2024 Models)
----------------------------------------

1. Backup the current device tree:

.. code-block:: bash

   sudo cp /boot/dtb/kernel_tegra234-p3767-0000-p3768-0000-a0.dtb kernel_tegra234-p3767-0000-p3768-0000-a0.dtb.bak

2. Download the latest device tree:  

`Latest Equipment Tree <https://oss-global-cdn.unitree.com/static/95bdc29bcc664325b5e1373d5512294a.zip>`_

3. Copy the updated device tree to the boot directory:

.. code-block:: bash

   sudo cp kernel_tegra234-p3767-0000-p3768-0000-a0.dtb /boot/dtb/ -r

4. Restart the system for changes to take effect.

Sync Host and GO2 Computers
---------------------------

Synchronize source files using `rsync`:

.. code-block:: bash

   rsync -avP -t --delete -e ssh src unitree@192.168.123.18://opt/mybotshop

Camera Stream via Terminal (Non-ROS)
------------------------------------

View video stream directly from terminal (replace ``multicast-iface`` with the network interface, e.g., ``eth0``):

.. code-block:: bash

   gst-launch-1.0 udpsrc address=230.1.1.1 port=1720 multicast-iface=eth0 ! application/x-rtp, media=video, encoding-name=H264 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink

**Faster version**:

.. code-block:: bash

   gst-launch-1.0 udpsrc address=230.1.1.1 port=1720 multicast-iface=eth0 ! \
       application/x-rtp, media=video, encoding-name=H264 ! \
       rtph264depay ! queue max-size-buffers=1 ! h264parse ! queue ! avdec_h264 ! \
       videoconvert ! autovideosink

Open Manipulator X (Independent)
--------------------------------

**Launch Open Manipulator X Controller:**

.. code-block:: bash

   ros2 launch open_manipulator_x_controller open_manipulator_x_controller.launch.py

**Teleoperate Open Manipulator X:**

.. code-block:: bash

   ros2 run open_manipulator_x_teleop teleop_keyboard


Enhancements
------------

WiFi Stick
----------

We recommend using a **long-range WiFi stick**, such as **TL-WN722N**, or any high-end long-range WiFi stick for remote operation.

.. image:: media/figures/go2_wifistick.png
    :alt: Go2
    :width: 90%
    :class: mbsrounded  

|

Connection Hub
--------------

For connecting a screen or expanding ports, we recommend a **USB-C hub** such as **Ugreen USB-C Hub with HDMI** for testing and debugging.

Latest QRE GO2 Updates
----------------------

.. important::

   The latest updates are available from the **qre_go2 GitHub repository**.  
   If access is required, email **support@mybotshop.de** with your GitHub username and purchase ID.