0
$\begingroup$

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.

Thanks in advance!

$\endgroup$
2
  • 1
    $\begingroup$ try this ... duckduckgo.com/?q=random+walk&ia=web $\endgroup$
    – jsotola
    Aug 8, 2022 at 16:16
  • $\begingroup$ @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. $\endgroup$
    – BiLLaKoS
    Aug 11, 2022 at 19:37

1 Answer 1

1
$\begingroup$

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:

Roomba paths

  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.

short random walk

long random walk

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)

    # cap turn radius
    if theta > np.pi * 3.0 / 4.0:
        theta = np.pi * 3.0 / 4.0
    if theta < np.pi / 4.0:
        theta = np.pi / 4.0
        
    left_vel = SPEED_SCALE * math.sin(theta) + math.cos(theta) / TURN_SCALE
    right_vel = SPEED_SCALE * math.sin(theta) - math.cos(theta) / TURN_SCALE
    
    return (left_vel, right_vel)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.