Commit d996d91a authored by Inès EL HADRI's avatar Inès EL HADRI 💤

Smooth robot movement

parent c2771496
...@@ -16,12 +16,15 @@ class ReactiveMove(Node): ...@@ -16,12 +16,15 @@ class ReactiveMove(Node):
MAX_STUCK_TIME = 5 # Time before the robot is considered to be stuck and has to make a U-turn MAX_STUCK_TIME = 5 # Time before the robot is considered to be stuck and has to make a U-turn
# Rectangle of vision of the robot # Rectangle of vision of the robot
RECT_WIDTH = 0.5 RECT_WIDTH = 0.6
RECT_LENGTH = 0.5 RECT_LENGTH = 0.8
# Rectangle of speeds of the robot
MIN_DIST_MOVE_FORWARD = 0.3
MAX_DIST_MOVE_FORWARD = RECT_LENGTH
# Robot velocities # Robot velocities
ANGULAR_VELOCITY = 1.0 ANGULAR_VELOCITY = 1.0
LINEAR_VELOCITY = 0.2 LINEAR_VELOCITY = 0.3
def __init__(self, name="reactive_move", timerFreq = 1/60.0): def __init__(self, name="reactive_move", timerFreq = 1/60.0):
""" constructor """ """ constructor """
...@@ -39,8 +42,8 @@ class ReactiveMove(Node): ...@@ -39,8 +42,8 @@ class ReactiveMove(Node):
# Initialize variables # Initialize variables
self._timerFreq = timerFreq self._timerFreq = timerFreq
self._previousScanTime = None self._previousScanTime = None
self._previousStraightMvtTime = None
self._points = [] self._points = []
self._firstPointSeen = None
...@@ -63,32 +66,37 @@ class ReactiveMove(Node): ...@@ -63,32 +66,37 @@ class ReactiveMove(Node):
# If scan data received more than 1s ago, stop the robot # If scan data received more than 1s ago, stop the robot
if now - self._previousScanTime > 1: if now - self._previousScanTime > 1:
print("STOP ROBOT") print("No data received for more than 1s")
return Twist() # Return a zero velocity return Twist() # Return a zero velocity
# If it's been rotating for more than 5s, it's probably stuck in a corner
# In this case, a u-turn is performed, until >3.14s which is equivalent to a rotation of >180°
if self._previousStraightMvtTime and self.MAX_STUCK_TIME < now - self._previousStraightMvtTime <= self.MAX_STUCK_TIME + m.pi:
velo = Twist()
velo.angular.z = self.ANGULAR_VELOCITY
print("U-TURN")
return velo
# Default case # Default case
x, y = firstPointInFront(self._points, self.RECT_LENGTH, self.RECT_WIDTH / 2.0) x, y = firstPointInFront(self._points, self.RECT_LENGTH, self.RECT_WIDTH / 2.0)
if(not self._firstPointSeen): #If you were previously moving straight without obstacles
self._firstPointSeen = (x,y)
velocity = Twist() velocity = Twist()
if x and y: if x and y: # If there is a point in front at the moment
if y >= 0: # Point is in the left part of the rectangle -> Turn right
# Linear movement
if x < self.MIN_DIST_MOVE_FORWARD:
velocity.linear.x = 0.0 #If the wall is too close, don't go forward, only rotate
else:
coefficient = (x - self.MIN_DIST_MOVE_FORWARD) / (self.MAX_DIST_MOVE_FORWARD - self.MIN_DIST_MOVE_FORWARD) #linear between 0 (MIN_DIST_MOVE_FORWARD) and 1 (MAX_DIST_MOVE_FORWARD)
velocity.linear.x = coefficient * self.LINEAR_VELOCITY
# Rotation, based on the first point seen
firstY = self._firstPointSeen[1]
if firstY >= 0: # Point was in the left part of the rectangle -> Continue turning right until there is no point in front
velocity.angular.z = -self.ANGULAR_VELOCITY velocity.angular.z = -self.ANGULAR_VELOCITY
print("TURN RIGHT") else: # Point was in the right part of the rectangle -> Continue turning left until there is no point in front
else: # Point is in the right part of the rectangle -> Turn left
velocity.angular.z = self.ANGULAR_VELOCITY velocity.angular.z = self.ANGULAR_VELOCITY
print("TURN LEFT")
else: # If there's not point in front, go straight else: # If there's not point in front, go straight
velocity.linear.x = self.LINEAR_VELOCITY velocity.linear.x = self.LINEAR_VELOCITY
self._previousStraightMvtTime = now self._firstPointSeen = None
print("STRAIGHT")
return velocity return velocity
...@@ -119,11 +127,21 @@ def firstPointInFront(points:list, maxX, maxY): ...@@ -119,11 +127,21 @@ def firstPointInFront(points:list, maxX, maxY):
""" """
Check if points in front of the robot (in the rectangle with forward distance maxX and lateral distance of 2*maxY) Check if points in front of the robot (in the rectangle with forward distance maxX and lateral distance of 2*maxY)
""" """
# Closest point
cx, cy = None, None
closestDistance = 10000
for (x,y,_) in points: for (x,y,_) in points:
if(x>0 and x < maxX and abs(y) < maxY): pointDistance = m.sqrt(x**2 + y**2) #Get point distance to Lidar
return (x,y)
isInRectangle = x > 0 and x < maxX and abs(y) < maxY
isCloser = (cx is None) or (pointDistance < closestDistance)
if(isInRectangle and isCloser): #If the point is closer, store it as the new closest point in the rectangle
cx,cy = x,y
closestDistance = pointDistance
return (None, None) return (cx, cy)
# Main loop # Main loop
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment