Skip to content

Commit fc3bc12

Browse files
(Merge this!) Drivetrain Safety Feature (#402)
* drivetrain safety feature * it works! --------- Co-authored-by: umnrobotics <robotics@umn.edu>
1 parent 2310108 commit fc3bc12

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

src/drivetrain/drivetrain/drivetrain_node.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
# Import ROS 2 formatted message types
1212
from geometry_msgs.msg import Twist
13-
from std_msgs.msg import Float64
13+
from std_msgs.msg import Float64, Float32
1414

1515
# Import custom ROS 2 interfaces
1616
from rovr_interfaces.srv import Drive, MotorCommandSet
@@ -30,6 +30,7 @@ def __init__(self):
3030
self.declare_parameter("GAZEBO_SIMULATION", False)
3131
self.declare_parameter("MAX_DRIVETRAIN_RPM", 10000)
3232
self.declare_parameter("DRIVETRAIN_TYPE", "velocity")
33+
self.declare_parameter("DIGGER_SAFETY_ZONE", 120) # Measured in potentiometer units (0 to 1023)
3334

3435
# Assign the ROS Parameters to member variables below #
3536
self.FRONT_LEFT_DRIVE = self.get_parameter("FRONT_LEFT_DRIVE").value
@@ -39,9 +40,11 @@ def __init__(self):
3940
self.GAZEBO_SIMULATION = self.get_parameter("GAZEBO_SIMULATION").value
4041
self.MAX_DRIVETRAIN_RPM = self.get_parameter("MAX_DRIVETRAIN_RPM").value
4142
self.DRIVETRAIN_TYPE = self.get_parameter("DRIVETRAIN_TYPE").value
43+
self.DIGGER_SAFETY_ZONE = self.get_parameter("DIGGER_SAFETY_ZONE").value
4244

4345
# Define publishers and subscribers here
4446
self.cmd_vel_sub = self.create_subscription(Twist, "cmd_vel", self.cmd_vel_callback, 10)
47+
self.lift_pose_subscription = self.create_subscription(Float32, "lift_pose", self.lift_pose_callback, 10)
4548

4649
if self.GAZEBO_SIMULATION:
4750
self.gazebo_front_left_wheel_pub = self.create_publisher(Float64, "front_left_wheel/cmd_vel", 10)
@@ -63,11 +66,20 @@ def __init__(self):
6366
self.get_logger().info("BACK_RIGHT_DRIVE has been set to: " + str(self.BACK_RIGHT_DRIVE))
6467
self.get_logger().info("GAZEBO_SIMULATION has been set to: " + str(self.GAZEBO_SIMULATION))
6568
self.get_logger().info("MAX_DRIVETRAIN_RPM has been set to: " + str(self.MAX_DRIVETRAIN_RPM))
69+
self.get_logger().info("DIGGER_SAFETY_ZONE has been set to: " + str(self.DIGGER_SAFETY_ZONE))
70+
71+
# Current position of the lift motor in potentiometer units (0 to 1023)
72+
self.current_lift_position = None # We don't know the current position yet
6673

6774
# Define subsystem methods here
6875
def drive(self, forward_power: float, turning_power: float) -> None:
6976
"""This method drives the robot with the desired forward and turning power."""
7077

78+
if self.current_lift_position is None or self.current_lift_position > self.DIGGER_SAFETY_ZONE:
79+
self.get_logger().warn("Digger outside the safety zone, cannot drive!")
80+
self.stop()
81+
return
82+
7183
# Clamp the values between -1 and 1
7284
forward_power = max(-1.0, min(forward_power, 1.0))
7385
turning_power = max(-1.0, min(turning_power, 1.0))
@@ -116,7 +128,18 @@ def drive(self, forward_power: float, turning_power: float) -> None:
116128

117129
def stop(self) -> None:
118130
"""This method stops the drivetrain."""
119-
self.drive(0.0, 0.0)
131+
self.cli_motor_set.call_async(
132+
MotorCommandSet.Request(can_id=self.FRONT_LEFT_DRIVE, type="duty_cycle", value=0.0)
133+
)
134+
self.cli_motor_set.call_async(
135+
MotorCommandSet.Request(can_id=self.BACK_LEFT_DRIVE, type="duty_cycle", value=0.0)
136+
)
137+
self.cli_motor_set.call_async(
138+
MotorCommandSet.Request(can_id=self.FRONT_RIGHT_DRIVE, type="duty_cycle", value=0.0)
139+
)
140+
self.cli_motor_set.call_async(
141+
MotorCommandSet.Request(can_id=self.BACK_RIGHT_DRIVE, type="duty_cycle", value=0.0)
142+
)
120143

121144
# Define service callback methods here
122145

@@ -137,6 +160,11 @@ def cmd_vel_callback(self, msg: Twist) -> None:
137160
"""This method is called whenever a message is received on the cmd_vel topic."""
138161
self.drive(msg.linear.x, msg.angular.z)
139162

163+
# Define the subscriber callback for the lift pose topic
164+
def lift_pose_callback(self, msg: Float32):
165+
# Average the two potentiometer values
166+
self.current_lift_position = msg.data
167+
140168

141169
def main(args=None):
142170
"""The main function."""

0 commit comments

Comments
 (0)