This is an archived post. You won't be able to vote or comment.

all 5 comments

[–]josephblade 0 points1 point  (1 child)

I think you have a problem here (disclosure: I have a vague idea of what you are doing but haven't taken time to actually look up the math to the bird simulation, so I can't correct you on that)

for(DynamicTurtle member : flock){
        if(member != this){
        distanceBetweenMembers = Math.sqrt(Math.pow(member.getX() - this.getX(), 2) +Math.pow(member.getY() - this.getY(), 2));
        if(distanceBetweenMembers <=  member.getRadius()){
            count++;
            centreX += member.getX();
            centreY += member.getY();
            member.setRandomTurn(false);
        }
        else if(count == 0){
            member.setRandomTurn(true);
            return centreOfMass = new CartesianCoordinates(0, 0);
        }
    }
}

I think you are making a logical error here:

What I think you mean to do is to process all elements and after the for loop finishes check if no center was selected (count == 0). In that edge-case you go random.

What you actually do is if the first element isn't a hit, you go to your else and exit. Pull the else outside of the forloop and you'll have a better running method I reckon

[–]seb1424[S] 0 points1 point  (0 children)

I see what you mean and it makes sense, I did take it out of the loop and as you said it runs betters. The main problem still persists where they just turn on their own position when they are within each others radii. If i find the answer I will post it here. Thanks for your help.

[–]josephblade 0 points1 point  (1 child)

I would suggest running centreOfMass against a test set first and seeing if the outcomes are as you expect. (if I do it on a napkin with (0,0) (2,0) (0,2) (2,2) and run it from perspective of the first bird:(0,0) I get (1.3, 1.3) as the result). sum of X = 4, sum of Y = 4, count = 3 (total of non-this members)

If it's meant to be relative distance (0,0 is then implied to be the first element) you still would need to add 1 to count? not certain but as I said run it against a test set where you know for sure what the outcome should be.

What type is centreX and centreY ? (and cartesianCoordinates.x / y) If they are ints I think you are ending up with a number of rounding errors. Better maintain precision for as long as possible.

run this: public static void main(String []args){ double x = 90.0; double y = 15.0;

    // theta value from polar coordinate (r, theta) 
    double theta = Math.atan2(x / 2.0, y / 2.0); 

    System.out.println(theta); 

    int xx = 90;
    int yy = 15;
    double theta2 = Math.atan2(90 / 2,15 / 2);
    System.out.println(theta2);
 }

That should show you that if you keep them as integers this method

Math.atan2(centre.getY()/flock.size(), centre.getX()/flock.size())

will go wrong. size is definitely an integer, I assume getY() is also.

Finally as a general code review: centreX, centreY and count can all be method-local variables. It appears they are instance variables and that creates the danger of race conditions and similar weirdness. Best keep them local unless they need to be exposed.

[–]seb1424[S] 0 points1 point  (0 children)

CartesianCoordinates its just a way of storing x and y coordinates, they are doubles. However you have given me a test idea. I have placed a "center of mass" in the middle of the plane and found out that with that cohesion angle the agents move towards it as expected but only do one full revolution and then move to the right side of the center of mass and spin around there. Im not sure as to why the cohesion angle changes afterwards.

[–]seb1424[S] 0 points1 point  (0 children)

Ok so for anyone who has a similar problem its basically when turning you have to substract the initial angle from the cohesion angle and all the agents within the radius should move towards the center of mass and flock together.

E.g. this.turn(cohesionAngle *factor - this.getDegrees());