2D¶
Parametric¶
V = socialforce.potentials.PedPedPotential2D(asymmetry=-1.0)
with socialforce.show.canvas(figsize=(12, 6), ncols=2) as (ax1, ax2):
socialforce.show.potential_2d(V, ax1)
socialforce.show.potential_2d_grad(V, ax2)

Asymmetry¶
We use a multiplicative function to make a symmetric potential asymmetric. Qualitativly, we would like an exponential function, but one that does not grow exponentially at large distances. We use a softplus function normalized such that it is one at the origin:
(9)¶\[\begin{align}
f_\textrm{asymmetry}(x_{\perp}) &= \frac{1}{\ln 2} \ln(1 + \exp(\textrm{asymmetry} \cdot x_{\perp}))
\end{align}\]
# HIDE CODE
asymmetry_factor = socialforce.potentials.PedPedPotential2D.asymmetry_factor
x = torch.linspace(-5, 5, 300)
with socialforce.show.canvas() as ax:
ax.plot(x, asymmetry_factor(0.0, x), label='no asymmetry')
ax.plot(x, asymmetry_factor(1.0, x), label='asymmetry = 1.0')
ax.plot(x, asymmetry_factor(0.5, x), label='asymmetry = 0.5')
ax.plot(x, asymmetry_factor(-1.0, x), label='asymmetry = -1.0')
ax.legend()
ax.set_xlabel('$x_{\\perp}$')
ax.set_ylabel('asymmetry factor')

Fitting to Circle and ParallelOvertake Scenarios¶
The preferred speed needs to be varied. Otherwise the symmetry of the problem creates unrealistic scenarios where the two pedestrians get stuck.
circle = socialforce.scenarios.Circle(ped_ped=V)
parallel = socialforce.scenarios.ParallelOvertake(ped_ped=V)
scenarios = circle.generate(5) + parallel.generate(5)
true_experience = socialforce.Trainer.scenes_to_experience(scenarios)
V = socialforce.potentials.PedPedPotentialMLP2D()
with socialforce.show.canvas(figsize=(12, 6), ncols=2) as (ax1, ax2):
socialforce.show.potential_2d(V, ax1)
socialforce.show.potential_2d_grad(V, ax2)
/home/runner/work/socialforce/socialforce/socialforce/show.py:253: UserWarning: No contour levels were found within the data range.
ax.contour(x1, x2, values.T,

simulator = socialforce.Simulator(ped_ped=V)
opt = torch.optim.SGD(V.parameters(), lr=1.0)
socialforce.Trainer(simulator, opt).loop(20, true_experience, log_interval=5)
epoch 5: 0.00540996069548192
epoch 10: 0.0009795692840979628
epoch 15: 0.0010826763397047913
epoch 20: 0.0009852333103764694
with socialforce.show.canvas(figsize=(12, 6), ncols=2) as (ax1, ax2):
socialforce.show.potential_2d(V, ax1)
socialforce.show.potential_2d_grad(V, ax2)
