diff --git a/scripts/joystick-launcher/README.md b/scripts/joystick-launcher/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7667eb8445d2bc2f0d84cf73eda44a0a71c3bbfe
--- /dev/null
+++ b/scripts/joystick-launcher/README.md
@@ -0,0 +1,17 @@
+# Joystick Launcher
+
+Start and stop the controller from the a joystick.
+
+## Install
+
+```bash
+sudo cp *.service /etc/systemd/system
+sudo systemctl daemon-reload
+sudo systemctl enable joystick-launcher
+sudo systemctl start joystick-launcher
+```
+
+## Use
+
+To start the controller, press LR1 + north (triangle on a ps-like gamepad)
+To stop the controller, press LR1 + west (square on a ps-like gamepad)
diff --git a/scripts/joystick-launcher/gepetto-quadruped-reactive-walking.service b/scripts/joystick-launcher/gepetto-quadruped-reactive-walking.service
new file mode 100644
index 0000000000000000000000000000000000000000..a02507bc27da32bfc711dee4f86c7b7b10370c51
--- /dev/null
+++ b/scripts/joystick-launcher/gepetto-quadruped-reactive-walking.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Gepetto Quadruped Reactive Walking
+
+[Service]
+Type=simple
+WorkingDirectory=/home/pi/src/quadruped-reactive-walking/build
+ExecStart=/home/pi/src/quadruped-reactive-walking/build/gepetto-quadruped-reactive-walking
diff --git a/scripts/joystick-launcher/joystick-launcher.py b/scripts/joystick-launcher/joystick-launcher.py
new file mode 100755
index 0000000000000000000000000000000000000000..0182250e95449fae265c922a1e01e32b27b81b6d
--- /dev/null
+++ b/scripts/joystick-launcher/joystick-launcher.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+"""Start and stop the odri-controller service."""
+
+import dbus
+from inputs import get_gamepad
+
+SERVICE = "gepetto-quadruped-reactive-walking.service"
+SYSTEMD = "org.freedesktop.systemd1"
+SYSTEMDS = '/' + SYSTEMD.replace('.', '/')
+
+
+def get_manager():
+    sysbus = dbus.SystemBus()
+    systemd1 = sysbus.get_object(SYSTEMD, SYSTEMDS)
+    return dbus.Interface(systemd1, SYSTEMD + ".Manager")
+
+
+def start(manager):
+    manager.StartUnit(SERVICE, "replace")
+
+
+def stop(manager):
+    manager.StopUnit(SERVICE, "replace")
+
+
+def main():
+    manager = get_manager()
+    security = False  # ensure no accidental trigger
+    while True:
+        for event in get_gamepad():
+            if event.code == "BTN_TR":
+                security = event.state == 1
+            elif security and event.state == 1:
+                if event.code == "BTN_NORTH":
+                    start(manager)
+                elif event.code == "BTN_WEST":
+                    stop(manager)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/scripts/joystick-launcher/joystick-launcher.service b/scripts/joystick-launcher/joystick-launcher.service
new file mode 100644
index 0000000000000000000000000000000000000000..16358613d53d63c12d449f66ea05548323663c41
--- /dev/null
+++ b/scripts/joystick-launcher/joystick-launcher.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Start the Gepetto Quadruped Reactive Walking service from a joystick
+StartLimitIntervalSec=2
+
+[Service]
+Type=simple
+Restart=always
+RestartSec=5
+WorkingDirectory=/home/pi/src/quadruped-reactive-walking/scripts/joystick-launcher
+ExecStart=/home/pi/src/quadruped-reactive-walking/scripts/joystick-launcher/joystick-launcher.py
+
+[Install]
+WantedBy=multi-user.target