def test_events():
# use bouncing ball to test events work
# simulate in block diagram
int_opts = block_diagram.DEFAULT_INTEGRATOR_OPTIONS.copy()
int_opts['rtol'] = 1E-12
int_opts['atol'] = 1E-15
int_opts['nsteps'] = 1000
int_opts['max_step'] = 2**-3
x = x1, x2 = Array(dynamicsymbols('x_1:3'))
mu, g = sp.symbols('mu g')
constants = {mu: 0.8, g: 9.81}
ic = np.r_[10, 15]
sys = SwitchedSystem(
x1, Array([0]),
state_equations=r_[x2, -g],
state_update_equation=r_[sp.Abs(x1), -mu*x2],
state=x,
constants_values=constants,
initial_condition=ic
)
bd = BlockDiagram(sys)
res = bd.simulate(5, integrator_options=int_opts)
# compute actual impact time
tvar = dynamicsymbols._t
impact_eq = (x2*tvar - g*tvar**2/2 + x1).subs(
{x1: ic[0], x2: ic[1], g: 9.81}
)
t_impact = sp.solve(impact_eq, tvar)[-1]
# make sure simulation actually changes velocity sign around impact
abs_diff_impact = np.abs(res.t - t_impact)
impact_idx = np.where(abs_diff_impact == np.min(abs_diff_impact))[0]
assert np.sign(res.x[impact_idx-1, 1]) != np.sign(res.x[impact_idx+1, 1])
评论列表
文章目录