0

I have made a similar question recently, but discovered many silly mistakes in the program. I am trying to add obstacle-avoidance to the Boids simulation while attempting to keep the behaviour as normal as possible. This is my algorithm so far:

def avoidcircle(self, circleobstacle):
    colliding = True
    while(colliding == True):
        newvector = pygame.math.Vector2(self.posvector[0] - circleobstacle.x, self.posvector[1] - circleobstacle.y)
        multiplythem = newvector.normalize().dot(self.velvector.normalize())
        a_angleinradian = math.acos(multiplythem)
        
        (Px, Py) = (self.posvector[0], self.posvector[1])
        (Cx, Cy) = (circleobstacle.x, circleobstacle.y)
        b = math.sqrt((Px - Cx)**2 + (Py - Cy)**2)
        theta = math.acos(circleobstacle.radius / b)        
        d = math.atan2(Py - Cy, Px - Cx) 
        d1 = d + theta
        d2 = d - theta
        
        T1x = Cx + circleobstacle.radius * math.cos(d1)
        T1y = Cy + circleobstacle.radius * math.sin(d1)
        T2x = Cx + circleobstacle.radius * math.cos(d2)
        T2y = Cy + circleobstacle.radius * math.sin(d2)
        
        newestbvector = pygame.math.Vector2(self.posvector[0] - T1x, self.posvector[1]- T1y)
        multiplythemagain = newestbvector.normalize().dot(newvector.normalize())
        b_angleinradian = math.acos(multiplythemagain)
        
        newestcvector = pygame.math.Vector2(self.posvector[0] - T2x, self.posvector[1] - T2y)
        multiplythemagain = newestcvector.normalize().dot(newvector.normalize())
        c_angleinradian = math.acos(multiplythemagain)
        
        if(a_angleinradian < b_angleinradian and a_angleinradian < c_angleinradian):
            #STEER THE BOID AWAY FROM TEH OBSTACLE BY SOME ANGLE
            #MAYBE CAN CHANGE VELOCITY BY SMALL ANGLE AND THEN RERUN ALL OF THE ABOVE CHECKING CODE UNTIL NO MORE COLLISION
            self.velvector = self.velvector.rotate(1)
            
            print("NOPE")
        else:
            colliding = False
            print("YEA")
            #RETURN THE NEW VELOCITY VECTOR.
            
    return self.velvector

will explain my method now: To avoid an obstacle, I first determine if the boid will collide with it if it continues to move in its current direction. To do this, I compute three angles. Angle a, which is the angle between the velocity and the vector joining the boid to the center of the obstacles, and angle b and c, which are the angles between the two tangents to the circle from the boid and the vector joining the boid do the obstacle's center.

Below is my simple obstacle class:

class CircularObstacle():
def __init__(self, x, y, radius): #MAYBE ADD A SIZE 
    self.x = x
    self.y = y
    self.radius = radius

The way I calculated the tangent to the circle was using an algorithm from this link: Find tangent points in a circle from a point

I am getting a ValueError: math domain error when the boids get too near (touching) the circle. I think it is because when I set theta = math.acos(circleobstacle.radius / b), b is so small that it makes circleobstacle.radius / b outside the domain of math.acos().

This algorithm has lots of problems:

  1. The error I described above
  2. The idea of just rotating the velocity until it is no longer going to collide with the obstacle does not yield the most efficient movement (might take the long way around an obstacle)
  3. The boids might be ignoring the obstacle before it even becomes important (too far away)

I would appreciate any help with this, and if it simply not a good method I welcome any other algorithms to try to have obstacle-avoiding behavior for a circular obstcle.

jbg05
  • 51
  • 7
  • we can't run it to see how it works - but you could use `print()` to see which part of code is executed and what you have in variables. It is called `"print debuginng"` and it helps ot see if code works as you expect. Or learn how to use real debuger. You could also display vectors on screen to see if they are correct. – furas Mar 06 '22 at 01:15
  • first you set `colliding = True`, next you check `while(colliding == False):` - so it will never execute this `while`. You should set `colliding = False` before `while`-loop. – furas Mar 06 '22 at 01:18

0 Answers0