From 826f14725a40d1234cafe329c56f32b76c215c76 Mon Sep 17 00:00:00 2001 From: David Sharpe Date: Sun, 17 Aug 2025 09:33:28 -0500 Subject: [PATCH 1/8] feat: create headless_pkg, combine core and arm headless Toggleable with Dpad up/down --- src/headless_pkg/core_pkg/__init__.py | 0 src/headless_pkg/core_pkg/headless.py | 176 +++++++++++++++++++++++++ src/headless_pkg/package.xml | 21 +++ src/headless_pkg/resource/headless_pkg | 0 src/headless_pkg/setup.cfg | 4 + src/headless_pkg/setup.py | 25 ++++ 6 files changed, 226 insertions(+) create mode 100644 src/headless_pkg/core_pkg/__init__.py create mode 100755 src/headless_pkg/core_pkg/headless.py create mode 100644 src/headless_pkg/package.xml create mode 100644 src/headless_pkg/resource/headless_pkg create mode 100644 src/headless_pkg/setup.cfg create mode 100644 src/headless_pkg/setup.py diff --git a/src/headless_pkg/core_pkg/__init__.py b/src/headless_pkg/core_pkg/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/headless_pkg/core_pkg/headless.py b/src/headless_pkg/core_pkg/headless.py new file mode 100755 index 0000000..fd9ecf5 --- /dev/null +++ b/src/headless_pkg/core_pkg/headless.py @@ -0,0 +1,176 @@ +import rclpy +from rclpy.node import Node + +import pygame + +import time + +import serial +import sys +import threading +import glob +import os + +import importlib +from std_msgs.msg import String +from ros2_interfaces_pkg.msg import CoreControl, ArmManual + + +os.environ["SDL_VIDEODRIVER"] = "dummy" # Prevents pygame from trying to open a display +os.environ["SDL_AUDIODRIVER"] = "dummy" # Force pygame to use a dummy audio driver before pygame.init() + + +max_speed = 90 #Max speed as a duty cycle percentage (1-100) + +core_stop_msg = CoreControl() +core_stop_msg.left_stick = 0 +core_stop_msg.right_stick = 0 +core_stop_msg.max_speed = 0 + +arm_stop_msg = ArmManual() +arm_stop_msg.axis0 = 0 +arm_stop_msg.axis1 = 0 +arm_stop_msg.axis2 = 0 +arm_stop_msg.axis3 = 0 +arm_stop_msg.effector_roll = 0 +arm_stop_msg.effector_yaw = 0 +arm_stop_msg.gripper = 0 +arm_stop_msg.linear_actuator = 0 +arm_stop_msg.laser = 0 + +ctrl_mode = "core" + + +class Headless(Node): + def __init__(self): + # Initialize pygame first + pygame.init() + pygame.joystick.init() + + # Wait for a gamepad to be connected + self.gamepad = None + print("Waiting for gamepad connection...") + while pygame.joystick.get_count() == 0: + # Process any pygame events to keep it responsive + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit(0) + time.sleep(1.0) # Check every second + print("No gamepad found. Waiting...") + + # Initialize the gamepad + self.gamepad = pygame.joystick.Joystick(0) + self.gamepad.init() + print(f'Gamepad Found: {self.gamepad.get_name()}') + + # Now initialize the ROS2 node + super().__init__("headless") + self.create_timer(0.15, self.send_controls) + self.core_publisher = self.create_publisher(CoreControl, '/core/control', 10) + self.arm_publisher = self.create_publisher(ArmManual, '/arm/control/manual', 10) + + def run(self): + # This thread makes all the update processes run in the background + thread = threading.Thread(target=rclpy.spin, args={self}, daemon=True) + thread.start() + + try: + while rclpy.ok(): + self.send_controls() + time.sleep(0.1) # Small delay to avoid CPU hogging + except KeyboardInterrupt: + sys.exit(0) + + def send_controls(self): + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit(0) + + # Check if controller is still connected + if pygame.joystick.get_count() == 0: + print("Gamepad disconnected. Exiting...") + # Send one last zero control message + self.core_publisher.publish(core_stop_msg) + self.arm_publisher.publish(arm_stop_msg) + self.get_logger().info("Final stop command sent. Shutting down.") + # Clean up + pygame.quit() + sys.exit(0) + + + global ctrl_mode + + dpad_input = self.gamepad.get_hat(0) + if dpad_input[1] == 1: + ctrl_mode = "arm" + elif dpad_input[1] == -1: + ctrl_mode = "core" + + + if ctrl_mode == "core": + input = CoreControl() + input.max_speed = max_speed + input.right_stick = -1 * round(self.gamepad.get_axis(4), 2) # right y-axis + if self.gamepad.get_axis(5) > 0: + input.left_stick = input.right_stick + else: + input.left_stick = -1 * round(self.gamepad.get_axis(1), 2) # left y-axis + + output = f'L: {input.left_stick}, R: {input.right_stick}, M: {max_speed}' + self.get_logger().info(f"[Ctrl] {output}") + self.core_publisher.publish(input) + self.arm_publisher.publish(arm_stop_msg) + + if ctrl_mode == "arm": + input = ArmManual() + + # Triggers for gripper control + if self.gamepad.get_axis(2) > 0:#left trigger + input.gripper = -1 + elif self.gamepad.get_axis(5) > 0:#right trigger + input.gripper = 1 + + if self.gamepad.get_button(5):#right bumper, control effector + + # Left stick X-axis for effector yaw + if self.gamepad.get_axis(0) > 0: + input.effector_yaw = 1 + elif self.gamepad.get_axis(0) < 0: + input.effector_yaw = -1 + + # Right stick X-axis for effector roll + if self.gamepad.get_axis(3) > 0: + input.effector_roll = 1 + elif self.gamepad.get_axis(3) < 0: + input.effector_roll = -1 + + else: # Control arm axis + dpad_input = self.gamepad.get_hat(0) + input.axis0 = 0 + if dpad_input[0] == 1: + input.axis0 = 1 + elif dpad_input[0] == -1: + input.axis0 = -1 + + if self.gamepad.get_axis(0) > .15 or self.gamepad.get_axis(0) < -.15: + input.axis1 = round(self.gamepad.get_axis(0)) + + if self.gamepad.get_axis(1) > .15 or self.gamepad.get_axis(1) < -.15: + input.axis2 = -1 * round(self.gamepad.get_axis(1)) + + if self.gamepad.get_axis(4) > .15 or self.gamepad.get_axis(4) < -.15: + input.axis3 = -1 * round(self.gamepad.get_axis(4)) + + self.arm_publisher.publish(input) + self.core_publisher.publish(core_stop_msg) + +def main(args=None): + rclpy.init(args=args) + node = Headless() + rclpy.spin(node) + rclpy.shutdown() + +if __name__ == '__main__': + main() diff --git a/src/headless_pkg/package.xml b/src/headless_pkg/package.xml new file mode 100644 index 0000000..a878362 --- /dev/null +++ b/src/headless_pkg/package.xml @@ -0,0 +1,21 @@ + + + + headless_pkg + 1.0.0 + Headless rover control package to handle command interpretation and embedded interfacing. + tristan + All Rights Reserved + + rclpy + ros2_interfaces_pkg + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/src/headless_pkg/resource/headless_pkg b/src/headless_pkg/resource/headless_pkg new file mode 100644 index 0000000..e69de29 diff --git a/src/headless_pkg/setup.cfg b/src/headless_pkg/setup.cfg new file mode 100644 index 0000000..6391d1a --- /dev/null +++ b/src/headless_pkg/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/core_pkg +[install] +install_scripts=$base/lib/core_pkg diff --git a/src/headless_pkg/setup.py b/src/headless_pkg/setup.py new file mode 100644 index 0000000..e65020a --- /dev/null +++ b/src/headless_pkg/setup.py @@ -0,0 +1,25 @@ +from setuptools import find_packages, setup + +package_name = 'headless_pkg' + +setup( + name=package_name, + version='0.0.0', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='David', + maintainer_email='ds0196@uah.edu', + description='Headless rover control package to handle command interpretation and embedded interfacing.', + license='All Rights Reserved', + entry_points={ + 'console_scripts': [ + "headless = headless_pkg.headless:main", + ], + }, +) From 37774c0c31847b3a2dd8a1835c66522187c0f78d Mon Sep 17 00:00:00 2001 From: David Sharpe Date: Thu, 21 Aug 2025 15:26:53 -0500 Subject: [PATCH 2/8] feat: add systemd files from NUC --- anchor.service | 14 ++++++++++++++ auto_start/auto_start_anchor.sh | 24 ++++++++++++++++++++++++ auto_start/auto_start_core_headless.sh | 24 ++++++++++++++++++++++++ core_headless.service | 14 ++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 anchor.service create mode 100755 auto_start/auto_start_anchor.sh create mode 100755 auto_start/auto_start_core_headless.sh create mode 100644 core_headless.service diff --git a/anchor.service b/anchor.service new file mode 100644 index 0000000..7b95062 --- /dev/null +++ b/anchor.service @@ -0,0 +1,14 @@ +[Unit] +Description=Autostart the anchor node for controlling the rover and its modules +After=systemd-user-sessions.service +Requires=systemd-user-sessions.service + +[Service] +ExecStart=/home/clucky/auto_start/auto_start_anchor.sh +Restart=always +RestartSec=5 +User=clucky +Environment=PYTHONUNBUFFERED=1 + +[Install] +WantedBy=multi-user.target diff --git a/auto_start/auto_start_anchor.sh b/auto_start/auto_start_anchor.sh new file mode 100755 index 0000000..724062c --- /dev/null +++ b/auto_start/auto_start_anchor.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Wait for a network interface to be up (not necessarily online) +while ! ip link show | grep -q "state UP"; do + echo "[INFO] Waiting for active network interface..." + sleep 1 +done + +echo "[INFO] Network interface is up!" + +# Your actual ROS node start command goes here +echo "[INFO] Starting ROS node..." + +# Source ROS 2 Humble setup script +source /opt/ros/humble/setup.bash + +# Source your workspace setup script +source /home/clucky/rover-ros2/install/setup.bash + +# CD to directory +cd /home/clucky/rover-ros2/ + +# Launch the ROS 2 node with the desired mode +ros2 launch rover_launch.py mode:=anchor diff --git a/auto_start/auto_start_core_headless.sh b/auto_start/auto_start_core_headless.sh new file mode 100755 index 0000000..b59126b --- /dev/null +++ b/auto_start/auto_start_core_headless.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Wait for a network interface to be up (not necessarily online) +while ! ip link show | grep -q "state UP"; do + echo "[INFO] Waiting for active network interface..." + sleep 1 +done + +echo "[INFO] Network interface is up!" + +# Your actual ROS node start command goes here +echo "[INFO] Starting ROS node..." + +# Source ROS 2 Humble setup script +source /opt/ros/humble/setup.bash + +# Source your workspace setup script +source /home/clucky/rover-ros2/install/setup.bash + +# CD to directory +cd /home/clucky/rover-ros2/ + +# Launch the ROS 2 node +ros2 run core_pkg headless diff --git a/core_headless.service b/core_headless.service new file mode 100644 index 0000000..035ba56 --- /dev/null +++ b/core_headless.service @@ -0,0 +1,14 @@ +[Unit] +Description=Autostart headless core node for controlling the rover without a base station +After=systemd-user-sessions.service +Requires=systemd-user-sessions.service + +[Service] +ExecStart=/home/clucky/auto_start/auto_start_core_headless.sh +Restart=always +RestartSec=10 +User=clucky +Environment=PYTHONUNBUFFERED=1 + +[Install] +WantedBy=multi-user.target From 10757c8c713a810b19e043c7c7f7d6953608d0e1 Mon Sep 17 00:00:00 2001 From: David Sharpe Date: Thu, 21 Aug 2025 16:31:59 -0500 Subject: [PATCH 3/8] fix: names in ROS2 files were incorrect for headless_full, add new service files for NUC --- auto_start/auto_start_headless_full.sh | 25 +++++++++++++++++++ headless_full.service | 14 +++++++++++ src/headless_pkg/setup.cfg | 4 +-- src/headless_pkg/setup.py | 5 ++-- .../{core_pkg => src}/__init__.py | 0 .../headless.py => src/headless_node.py} | 0 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100755 auto_start/auto_start_headless_full.sh create mode 100644 headless_full.service rename src/headless_pkg/{core_pkg => src}/__init__.py (100%) rename src/headless_pkg/{core_pkg/headless.py => src/headless_node.py} (100%) diff --git a/auto_start/auto_start_headless_full.sh b/auto_start/auto_start_headless_full.sh new file mode 100755 index 0000000..488e033 --- /dev/null +++ b/auto_start/auto_start_headless_full.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Wait for a network interface to be up (not necessarily online) +while ! ip link show | grep -q "state UP"; do + echo "[INFO] Waiting for active network interface..." + sleep 1 +done + +echo "[INFO] Network interface is up!" + +# Your actual ROS node start command goes here +echo "[INFO] Starting ROS node..." + +# Source ROS 2 Humble setup script +source /opt/ros/humble/setup.bash + +# Source your workspace setup script +source /home/clucky/rover-ros2/install/setup.bash + +# CD to directory +cd /home/clucky/rover-ros2/ + +# Launch the ROS 2 node +ros2 run headless_pkg headless_full + diff --git a/headless_full.service b/headless_full.service new file mode 100644 index 0000000..ab79084 --- /dev/null +++ b/headless_full.service @@ -0,0 +1,14 @@ +[Unit] +Description=Autostart headless core node for controlling the rover without a base station +After=systemd-user-sessions.service +Requires=systemd-user-sessions.service + +[Service] +ExecStart=/home/clucky/auto_start/auto_start_headless_full.sh +Restart=always +RestartSec=10 +User=clucky +Environment=PYTHONUNBUFFERED=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/headless_pkg/setup.cfg b/src/headless_pkg/setup.cfg index 6391d1a..b9bc220 100644 --- a/src/headless_pkg/setup.cfg +++ b/src/headless_pkg/setup.cfg @@ -1,4 +1,4 @@ [develop] -script_dir=$base/lib/core_pkg +script_dir=$base/lib/headless_pkg [install] -install_scripts=$base/lib/core_pkg +install_scripts=$base/lib/headless_pkg diff --git a/src/headless_pkg/setup.py b/src/headless_pkg/setup.py index e65020a..97417fd 100644 --- a/src/headless_pkg/setup.py +++ b/src/headless_pkg/setup.py @@ -7,8 +7,7 @@ setup( version='0.0.0', packages=find_packages(exclude=['test']), data_files=[ - ('share/ament_index/resource_index/packages', - ['resource/' + package_name]), + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), ], install_requires=['setuptools'], @@ -19,7 +18,7 @@ setup( license='All Rights Reserved', entry_points={ 'console_scripts': [ - "headless = headless_pkg.headless:main", + "headless_full = src.headless_node:main", ], }, ) diff --git a/src/headless_pkg/core_pkg/__init__.py b/src/headless_pkg/src/__init__.py similarity index 100% rename from src/headless_pkg/core_pkg/__init__.py rename to src/headless_pkg/src/__init__.py diff --git a/src/headless_pkg/core_pkg/headless.py b/src/headless_pkg/src/headless_node.py similarity index 100% rename from src/headless_pkg/core_pkg/headless.py rename to src/headless_pkg/src/headless_node.py From 4254ecc4ce9ac384c8b72206ad486a4b2002592c Mon Sep 17 00:00:00 2001 From: David Date: Fri, 22 Aug 2025 16:41:54 -0500 Subject: [PATCH 4/8] fix: python float/int for /core/control --- src/headless_pkg/src/headless_node.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/headless_pkg/src/headless_node.py b/src/headless_pkg/src/headless_node.py index fd9ecf5..2ff7c32 100755 --- a/src/headless_pkg/src/headless_node.py +++ b/src/headless_pkg/src/headless_node.py @@ -23,8 +23,8 @@ os.environ["SDL_AUDIODRIVER"] = "dummy" # Force pygame to use a dummy audio dri max_speed = 90 #Max speed as a duty cycle percentage (1-100) core_stop_msg = CoreControl() -core_stop_msg.left_stick = 0 -core_stop_msg.right_stick = 0 +core_stop_msg.left_stick = 0.0 +core_stop_msg.right_stick = 0.0 core_stop_msg.max_speed = 0 arm_stop_msg = ArmManual() From d3dbbf86588e613e4221f364ec6219509ca6486a Mon Sep 17 00:00:00 2001 From: David Date: Thu, 28 Aug 2025 18:55:22 -0500 Subject: [PATCH 5/8] style: fix author stuff for headless_pkg --- src/headless_pkg/package.xml | 2 +- src/headless_pkg/setup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/headless_pkg/package.xml b/src/headless_pkg/package.xml index a878362..bcab1f8 100644 --- a/src/headless_pkg/package.xml +++ b/src/headless_pkg/package.xml @@ -4,7 +4,7 @@ headless_pkg 1.0.0 Headless rover control package to handle command interpretation and embedded interfacing. - tristan + David Sharpe All Rights Reserved rclpy diff --git a/src/headless_pkg/setup.py b/src/headless_pkg/setup.py index 97417fd..3d27cfe 100644 --- a/src/headless_pkg/setup.py +++ b/src/headless_pkg/setup.py @@ -4,7 +4,7 @@ package_name = 'headless_pkg' setup( name=package_name, - version='0.0.0', + version='1.0.0', packages=find_packages(exclude=['test']), data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), @@ -12,7 +12,7 @@ setup( ], install_requires=['setuptools'], zip_safe=True, - maintainer='David', + maintainer='David Sharpe', maintainer_email='ds0196@uah.edu', description='Headless rover control package to handle command interpretation and embedded interfacing.', license='All Rights Reserved', From caf20f46f65b2efdfb3f59bdc7b1dee747fb7acf Mon Sep 17 00:00:00 2001 From: David Date: Tue, 2 Sep 2025 02:43:38 -0500 Subject: [PATCH 6/8] refactor: poll controller state all at once, add deadzones UNTESTED Also adds ability to control axis 0 while controlling wrist --- src/headless_pkg/src/headless_node.py | 95 +++++++++++++++++++-------- 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/src/headless_pkg/src/headless_node.py b/src/headless_pkg/src/headless_node.py index 2ff7c32..f63a336 100755 --- a/src/headless_pkg/src/headless_node.py +++ b/src/headless_pkg/src/headless_node.py @@ -94,7 +94,7 @@ class Headless(Node): # Send one last zero control message self.core_publisher.publish(core_stop_msg) self.arm_publisher.publish(arm_stop_msg) - self.get_logger().info("Final stop command sent. Shutting down.") + self.get_logger().info("Final stop commands sent. Shutting down.") # Clean up pygame.quit() sys.exit(0) @@ -102,6 +102,7 @@ class Headless(Node): global ctrl_mode + # Check for control mode change dpad_input = self.gamepad.get_hat(0) if dpad_input[1] == 1: ctrl_mode = "arm" @@ -109,62 +110,102 @@ class Headless(Node): ctrl_mode = "core" + # CORE if ctrl_mode == "core": input = CoreControl() input.max_speed = max_speed - input.right_stick = -1 * round(self.gamepad.get_axis(4), 2) # right y-axis - if self.gamepad.get_axis(5) > 0: + + # Collect controller state + left_stick_y = deadzone(self.gamepad.get_axis(1)) + right_stick_y = deadzone(self.gamepad.get_axis(4)) + right_trigger = deadzone(self.gamepad.get_axis(5)) + + + # Right wheels + input.right_stick = round(-1 * right_stick_y, 2) + + # Left wheels + if right_trigger > 0: input.left_stick = input.right_stick else: - input.left_stick = -1 * round(self.gamepad.get_axis(1), 2) # left y-axis + input.left_stick = round(-1 * left_stick_y, 2) + + # Debug output = f'L: {input.left_stick}, R: {input.right_stick}, M: {max_speed}' self.get_logger().info(f"[Ctrl] {output}") + self.core_publisher.publish(input) self.arm_publisher.publish(arm_stop_msg) + + # ARM if ctrl_mode == "arm": input = ArmManual() + + # Collect controller state + left_stick_x = deadzone(self.gamepad.get_axis(0)) + left_stick_y = deadzone(self.gamepad.get_axis(1)) + left_trigger = deadzone(self.gamepad.get_axis(2)) + right_stick_x = deadzone(self.gamepad.get_axis(3)) + right_stick_y = deadzone(self.gamepad.get_axis(4)) + right_trigger = deadzone(self.gamepad.get_axis(5)) + right_bumper = self.gamepad.get_button(5) + dpad_input = self.gamepad.get_hat(0) - # Triggers for gripper control - if self.gamepad.get_axis(2) > 0:#left trigger + + # EF Grippers + if left_trigger > 0 and right_trigger > 0: + input.gripper = 0 + elif left_trigger > 0: input.gripper = -1 - elif self.gamepad.get_axis(5) > 0:#right trigger + elif right_trigger > 0: input.gripper = 1 - if self.gamepad.get_button(5):#right bumper, control effector + # Axis 0 + if dpad_input[0] == 1: + input.axis0 = 1 + elif dpad_input[0] == -1: + input.axis0 = -1 - # Left stick X-axis for effector yaw - if self.gamepad.get_axis(0) > 0: + + if right_bumper: # Control end effector + + # Effector yaw + if left_stick_x > 0: input.effector_yaw = 1 - elif self.gamepad.get_axis(0) < 0: + elif left_stick_x < 0: input.effector_yaw = -1 - # Right stick X-axis for effector roll - if self.gamepad.get_axis(3) > 0: + # Effector roll + if right_stick_x > 0: input.effector_roll = 1 - elif self.gamepad.get_axis(3) < 0: + elif right_stick_x < 0: input.effector_roll = -1 else: # Control arm axis - dpad_input = self.gamepad.get_hat(0) - input.axis0 = 0 - if dpad_input[0] == 1: - input.axis0 = 1 - elif dpad_input[0] == -1: - input.axis0 = -1 - if self.gamepad.get_axis(0) > .15 or self.gamepad.get_axis(0) < -.15: - input.axis1 = round(self.gamepad.get_axis(0)) + # Axis 1 + if abs(left_stick_x) > .15: + input.axis1 = round(left_stick_x) - if self.gamepad.get_axis(1) > .15 or self.gamepad.get_axis(1) < -.15: - input.axis2 = -1 * round(self.gamepad.get_axis(1)) + # Axis 2 + if abs(left_stick_y) > .15: + input.axis2 = -1 * round(left_stick_y) - if self.gamepad.get_axis(4) > .15 or self.gamepad.get_axis(4) < -.15: - input.axis3 = -1 * round(self.gamepad.get_axis(4)) + # Axis 3 + if abs(right_stick_y) > .15: + input.axis3 = -1 * round(right_stick_y) - self.arm_publisher.publish(input) self.core_publisher.publish(core_stop_msg) + self.arm_publisher.publish(input) + + +def deadzone(value: float, threshold=0.05) -> float: + if abs(value) < threshold: + return 0 + return value + def main(args=None): rclpy.init(args=args) From a0db7f62bc0916370672ef9c401dfd6e461ce31c Mon Sep 17 00:00:00 2001 From: David Date: Tue, 2 Sep 2025 02:56:50 -0500 Subject: [PATCH 7/8] refactor: move auto_start folder into rover-ros2 from home dir --- anchor.service | 2 +- core_headless.service | 2 +- headless_full.service | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/anchor.service b/anchor.service index 7b95062..b931e87 100644 --- a/anchor.service +++ b/anchor.service @@ -4,7 +4,7 @@ After=systemd-user-sessions.service Requires=systemd-user-sessions.service [Service] -ExecStart=/home/clucky/auto_start/auto_start_anchor.sh +ExecStart=/home/clucky/rover-ros2/auto_start/auto_start_anchor.sh Restart=always RestartSec=5 User=clucky diff --git a/core_headless.service b/core_headless.service index 035ba56..b43c9a3 100644 --- a/core_headless.service +++ b/core_headless.service @@ -4,7 +4,7 @@ After=systemd-user-sessions.service Requires=systemd-user-sessions.service [Service] -ExecStart=/home/clucky/auto_start/auto_start_core_headless.sh +ExecStart=/home/clucky/rover-ros2/auto_start/auto_start_core_headless.sh Restart=always RestartSec=10 User=clucky diff --git a/headless_full.service b/headless_full.service index ab79084..400438d 100644 --- a/headless_full.service +++ b/headless_full.service @@ -4,7 +4,7 @@ After=systemd-user-sessions.service Requires=systemd-user-sessions.service [Service] -ExecStart=/home/clucky/auto_start/auto_start_headless_full.sh +ExecStart=/home/clucky/rover-ros2/auto_start/auto_start_headless_full.sh Restart=always RestartSec=10 User=clucky From 5461fbab1125eb1506c7ca75666e2bd3f41d84ab Mon Sep 17 00:00:00 2001 From: David Date: Tue, 2 Sep 2025 12:24:38 -0500 Subject: [PATCH 8/8] fix: round() is not float ._. --- src/headless_pkg/src/headless_node.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/headless_pkg/src/headless_node.py b/src/headless_pkg/src/headless_node.py index f63a336..4094e60 100755 --- a/src/headless_pkg/src/headless_node.py +++ b/src/headless_pkg/src/headless_node.py @@ -122,13 +122,13 @@ class Headless(Node): # Right wheels - input.right_stick = round(-1 * right_stick_y, 2) + input.right_stick = float(round(-1 * right_stick_y, 2)) # Left wheels if right_trigger > 0: input.left_stick = input.right_stick else: - input.left_stick = round(-1 * left_stick_y, 2) + input.left_stick = float(round(-1 * left_stick_y, 2)) # Debug