# Diff-drive robot - Obstacle avoiding - random walk

I have implemented a logic-based algorithm for obstacle avoidance in a differential drive robot with 5 IR sensors. I want the robot in space, for example, a square room, to move freely and avoid various obstacles and walls.

Below are samples of the code:

# False means no obstacles and True means obstacles in front.
def left_callback(self, msg):
self.L_Range = msg.range
self.action_array[0] = True if self.L_Range <= obstacle_avoider.ACTION_RANGE else False
self.avoid_obstacle()

def frontleft_callback(self, msg):
self.FL_Range = msg.range
self.action_array[1] = True if self.FL_Range <= obstacle_avoider.ACTION_RANGE else False
self.avoid_obstacle()

def front_callback(self, msg):
self.F_Range = msg.range
self.action_array[2] = True if self.F_Range <= obstacle_avoider.ACTION_RANGE else False
self.avoid_obstacle()

def frontright_callback(self, msg):
self.FR_Range = msg.range
self.action_array[3] = True if self.FR_Range <= obstacle_avoider.ACTION_RANGE else False
self.avoid_obstacle()

def right_callback(self, msg):
self.R_Range = msg.range
self.action_array[4] = True if self.R_Range <= obstacle_avoider.ACTION_RANGE else False
self.avoid_obstacle()

def avoid_obstacle(self):
# We have a primary and secondary array, the primary has the three front sensors, and the secondary has the rest two, right and left.
primary_array = self.action_array[1:4]
secondary_array = [self.action_array[0], self.action_array[4]]

if primary_array == [False, False, False]:
# Just Move Forward
self.velocity.linear.x = obstacle_avoider.MAX_SPEED
self.velocity.angular.z = 0

elif primary_array == [True, False, False]:
# Move Forward with Right Turn
self.velocity.linear.x = obstacle_avoider.MAX_SPEED
self.velocity.angular.z = obstacle_avoider.TURN_SPEED

elif primary_array == [False, False, True]:
# Move Forward with Left Turn
self.velocity.linear.x = obstacle_avoider.MAX_SPEED
self.velocity.angular.z = -1 * obstacle_avoider.TURN_SPEED

else:
# Stop Moving Forward
self.velocity.linear.x = obstacle_avoider.MIN_SPEED
if primary_array == [False, True, False]:
# Compare FL_Range and FR_Range
if self.FL_Range > self.FR_Range:
# Turn Left
self.velocity.angular.z = -1 * obstacle_avoider.TURN_SPEED

else:
# Turn Right
self.velocity.angular.z = obstacle_avoider.TURN_SPEED

elif primary_array == [True, True, False]:
# Turn Right
self.velocity.angular.z = obstacle_avoider.TURN_SPEED

elif primary_array == [False, True, True]:
# Turn Left
self.velocity.angular.z = -1 * obstacle_avoider.TURN_SPEED

else:
# Check Secondary
if secondary_array == [False, True]:
# Turn Left
self.velocity.angular.z = -1 * obstacle_avoider.TURN_SPEED

elif secondary_array == [True, False]:
# Turn Right
self.velocity.angular.z = obstacle_avoider.TURN_SPEED

else:
# Compare L_Range and R_Range
if self.L_Range > self.R_Range:
# Turn Left
self.velocity.angular.z = -1 * obstacle_avoider.TURN_SPEED

else:
# Turn Right
self.velocity.angular.z = obstacle_avoider.TURN_SPEED


I want to ask what a random walk is and how it can be used in this particular robot.

• try this ... duckduckgo.com/?q=random+walk&ia=web Aug 8, 2022 at 16:16
• @jsotola I couldn't find anything about it. I've been looking for three days but nothing! I can't understand how this algorithm works and how it differs from what I implemented. Aug 11, 2022 at 19:37

A random walk isn't an algorithm. It is a description of a random process.

If you want to inject some randomness into your robot code, here are a few ideas:

1. Drive straight, but when you hit an obstacle, turn in a random direction. This is kind of how old Roomba code worked. Given enough time, the robot will cover the entire area. (Maybe there is a proof of this somewhere in the random walk literature, but I'm not going to dig it up). Here is a time-lapse photo of a Roomba with a color changing LED on it:

1. Drive randomly. There are a few different ways to do this.

The naive implementation is to just put some random velocities on the wheels. This kind of works, but will probably produce jumpy or shakey behavior.

def get_vels():
left_vel = RANDOM_SCALE * (np.random.random() - 0.5) + SPEED
right_vel = RANDOM_SCALE * (np.random.random() - 0.5) + SPEED
return (left_vel, right_vel)


A slightly better way is to get a random speed delta:

left_vel = DEFAULT_VEL
right_vel = DEFAULT_VEL
def get_vels():
global left_vel
global right_vel

left_vel += RANDOM_SCALE * (np.random.random() - 0.5)
right_vel += RANDOM_SCALE * (np.random.random() - 0.5)

# cap wheel velocities
if left_vel < MIN_VEL:
left_vel = MIN_VEL
if right_vel < MIN_VEL:
right_vel = MIN_VEL
if left_vel > MAX_VEL:
left_vel = MAX_VEL
if right_vel > MAX_VEL:
right_vel = MAX_VEL

return (left_vel, right_vel)


This is still not ideal though because the robot may slow down and speed up. (For example if both wheels have minimum or maximum velocities at the same time).

This is a simulation I ran twice with the same parameters, for the same number of iterations. You can see that in the first the robot drove very far and straight, and in the second the robot covered very little distance.

Lastly, the method I prefer is to get a random vector to drive in, then convert that to left / right wheel commands.

theta = np.pi/2.0
def get_vels():
global theta

theta += RANDOM_SCALE * (np.random.random() - 0.5)