Skip to content

Commit 228dec9

Browse files
committed
perf(flocking): improve tests
1 parent 5b08e0e commit 228dec9

1 file changed

Lines changed: 76 additions & 25 deletions

File tree

  • artificialintelligence/assignments/flocking

artificialintelligence/assignments/flocking/README.md

Lines changed: 76 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,19 @@
11
# Flocking agents behavior assignment
22

3-
You are in charge to implement some functions to make some AI agents flock together in a game.
3+
You are in charge to implement some functions to make some AI agents flock together in a game. After finishing it, uou will be one step further to render it in a game engine, and start making reactive NPCs and enemies. You will learn all the basics concepts needed to code and customize your own AI behaviors.
44

55
## What is flocking?
66

77
Flocking is a behavior that is observed in birds, fish and other animals that move in groups. It is a very simple behavior that can be implemented with a few lines of code. The idea is that each agent will try to move towards the center of mass of the group (cohesion), and will try to align its velocity with the average velocity of the group (AKA alignment). In addition, each agent will try to avoid collisions with other agents (AKA avoidance).
88

9-
In order to calculate the new position of the agent, we have to use some phisics formulas such as:
10-
11-
- $ \overrightarrow{F} = K_c*\hat{F_c} + K_s*\hat{F_s} + K_a*\hat{F_a} $
12-
- $ \overrightarrow{V_{new}} = \overrightarrow{V_{cur}}+\frac{\overrightarrow{F}}{m} \cdot \Delta t $
13-
- $ P_{new} = P_{cur}+\overrightarrow{V_{cur}} \cdot \Delta t + \frac{\overrightarrow{F}}{m} \cdot \frac{\Delta t^2}{2} $
14-
15-
!!! note "Notation"
9+
!!! note "Formal Notation Review"
1610

1711
- $\overrightarrow{F}$ means a vector $F$ that has components. In a 2 dimensional vector it will hold $F_x$ and $F_y$. For example, if $F_x = 1$ and $F_y = 1$, then $\overrightarrow{F} = (1,1)$
1812
- $\overrightarrow{P_1P_2}$ means the vector that goes from $P_1$ to $P_2$. It is the same as $P_2-P_1$
1913
- The modulus notation means the length (magnitude) of the vector. $|\overrightarrow{F}| = \sqrt{F_x^2+F_y^2}$ For example, if $\overrightarrow{F} = (1,1)$, then $|\overrightarrow{F}| = \sqrt{2}$
2014
- The hat ^ notation means the unitary vector of the vector. $\hat{F} = \frac{\overrightarrow{F}}{|\overrightarrow{F}|}$ For example, if $\overrightarrow{F} = (1,1)$, then $\hat{F} = (\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}})$
2115
- The hat notation over 2 points means the unit vector that goes from the first point to the second point. $\widehat{P_1P_2} = \frac{\overrightarrow{P_1P_2}}{|\overrightarrow{P_1P_2}|}$ For example, if $P_1 = (0,0)$ and $P_2 = (1,1)$, then $\widehat{P_1P_2} = (\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}})$
2216

23-
Where:
24-
25-
- $\overrightarrow{F}$ is the force applied to the agent;
26-
- $\overrightarrow{V}$ is the velocity of the agent;
27-
- $P$ is the position of the agent;
28-
- $m$ is the mass of the agent;
29-
- $\Delta t$ is the time frame (1/FPS);
30-
- $cur$ is the current value of the variable;
31-
- $new$ is the new value of the variable to be used in the next frame.
32-
33-
!!! note
34-
35-
For simplicity, we are going to assume that the mass of all agents is 1, and the time frame is 0.017s.
36-
3717
It is your job to implement those 3 behaviors following the ruleset below:
3818

3919
### Cohesion
@@ -56,6 +36,10 @@ F_c = \begin{cases}
5636
\end{cases}
5737
$$
5838

39+
!!! tip
40+
41+
Note that the maximum magnitude of $F_c$ is 1. Inclusive. This value can be multiplied by a constant $K_c$ to increase or decrease the cohesion force to looks more appealing.
42+
5943
### Separation
6044

6145
It will move the agent away from other agents when they get too close.
@@ -66,27 +50,75 @@ It will move the agent away from other agents when they get too close.
6650
4. Clamp the force to a maximum value of $F_{Smax}$.
6751

6852
$$
69-
F_s = \sum_{i=0}^{n-1} \begin{cases}
53+
\overrightarrow{F_s} = \sum_{i=0}^{n-1} \begin{cases}
7054
0 & \text{if } |\overrightarrow{AN_i}| = 0 \\
7155
\widehat{AN_i} / |\overrightarrow{AN_i}| & \text{if } 0 < |\overrightarrow{AN_i}| \leq r_s \\
7256
0 & \text{if } |\overrightarrow{AN_i}| > r_s
7357
\end{cases}
7458
$$
7559

76-
The force will go near infinite when the distance between the agent and the neighbor is 0. To avoid this, after accumulating all the influences from every neighbor, the force will be clamped to a maximum value of $F_{Smax}$.
60+
!!! tip
61+
62+
Here you can see that if we have more than one neighbor and one of them is way too close, the force will be very high and make the influence of the other neighbors irrelevant. This is the expected behavior.
63+
64+
The force will go near infinite when the distance between the agent and the neighbor is 0. To avoid this, after accumulating all the influences from every neighbor, the force will be clamped to a maximum magnitude of $F_{Smax}$.
65+
66+
$$
67+
\overrightarrow{F_{s}} = \begin{cases}
68+
\overrightarrow{F_s} & \text{if } |\overrightarrow{F_s}| \leq F_{Smax} \\
69+
\frac{\overrightarrow{F_s}}{|\overrightarrow{F_s}|} * F_{Smax} & \text{if } |\overrightarrow{F_s}| > F_{Smax}
70+
\end{cases}
71+
$$
72+
73+
!!! tip
74+
75+
- You can implement those two math together, but it is better to isolate in two steps to make it easier to understand and debug.
76+
- This is not an averaged force like the cohesion force, it is a sum of forces. So, the maximum magnitude of the force can be higher than 1.
7777

7878
### Alignment
7979

8080
It is the force that will align the velocity of the agent with the average velocity of the group.
8181

8282
1. The neighbors of an agent are all the agents that are within the alignment radius of the agent, including itself;
83-
2. Compute the average velocity of the group ($V_{avg}$);
83+
2. Compute the average velocity of the group ($\overrightarrow{V_{avg}}$);
8484
3. Compute the force that will move the agent towards the average velocity ($F_{alignment}$);
8585

8686
$$
8787
V_{avg} = \frac{\sum_{i=0}^{n-1} V_i}{n}
8888
$$
8989

90+
## Behavior composition
91+
92+
The force composition is made by a weighted sum of the influences of those 3 behaviors. This is the way we are going to work, this is not the only way to do it, nor the more correct. It is just a way to do it.
93+
94+
- $ \overrightarrow{F} = K_c*\overrightarrow{F_c} + K_s*\overrightarrow{F_s} + K_a*\overrightarrow{F_a} $ `This is a weighted sum!`
95+
- $ \overrightarrow{V_{new}} = \overrightarrow{V_{cur}} + \overrightarrow{F} \cdot \Delta t $ `This is a simplification!`
96+
- $ P_{new} = P_{cur}+\overrightarrow{V_{new}} \cdot \Delta t $ `This is an approximation!`
97+
98+
!!! warning
99+
100+
A more precise way for representing the new position would be to use full equations of motion. But given timestep is usually very small and it even squared, it is acceptable to ignore it. But here they are anyway, just dont use them in this assignment:
101+
102+
- $ \overrightarrow{V_{new}} = \overrightarrow{V_{cur}}+\frac{\overrightarrow{F}}{m} \cdot \Delta t $
103+
- $ P_{new} = P_{cur}+\overrightarrow{V_{cur}} \cdot \Delta t + \frac{\overrightarrow{F}}{m} \cdot \frac{\Delta t^2}{2} $
104+
105+
Where:
106+
107+
- $\overrightarrow{F}$ is the force applied to the agent;
108+
- $\overrightarrow{V}$ is the velocity of the agent;
109+
- $P$ is the position of the agent;
110+
- $m$ is the mass of the agent, here it is always 1;
111+
- $\Delta t$ is the time frame (1/FPS);
112+
- $cur$ is the current value of the variable;
113+
- $new$ is the new value of the variable to be used in the next frame.
114+
115+
The $\overrightarrow{V_{new}}$ and $P_{new}$ are the ones that will be used in the next frame and you will have to print to the console at the end of every single frame.
116+
117+
!!! note
118+
119+
- For simplicity, we are going to assume that the mass of all agents is 1.
120+
- In a real game simulation, it would be nice to apply some friction to the velocity of the agent to make it stop eventually or just clamp it to prevent the velocity get too high. But, for simplicity, we are going to ignore it.
121+
90122
## Input
91123

92124
The input consists in a list of parameters followed by a list of agents. The parameters are:
@@ -109,6 +141,25 @@ Every agent is represented by 4 values in the same line, separated by a space:
109141

110142
After reading the agents data, the program should read the time frame ($\Delta t$), simulate the agents and then output the new position of the agents in the same sequence and format it was read. The program should keep reading the time frame and simulating the agents until the end of the input.
111143

144+
### Input Example
145+
146+
In this example we are going to test only the cohesion behavior. The input is composed by the parameters and 2 agents.
147+
148+
```text
149+
1.000 0.000 0.000 0.000 1.000 0.000 0.000 2
150+
0.000 0.500 0.000 0.000
151+
0.000 -0.500 0.000 0.000
152+
0.010
153+
EOF
154+
```
155+
112156
## Output
113157

158+
The expected output are the position and velocity for each simulation step after the time frame. After printing each simulation step, the program should wait for the next time frame and then simulate the next step.
159+
160+
```text
161+
0.000 0.490 0.000 -0.010
162+
0.000 -0.490 0.000 0.010
163+
```
164+
114165
## Test cases

0 commit comments

Comments
 (0)