import%20marimo%0A%0A__generated_with%20%3D%20%220.14.6%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%20Rudder%20Kick%0A%0A%20%20%20%20Simulate%20a%20pilot%20performing%20a%20rudder%20kick%20test%20by%20inputing%20a%20rudder%20input%20based%20on%20a%20ramp%20input.%20Aileron%20input%20is%20also%20included%20to%20maintain%20a%20steady%20heading%20sideslip%20(SHSS).%20The%20time%20histories%20of%20the%20control%20inputs%20and%20beta%20(sideslip%20angle)%20are%20plotted.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20jsbsim%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20math%0A%0A%20%20%20%20%23%20Global%20variables%20that%20must%20be%20modified%20to%20match%20your%20particular%20need%0A%20%20%20%20%23%20The%20aircraft%20name%0A%20%20%20%20%23%20Note%20-%20It%20should%20match%20the%20exact%20spelling%20of%20the%20model%20file%0A%20%20%20%20AIRCRAFT_NAME%3D%22737%22%0A%20%20%20%20%23%20Path%20to%20JSBSim%20files%2C%20location%20of%20the%20folders%20%22aircraft%22%2C%20%22engines%22%20and%20%22systems%22%0A%20%20%20%20PATH_TO_JSBSIM_FILES%3D%22data%2Fjsbsim%22%0A%0A%20%20%20%20%23%20Avoid%20flooding%20the%20console%20with%20log%20messages%0A%20%20%20%20jsbsim.FGJSBBase().debug_lvl%20%3D%200%0A%0A%20%20%20%20fdm%20%3D%20jsbsim.FGFDMExec(PATH_TO_JSBSIM_FILES)%0A%0A%20%20%20%20%23%20Load%20the%20aircraft%20model%0A%20%20%20%20fdm.load_model(AIRCRAFT_NAME)%0A%0A%20%20%20%20%23%20Set%20engines%20running%0A%20%20%20%20fdm%5B'propulsion%2Fset-running'%5D%20%3D%20-1%0A%0A%20%20%20%20%23%20Set%20alpha%20range%20for%20trim%20solutions%0A%20%20%20%20fdm%5B'aero%2Falpha-max-rad'%5D%20%3D%20math.radians(12)%0A%20%20%20%20fdm%5B'aero%2Falpha-min-rad'%5D%20%3D%20math.radians(-4.0)%0A%0A%20%20%20%20dt%20%3D%20fdm.get_delta_t()%0A%0A%20%20%20%20%23%20Max%20control%20deflection%0A%20%20%20%20aileronMax%20%3D%201%0A%20%20%20%20rudderMax%20%3D%200.92%0A%0A%20%20%20%20%23%20Number%20of%20seconds%20for%20control%20surface%20to%20reach%20max%20deflection%0A%20%20%20%20risetime%20%3D%203%0A%0A%20%20%20%20%23%20Per%20timestep%20increment%20for%20control%20surfaces%0A%20%20%20%20diAileron%20%3D%20aileronMax%20%2F%20(risetime%2Fdt)%0A%20%20%20%20diRudder%20%3D%20rudderMax%20%2F%20(risetime%2Fdt)%0A%0A%20%20%20%20%23%20Recorded%20data%0A%20%20%20%20times%20%3D%20%5B%5D%0A%0A%20%20%20%20betas%20%3D%20%5B%5D%0A%20%20%20%20bankAngle%20%3D%20%5B%5D%0A%20%20%20%20ailerons%20%3D%20%5B%5D%0A%20%20%20%20rudder%20%3D%20%5B%5D%0A%0A%20%20%20%20%23%20Initial%20conditions%0A%20%20%20%20fdm%5B'ic%2Fh-sl-ft'%5D%20%3D%201000%0A%20%20%20%20fdm%5B'ic%2Fvc-kts'%5D%20%3D%20200%0A%20%20%20%20fdm%5B'ic%2Fgamma-deg'%5D%20%3D%200%0A%20%20%20%20fdm%5B'ic%2Fbeta-deg'%5D%20%3D%200%0A%0A%20%20%20%20%23%20Initialize%20the%20aircraft%20with%20initial%20conditions%0A%20%20%20%20fdm.run_ic()%20%0A%0A%20%20%20%20%23%20Trim%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20fdm%5B'simulation%2Fdo_simple_trim'%5D%20%3D%201%0A%0A%20%20%20%20except%20jsbsim.TrimFailureError%3A%0A%20%20%20%20%20%20%20%20print(%22Trim%20failed%2C%20continuing%20rudder%20kick%20in%20an%20untrimmed%20state.%22)%0A%20%20%20%20%20%20%20%20pass%20%20%23%20Ignore%20trim%20failure%0A%0A%20%20%20%20%23%20Time%20to%20run%20for%20in%20seconds%0A%20%20%20%20run_period%20%3D%2020%0A%0A%20%20%20%20for%20i%20in%20range(int(run_period%2Fdt))%3A%0A%20%20%20%20%20%20%20%20fdm.run()%0A%0A%20%20%20%20%20%20%20%20times.append(fdm.get_sim_time())%0A%0A%20%20%20%20%20%20%20%20betas.append(fdm%5B'aero%2Fbeta-deg'%5D)%0A%20%20%20%20%20%20%20%20bankAngle.append(fdm%5B'attitude%2Fphi-deg'%5D)%0A%20%20%20%20%20%20%20%20ailerons.append(fdm%5B'fcs%2Faileron-cmd-norm'%5D)%0A%20%20%20%20%20%20%20%20rudder.append(fdm%5B'fcs%2Frudder-cmd-norm'%5D)%0A%0A%20%20%20%20%20%20%20%20aileronCmd%20%3D%20fdm%5B'fcs%2Faileron-cmd-norm'%5D%0A%20%20%20%20%20%20%20%20rudderCmd%20%3D%20fdm%5B'fcs%2Frudder-cmd-norm'%5D%0A%0A%20%20%20%20%20%20%20%20if%20aileronCmd%20%3C%20aileronMax%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20aileronCmd%20%2B%3D%20diAileron%0A%20%20%20%20%20%20%20%20%20%20%20%20fdm%5B'fcs%2Faileron-cmd-norm'%5D%20%3D%20aileronCmd%0A%0A%20%20%20%20%20%20%20%20if%20rudderCmd%20%3C%20rudderMax%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20rudderCmd%20%2B%3D%20diRudder%0A%20%20%20%20%20%20%20%20%20%20%20%20fdm%5B'fcs%2Frudder-cmd-norm'%5D%20%3D%20rudderCmd%0A%0A%20%20%20%20%23%20Plot%20results%0A%20%20%20%20plt.rcParams%5B%22figure.figsize%22%5D%20%3D%20(12%2C%208)%0A%20%20%20%20fig%2C%20ax1%20%3D%20plt.subplots()%0A%20%20%20%20ax1.set_xlabel('Time%20(s)')%0A%20%20%20%20ax1.set_ylabel('Beta%20(deg)')%0A%20%20%20%20line1%20%3D%20ax1.plot(times%2C%20betas%2C%20label%3D'Beta'%2C%20color%3D'red')%0A%0A%20%20%20%20ax2%20%3D%20ax1.twinx()%0A%0A%20%20%20%20ax2.set_ylabel('Inceptor%20Position')%0A%20%20%20%20line2%20%3D%20ax2.plot(times%2C%20ailerons%2C%20label%3D'Aileron')%0A%20%20%20%20line3%20%3D%20ax2.plot(times%2C%20rudder%2C%20label%3D'Rudder')%0A%0A%20%20%20%20ax1.legend(handles%3Dline1%2Bline2%2Bline3%2C%20loc%3D4)%0A%0A%20%20%20%20plt.title('Rudder%20Kick')%0A%0A%20%20%20%20plt.gca()%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
cb3fbd1c7fa664f877c57de96bb71562c7ec15f40da4ee7b0c0416a18ee2db5b