I find the solution to a problem found in an XKCD comic involving raptors attacking a human. The goal was to find the optimal action for a human who is surrounded by three raptors positioned in an equilateral triangle. The problem appears in an XKCD comic at https://xkcd.com/135/.

Question 2

Let the human position be $\boldsymbol{h}(t) \in \mathbb{R}^2$ and a raptor’s position $\boldsymbol{r}(t) \in \mathbb{R}^2$.

A raptor’s motion can be modeled as

\[\frac{d \boldsymbol{r}}{dt} = v_r \frac{\boldsymbol{h}(t)-\boldsymbol{r}(t)}{|\boldsymbol{h}(t)-\boldsymbol{r}(t)|} \text{ } (Eq. 1)\]

where if $\boldsymbol{x}=(x,y)$ then we define $\vert \boldsymbol{x}\vert = \sqrt{x^2+y^2}$.

The three raptor’s each satisfy this ODE separately, but the $x$ and $y$ components of a raptor’s motion are coupled, so we have 2-dimensional ODEs.

For simplicity, we assume the human runs in a constant direction and at a constant speed. Thus,

\[\boldsymbol{h}(t) = v_ht\frac{\boldsymbol{c}}{| \boldsymbol{c}|}+ \boldsymbol{h}(0) \text{ } (Eq. 2)\]

where $\boldsymbol{c} \in \mathbb{R}^2$ is an initial direction and $\boldsymbol{h}(0)$ is the human’s initial position.

We substitute $\boldsymbol{h}(t)$ into equation (1) to obtain $\frac{d \boldsymbol{r}}{dt}=F(t, \boldsymbol{r})$ for some function F (to be defined).

As in the comic, the human is at the center of an equilateral triangle with 20m sidelengths. The human has a top speed of $v_h=6$ m/s. The healthy raptors have a top speed of $v_r=25$ m/s. We’ll assume the injured raptor can run at 20 m/s to make the problem more interesting.

Define the human as “caught” when the raptor is within 0.01 m of the human. Specifically, assume the human starts running at a $56^{\circ}$ angle above the horizontal.

We have $\boldsymbol{h}(0)=(0,0)$ since the human starts at the origin. $v_h=6$, the (max) velocity of the human.

To determine $\boldsymbol{c}$ we have $y=6\sin(56)\approx 4.974$ and $x=6 \cos(56) \approx 3.355$.

\(c= (3.355,4.974)\) so \(|c|= \sqrt{3.355^2+4.974^2}=6\)

Thus, $\boldsymbol{h}(t) = 6t\frac{(3.355,4.974)}{6} = (3.355t,4.974t)$.

So Equation (1) becomes \(\frac{d \boldsymbol{r}}{dt} = F(t, \boldsymbol{r}) = v_r \frac{(3.355t,4.974t)- \boldsymbol{r}(t)}{|(3.355t,4.974t)- \boldsymbol{r}(t)|}\)


import numpy as np
import scipy.integrate
import scipy.interpolate
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

h = lambda t: (3.355*t,4.974*t)

#dr/dt
v_r1 = 20 #velocity of raptor 1
F1 = lambda t,r: v_r1*((3.355*t,4.974*t)-r)/np.sqrt((3.355*t-r[0])**2+(4.974*t-r[1])**2)
v_r = 25 #velocity of uninjured raptor
F = lambda t,r: v_r*((3.355*t,4.974*t)-r)/np.sqrt((3.355*t-r[0])**2+(4.974*t-r[1])**2)

tStart= 0.0
tStop = 5.0
tspan= (tStart, tStop)

r1 = (0,11.547)
r2 = (10,-5.7735)
r3 = (-10,-5.7735)
raptor1 = solve_ivp(F1, tspan, r1, dense_output=True)
raptor2 = solve_ivp(F, tspan, r2, dense_output=True)
raptor3 = solve_ivp(F, tspan, r3, dense_output=True)
print('Success status of IVP solver is: ', raptor1.success)

t = np.linspace(0,1,2000)
# make variable arrays less confusing, do this for each raptor
t_r1 = t
x_r1 = raptor1.sol(t)[0,:]
y_r1 = raptor1.sol(t)[1,:]
...

# Find time human is "caught" by each raptor
def distanceFormula(x1,y1,x2,y2):
    xdiff = np.subtract(x2,x1)
    ydiff = np.subtract(y2,y1)
    distance = np.sqrt(xdiff**2+ydiff**2)
    return distance #this is an nd.array

def raptorEatsHuman(distanceBetween):
    if any(element < 0.01 for element in distanceBetween):
        for element in distanceBetween:
            if element<0.01:
                idx, =  np.where(np.isclose(distanceBetween, element))
#                 timeCaught = float(time[idx])
                return idx #this is a float
    return("Failed.")

# Time Raptor 1 Catches Human, do this for each raptor
x_h1 = h(t_r1)[0]
y_h1 = h(t_r1)[1]
R1_distanceBetween = distanceFormula(x_h1,y_h1, x_r1, y_r1)
index1 = int(raptorEatsHuman(R1_distanceBetween))
timeCaught1 = float(t_r1[index1])
...

timeCaught = np.array([timeCaught1, timeCaught2, timeCaught3])
for i in np.arange(1,4):
    print( f'Time caught by raptor{i:2d}, t = {timeCaught[i-1]:.16}' )
Time caught by raptor 1, t = 0.4772386193096548
Time caught by raptor 2, t = 0.4827413706853426
Time caught by raptor 3, t = 0.6068034017008503
SOLUTION:

Dinosaur Attack Q2 Solution

The human is caught by the injured raptor at t = min(timeCaught) = 0.4772386193096548

If the human starts in the center of the triangle and runs at a 56 degree angle above the horizontal, the injured raptor reaches the human first at 𝑡≈0.477 seconds.

Additional interesting questions to consider: 
Optimize the angle for this problem. 
For which top speed of the wounded raptor does the optimal strategy become to run straight at the wounded raptor?