diff --git a/lynx_description/urdf/lynx_macro.urdf.xacro b/lynx_description/urdf/lynx_macro.urdf.xacro
index 8443fe58..4e1fdf17 100644
--- a/lynx_description/urdf/lynx_macro.urdf.xacro
+++ b/lynx_description/urdf/lynx_macro.urdf.xacro
@@ -61,8 +61,8 @@
true
-
- panther_hardware_interfaces/PantherSystem
+
+ panther_hardware_interfaces/LynxSystem
1600
@@ -77,8 +77,7 @@
panther_can
3
- 1
- 2
+ 1
100
+Since some of the tests create and access a virtual CAN interface, it is necessary to install `kmod` and `iproute2`.
```bash
-sudo modprobe vcan
-sudo ip link add dev panther_can type vcan
-sudo ip link set up panther_can
-sudo ip link set panther_can down
-sudo ip link set panther_can txqueuelen 1000
-sudo ip link set panther_can up
+sudo apt update
+sudo apt install -y kmod iproute2
```
### Running tests
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/lynx_system.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/lynx_system.hpp
new file mode 100644
index 00000000..b5927e59
--- /dev/null
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/lynx_system.hpp
@@ -0,0 +1,60 @@
+// Copyright 2024 Husarion sp. z o.o.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_LYNX_SYSTEM_HPP_
+#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_LYNX_SYSTEM_HPP_
+
+#include
+#include
+
+#include "panther_hardware_interfaces/panther_system/ugv_system.hpp"
+
+namespace panther_hardware_interfaces
+{
+
+/**
+ * @brief Class that implements UGVSystem for Lynx robot
+ */
+class LynxSystem : public UGVSystem
+{
+public:
+ RCLCPP_SHARED_PTR_DEFINITIONS(LynxSystem)
+
+ LynxSystem() : UGVSystem(kJointOrder) {}
+
+ ~LynxSystem() = default;
+
+protected:
+ void ReadCANopenSettingsDriverCANIDs() override;
+
+ virtual void DefineRobotDriver() override; // virtual for testing
+
+ void UpdateHwStates() override;
+ void UpdateMotorsStateDataTimedOut() override;
+
+ void UpdateDriverStateMsg() override;
+ void UpdateFlagErrors() override;
+ void UpdateDriverStateDataTimedOut() override;
+
+ std::vector GetSpeedCommands() const;
+
+ void DiagnoseErrors(diagnostic_updater::DiagnosticStatusWrapper & status) override;
+ void DiagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper & status) override;
+
+ static const inline std::vector kJointOrder = {"fl", "fr", "rl", "rr"};
+};
+
+} // namespace panther_hardware_interfaces
+
+#endif // PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_LYNX_SYSTEM_HPP_
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system.hpp
index 373ff0ee..80cf06bb 100644
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system.hpp
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system.hpp
@@ -15,141 +15,44 @@
#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_HPP_
#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_HPP_
-#include
-#include
-#include
#include
#include
-#include "diagnostic_updater/diagnostic_status_wrapper.hpp"
-#include "rclcpp/rclcpp.hpp"
-#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
-#include "rclcpp_lifecycle/state.hpp"
-
-#include "hardware_interface/handle.hpp"
-#include "hardware_interface/system_interface.hpp"
-#include "hardware_interface/types/hardware_interface_return_values.hpp"
-
-#include "panther_hardware_interfaces/panther_system/gpio/gpio_controller.hpp"
-#include "panther_hardware_interfaces/panther_system/motors_controller/motors_controller.hpp"
-#include "panther_hardware_interfaces/panther_system/motors_controller/roboteq_error_filter.hpp"
-#include "panther_hardware_interfaces/panther_system/panther_system_e_stop.hpp"
-#include "panther_hardware_interfaces/panther_system/panther_system_ros_interface.hpp"
+#include "panther_hardware_interfaces/panther_system/ugv_system.hpp"
namespace panther_hardware_interfaces
{
-using return_type = hardware_interface::return_type;
-using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
-using StateInterface = hardware_interface::StateInterface;
-using CommandInterface = hardware_interface::CommandInterface;
-
/**
- * @brief Class that implements SystemInterface from ros2_control for Panther
+ * @brief Class that implements UGVSystem for Panther robot
*/
-class PantherSystem : public hardware_interface::SystemInterface
+class PantherSystem : public UGVSystem
{
public:
RCLCPP_SHARED_PTR_DEFINITIONS(PantherSystem)
- CallbackReturn on_init(const hardware_interface::HardwareInfo & hardware_info) override;
- CallbackReturn on_configure(const rclcpp_lifecycle::State & previous_state) override;
- CallbackReturn on_cleanup(const rclcpp_lifecycle::State & previous_state) override;
- CallbackReturn on_activate(const rclcpp_lifecycle::State & previous_state) override;
- CallbackReturn on_deactivate(const rclcpp_lifecycle::State & previous_state) override;
- CallbackReturn on_shutdown(const rclcpp_lifecycle::State & previous_state) override;
- CallbackReturn on_error(const rclcpp_lifecycle::State & previous_state) override;
+ PantherSystem() : UGVSystem(kJointOrder) {}
- std::vector export_state_interfaces() override;
- std::vector export_command_interfaces() override;
-
- return_type read(const rclcpp::Time & time, const rclcpp::Duration & /* period */) override;
- return_type write(
- const rclcpp::Time & /* time */, const rclcpp::Duration & /* period */) override;
+ ~PantherSystem() = default;
protected:
- void CheckJointSize() const;
- void SortAndCheckJointNames();
- void SetInitialValues();
- void CheckInterfaces() const;
- void ReadPantherVersion();
- void ReadDrivetrainSettings();
- void ReadCANopenSettings();
- void ReadInitializationActivationAttempts();
- void ReadParametersAndCreateRoboteqErrorFilter();
- void ReadDriverStatesUpdateFrequency();
-
- void ConfigureGPIOController();
- void ConfigureMotorsController();
- void ConfigureEStop();
-
- void UpdateMotorsState();
- void UpdateDriverState();
- void UpdateEStopState();
-
- void UpdateHwStates();
- void UpdateMotorsStateDataTimedOut();
- bool AreVelocityCommandsNearZero();
-
- void UpdateDriverStateMsg();
- void UpdateFlagErrors();
- void UpdateDriverStateDataTimedOut();
-
- void HandlePDOWriteOperation(std::function pdo_write_operation);
-
- void MotorsPowerEnable(const bool enable);
-
- void DiagnoseErrors(diagnostic_updater::DiagnosticStatusWrapper & status);
- void DiagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper & status);
-
- static constexpr size_t kJointsSize = 4;
-
- // Currently only velocity command mode is supported - although Roboteq driver support position
- // and torque mode, in 2.1 firmware both modes aren't really stable and safe.
- // In torque mode sometimes after killing the software motor moves and it generally isn't well
- // tuned. Position mode also isn't really stable (reacts abruptly to spikes). If updating the
- // firmware to 2.1a will solve these issues, it may be worth to enable other modes.
- std::array hw_commands_velocities_;
-
- std::array hw_states_positions_;
- std::array hw_states_velocities_;
- std::array hw_states_efforts_;
-
- // Define expected joint order, so that it doesn't matter what order is defined in the URDF.
- // It is expected that the joint name should contain these specifiers.
- static const inline std::array joint_order_ = {"fl", "fr", "rl", "rr"};
- std::array joints_names_sorted_;
-
- std::shared_ptr gpio_controller_;
- std::shared_ptr motors_controller_;
- std::shared_ptr e_stop_;
-
- DrivetrainSettings drivetrain_settings_;
- CANopenSettings canopen_settings_;
-
- std::unique_ptr panther_system_ros_interface_;
+ void ReadCANopenSettingsDriverCANIDs() override;
- // Sometimes SDO errors can happen during initialization and activation of Roboteq drivers,
- // in these cases it is better to retry
- // Example errors:
- // SDO abort code 05040000 received on upload request of object 1000 (Device type) to
- // node 02: SDO protocol timed out
- // SDO abort code 05040000 received on upload request of sub-object 1018:01 (Vendor-ID) to
- // node 02: SDO protocol timed out
- unsigned max_roboteq_initialization_attempts_;
- unsigned max_roboteq_activation_attempts_;
+ virtual void DefineRobotDriver() override; // virtual for testing
- rclcpp::Logger logger_{rclcpp::get_logger("PantherSystem")};
- rclcpp::Clock steady_clock_{RCL_STEADY_TIME};
+ void UpdateHwStates() override;
+ void UpdateMotorsStateDataTimedOut() override;
- std::shared_ptr roboteq_error_filter_;
+ void UpdateDriverStateMsg() override;
+ void UpdateFlagErrors() override;
+ void UpdateDriverStateDataTimedOut() override;
- float panther_version_;
+ std::vector GetSpeedCommands() const;
- std::shared_ptr motor_controller_write_mtx_;
+ void DiagnoseErrors(diagnostic_updater::DiagnosticStatusWrapper & status) override;
+ void DiagnoseStatus(diagnostic_updater::DiagnosticStatusWrapper & status) override;
- rclcpp::Time next_driver_state_update_time_{0, 0, RCL_ROS_TIME};
- rclcpp::Duration driver_states_update_period_{0, 0};
+ static const inline std::vector kJointOrder = {"fl", "fr", "rl", "rr"};
};
} // namespace panther_hardware_interfaces
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_e_stop.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_e_stop.hpp
deleted file mode 100644
index 146bd909..00000000
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_e_stop.hpp
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2024 Husarion sp. z o.o.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_E_STOP_HPP_
-#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_E_STOP_HPP_
-
-#include
-#include
-#include
-
-#include "panther_hardware_interfaces/panther_system/gpio/gpio_controller.hpp"
-#include "panther_hardware_interfaces/panther_system/motors_controller/motors_controller.hpp"
-#include "panther_hardware_interfaces/panther_system/motors_controller/roboteq_error_filter.hpp"
-
-namespace panther_hardware_interfaces
-{
-
-/**
- * @class EStopInterface
- * @brief Abstract base class defining the interface for emergency stop detailed implementations.
- */
-class EStopInterface
-{
-public:
- EStopInterface(
- std::shared_ptr gpio_controller,
- std::shared_ptr roboteq_error_filter,
- std::shared_ptr motors_controller,
- std::shared_ptr motor_controller_write_mtx,
- std::function zero_velocity_check)
- : gpio_controller_(gpio_controller),
- roboteq_error_filter_(roboteq_error_filter),
- motors_controller_(motors_controller),
- motor_controller_write_mtx_(motor_controller_write_mtx),
- ZeroVelocityCheck(zero_velocity_check) {};
-
- virtual ~EStopInterface() = default;
-
- virtual bool ReadEStopState() = 0;
- virtual void TriggerEStop() = 0;
- virtual void ResetEStop() = 0;
-
-protected:
- std::shared_ptr gpio_controller_;
- std::shared_ptr roboteq_error_filter_;
- std::shared_ptr motors_controller_;
- std::shared_ptr motor_controller_write_mtx_;
-
- std::function ZeroVelocityCheck;
-
- std::mutex e_stop_manipulation_mtx_;
- std::atomic_bool e_stop_triggered_ = true;
-};
-
-/**
- * @class EStopPTH12X
- * @brief Implements the emergency stop for the PTH12X hardware variant.
- */
-class EStopPTH12X : public EStopInterface
-{
-public:
- EStopPTH12X(
- std::shared_ptr gpio_controller,
- std::shared_ptr roboteq_error_filter,
- std::shared_ptr motors_controller,
- std::shared_ptr motor_controller_write_mtx,
- std::function zero_velocity_check)
- : EStopInterface(
- gpio_controller, roboteq_error_filter, motors_controller, motor_controller_write_mtx,
- zero_velocity_check) {};
-
- virtual ~EStopPTH12X() override = default;
-
- /**
- * @brief Checks the emergency stop state.
- *
- * 1. Check if ESTOP GPIO pin is not active. If is not it means that E-Stop is triggered by
- * another device within the robot's system (e.g., Roboteq controller or Safety Board),
- * disabling the software Watchdog is necessary to prevent an uncontrolled reset.
- * 2. If there is a need, disable software Watchdog using
- * GPIOControllerInterface::EStopTrigger method.
- * 3. Return ESTOP GPIO pin state.
- */
- bool ReadEStopState() override;
-
- /**
- * @brief Triggers the emergency stop.
- *
- * 1. Interrupt the E-Stop resetting process if it is in progress.
- * 2. Attempt to trigger the E-Stop using GPIO by disabling the software-controlled watchdog.
- * 3. If successful, set e_stop_triggered_ to true; otherwise, throw a std::runtime_error
- * exception.
- *
- * @throws std::runtime_error if triggering the E-stop using GPIO fails.
- */
- void TriggerEStop() override;
-
- /**
- * @brief Resets the emergency stop.
- *
- * 1. Verify that the last velocity commands are zero to prevent an uncontrolled robot movement
- * after an E-stop state change.
- * 2. Attempt to reset the E-Stop using GPIO by manipulating the ESTOP GPIO pin. This operation
- * may take some time and can be interrupted by the E-Stop trigger process.
- * 3. Set the clear_error flag to allow for clearing of Roboteq errors.
- * 4. Confirm the E-Stop reset was successful with the ReadEStopState method.
- *
- * @throws EStopResetInterrupted if the E-stop reset operation was halted because the E-stop was
- * triggered again.
- * @throws std::runtime_error if an error occurs when trying to reset the E-stop using GPIO.
- */
- void ResetEStop() override;
-};
-
-/**
- * @class EStopPTH10X
- * @brief Implements the emergency stop for the PTH10X hardware variant. In this robot
- * version, only a software-based E-Stop is supported. There are no hardware components that
- * implement E-Stop functionality.
- */
-class EStopPTH10X : public EStopInterface
-{
-public:
- EStopPTH10X(
- std::shared_ptr gpio_controller,
- std::shared_ptr roboteq_error_filter,
- std::shared_ptr motors_controller,
- std::shared_ptr motor_controller_write_mtx,
- std::function zero_velocity_check)
- : EStopInterface(
- gpio_controller, roboteq_error_filter, motors_controller, motor_controller_write_mtx,
- zero_velocity_check) {};
-
- virtual ~EStopPTH10X() override = default;
-
- /**
- * @brief Checks the emergency stop state.
- *
- * 1. Verify if the main switch is in the STAGE2 position to confirm if the motors are powered
- * up.
- * 2. Check for any errors reported by the Roboteq controller.
- * 3. If the E-Stop is not currently triggered, initiate an E-Stop if the motors are not powered
- * up or if a driver error has occurred.
- * 4. Return the actual state of the E-Stop.
- *
- * @return A boolean indicating whether the E-Stop is currently triggered `true` or not `false`.
- */
- bool ReadEStopState() override;
-
- /**
- * @brief Trigger the emergency stop state.
- *
- * 1. Send a command to the Roboteq controllers to enable the Safety Stop.
- * Note: The Safety Stop is a specific state of the Roboteq controller, distinct from
- * the E-Stop state of the Panther robot.
- * 2. Update the e_stop_triggered_ flag to indicate that the E-Stop state has been triggered.
- */
- void TriggerEStop() override;
-
- /**
- * @brief Resets the emergency stop.
- *
- * 1. Verify that the last velocity commands are zero to prevent an uncontrolled robot movement
- * after an E-stop state change.
- * 2. Verify if the main switch is in the STAGE2 position to confirm if the motors are powered
- * up.
- * 3. Check for any errors reported by the Roboteq controller.
- * 4. Set the clear_error flag to allow for clearing of Roboteq errors.
- * 5. Confirm the E-Stop reset was successful with the ReadEStopState method.
- * 6. Update the e_stop_triggered_ flag to indicate that the E-Stop state has been triggered.
- *
- * @throws std::runtime_error if the E-stop reset operation was halted because the E-stop was
- * triggered again, motors are not powered or motor controller is in an error state.
- */
- void ResetEStop() override;
-};
-
-} // namespace panther_hardware_interfaces
-
-#endif // PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_E_STOP_HPP_
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/lynx_robot_driver.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/lynx_robot_driver.hpp
index 6449d7c6..25b61114 100644
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/lynx_robot_driver.hpp
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/lynx_robot_driver.hpp
@@ -63,7 +63,7 @@ class LynxRobotDriver : public RoboteqRobotDriver
* @brief This method defines driver objects and adds motor drivers for them. It is virtual to
* allow mocking drivers in tests.
*/
- virtual void DefineDrivers();
+ void DefineDrivers() override;
};
} // namespace panther_hardware_interfaces
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/robot_driver.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/robot_driver.hpp
index bccd1f64..78e38064 100644
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/robot_driver.hpp
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/robot_driver.hpp
@@ -107,6 +107,13 @@ class RobotDriverInterface
* the error flags should remain active.
*/
virtual void AttemptErrorFlagReset() = 0;
+
+ /**
+ * @brief Check if communication with drivers is working properly
+ *
+ * @return true if communication error occurred
+ */
+ virtual bool CommunicationError() = 0;
};
} // namespace panther_hardware_interfaces
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/roboteq_robot_driver.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/roboteq_robot_driver.hpp
index 3d4e8440..6f872307 100644
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/roboteq_robot_driver.hpp
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/robot_driver/roboteq_robot_driver.hpp
@@ -132,6 +132,8 @@ class RoboteqRobotDriver : public RobotDriverInterface
*/
const DriverData & GetData(const std::string & name) override;
+ bool CommunicationError() override;
+
protected:
/**
* @brief This method defines driver objects and adds motor drivers for them.
@@ -156,6 +158,7 @@ class RoboteqRobotDriver : public RobotDriverInterface
bool DataTimeout(
const timespec & current_time, const timespec & data_timestamp,
const std::chrono::milliseconds & timeout);
+ void BootDrivers();
bool initialized_ = false;
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_e_stop.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_e_stop.hpp
new file mode 100644
index 00000000..a0d1088e
--- /dev/null
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_e_stop.hpp
@@ -0,0 +1,120 @@
+// Copyright 2024 Husarion sp. z o.o.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_SYSTEM_E_STOP_HPP_
+#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_SYSTEM_E_STOP_HPP_
+
+#include
+#include
+#include
+
+#include "panther_hardware_interfaces/panther_system/gpio/gpio_controller.hpp"
+#include "panther_hardware_interfaces/panther_system/robot_driver/robot_driver.hpp"
+#include "panther_hardware_interfaces/panther_system/robot_driver/roboteq_error_filter.hpp"
+
+namespace panther_hardware_interfaces
+{
+
+/**
+ * @class EStopInterface
+ * @brief Abstract base class defining the interface for emergency stop detailed implementations.
+ */
+class EStopInterface
+{
+public:
+ EStopInterface() {}
+
+ virtual ~EStopInterface() = default;
+
+ virtual bool ReadEStopState() = 0;
+ virtual void TriggerEStop() = 0;
+ virtual void ResetEStop() = 0;
+};
+
+/**
+ * @class EStop
+ * @brief Implements the emergency stop interface.
+ */
+class EStop : public EStopInterface
+{
+public:
+ EStop(
+ std::shared_ptr gpio_controller,
+ std::shared_ptr roboteq_error_filter,
+ std::shared_ptr robot_driver,
+ std::shared_ptr robot_driver_write_mtx, std::function zero_velocity_check)
+ : EStopInterface(),
+ gpio_controller_(gpio_controller),
+ roboteq_error_filter_(roboteq_error_filter),
+ robot_driver_(robot_driver),
+ robot_driver_write_mtx_(robot_driver_write_mtx),
+ ZeroVelocityCheck(zero_velocity_check) {};
+
+ virtual ~EStop() override = default;
+
+ /**
+ * @brief Checks the emergency stop state.
+ *
+ * 1. Check if ESTOP GPIO pin is not active. If is not it means that E-Stop is triggered by
+ * another device within the robot's system (e.g., Roboteq controller or Safety Board),
+ * disabling the software Watchdog is necessary to prevent an uncontrolled reset.
+ * 2. If there is a need, disable software Watchdog using
+ * GPIOControllerInterface::EStopTrigger method.
+ * 3. Return ESTOP GPIO pin state.
+ */
+ bool ReadEStopState() override;
+
+ /**
+ * @brief Triggers the emergency stop.
+ *
+ * 1. Interrupt the E-Stop resetting process if it is in progress.
+ * 2. Attempt to trigger the E-Stop using GPIO by disabling the software-controlled watchdog.
+ * 3. If successful, set e_stop_triggered_ to true; otherwise, throw a std::runtime_error
+ * exception.
+ *
+ * @throws std::runtime_error if triggering the E-stop using GPIO fails.
+ */
+ void TriggerEStop() override;
+
+ /**
+ * @brief Resets the emergency stop.
+ *
+ * 1. Verify that the last velocity commands are zero to prevent an uncontrolled robot movement
+ * after an E-stop state change.
+ * 2. Attempt to reset the E-Stop using GPIO by manipulating the ESTOP GPIO pin. This operation
+ * may take some time and can be interrupted by the E-Stop trigger process.
+ * 3. Set the clear_error flag to allow for clearing of Roboteq errors.
+ * 4. Confirm the E-Stop reset was successful with the ReadEStopState method.
+ *
+ * @throws EStopResetInterrupted if the E-stop reset operation was halted because the E-stop was
+ * triggered again.
+ * @throws std::runtime_error if an error occurs when trying to reset the E-stop using GPIO.
+ */
+ void ResetEStop() override;
+
+protected:
+ std::shared_ptr gpio_controller_;
+ std::shared_ptr roboteq_error_filter_;
+ std::shared_ptr robot_driver_;
+ std::shared_ptr robot_driver_write_mtx_;
+
+ std::function ZeroVelocityCheck;
+
+ std::mutex e_stop_manipulation_mtx_;
+ std::atomic_bool e_stop_triggered_ = true;
+};
+
+} // namespace panther_hardware_interfaces
+
+#endif // PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_SYSTEM_E_STOP_HPP_
diff --git a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_ros_interface.hpp b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_ros_interface.hpp
similarity index 85%
rename from panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_ros_interface.hpp
rename to panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_ros_interface.hpp
index ca04943d..856d4b72 100644
--- a/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/panther_system_ros_interface.hpp
+++ b/panther_hardware_interfaces/include/panther_hardware_interfaces/panther_system/system_ros_interface.hpp
@@ -12,30 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_ROS_INTERFACE_HPP_
-#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_PANTHER_SYSTEM_ROS_INTERFACE_HPP_
+#ifndef PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_SYSTEM_ROS_INTERFACE_HPP_
+#define PANTHER_HARDWARE_INTERFACES_PANTHER_SYSTEM_SYSTEM_ROS_INTERFACE_HPP_
#include
-#include
#include
+#include