from math import pi import beluga import logging # Rename this and/or move to optim package? ocp = beluga.OCP('hypersonic3DOF') # Define independent variables ocp.independent('t', 's') rho = 'rho0*exp(-h/H)' Cl = '(1.5658*alpha + -0.0000)' Cd = '(1.6537*alpha**2 + 0.0612)' D = '(0.5*{}*v**2*{}*Aref)'.format(rho, Cd) L = '(0.5*{}*v**2*{}*Aref)'.format(rho, Cl) r = '(re+h)' # Define equations of motion ocp \ .state('h', 'v*sin(gam)', 'm') \ .state('theta', 'v*cos(gam)*cos(psi)/({}*cos(phi))'.format(r), 'rad') \ .state('phi', 'v*cos(gam)*sin(psi)/{}'.format(r), 'rad') \ .state('v', '-{}/mass - mu*sin(gam)/{}**2'.format(D,r), 'm/s') \ .state('gam', '{}*cos(bank)/(mass*v) - mu/(v*{}**2)*cos(gam) + v/{}*cos(gam)'.format(L,r,r), 'rad') \ .state('psi', '{}*sin(bank)/(mass*cos(gam)*v) - v/{}*cos(gam)*cos(psi)*tan(phi)'.format(L,r), 'rad') ocp.constant_of_motion('c1', 'lamTHETA', 'm/(s*rad)') # ocp.constant_of_motion('c2r', 'lamTHETA + lamPHI*cos(theta) + lamTHETA*tan(phi)*sin(theta) + lamPSI*sin(theta)/cos(phi) + lamPHI*sin(theta) - lamTHETA*tan(phi)*cos(theta) - lamPSI*cos(theta)/cos(phi)', 'm/(s*rad)') # ocp.constant_of_motion('c2', 'lamPHI*cos(theta) + lamTHETA*tan(phi)*sin(theta) + lamPSI*sin(theta)/cos(phi)', 'm/(s*rad)') # ocp.constant_of_motion('c3', 'lamPHI*sin(theta) - lamTHETA*tan(phi)*cos(theta) - lamPSI*cos(theta)/cos(phi)', 'm/(s*rad)')
"""Brachistochrone example.""" import beluga import logging from math import pi ocp = beluga.OCP('brachisto') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v*cos(theta)', 'm') \ .state('y', 'v*sin(theta)', 'm') \ .state('v', 'g*sin(theta)', 'm/s') ocp.constant_of_motion('c1', 'lamX', 's/m') ocp.constant_of_motion('c2', 'lamY', 's/m') # Define controls ocp.control('theta', 'rad') # Define constants ocp.constant('g', -9.81, 'm/s^2') ocp.constant('x_f', 0, 'm') ocp.constant('y_f', 0, 'm') # Define costs ocp.path_cost('1', '1') # Define constraints ocp.constraints() \
""" References ---------- .. [1] Ping Chen and Sardar M.N. Islam. "Optimal Control Models in Finance." Kluwer Academic Publishers. DOI: 10.1007/b101888. """ import beluga import numpy as np import logging ocp_indirect = beluga.OCP() # Define independent variables ocp_indirect.independent('t', 'nd') # Define equations of motion ocp_indirect.state('x1', 'T*x2', 'nd') ocp_indirect.state('x2', '-T*x1 + T*u - T**2*B*x2', 'nd') # 2*sin(u) # Define controls ocp_indirect.control('u', 'rad') # Define constants ocp_indirect.constant('T', 5, 'nd') ocp_indirect.constant('B', 0.2, 'nd') ocp_indirect.constant('x1_0', 3, 'nd') ocp_indirect.constant('x2_0', 5, 'nd') ocp_indirect.constant('epsilon1', 10, 'nd') # Define costs
"""Unconstrained planar hypersonic trajectory problem. Entry flight-path angle is constrained so the vehicle enters the atmosphere fairly steep. It performs a skip maneuver to reach it's target. The first solution is the planar problem, which then is used as an initial guess into the 4-hypersonic3dof problem.""" from math import * import beluga import logging ''' Begin the planar portion of the solution process. ''' ocp = beluga.OCP('planarHypersonic') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('h','v*sin(gam)','m') \ .state('theta','v*cos(gam)/r','rad') \ .state('v','-D/mass - mu*sin(gam)/r**2','m/s') \ .state('gam','L/(mass*v) + (v/r - mu/(v*r^2))*cos(gam)','rad') # Define quantities used in the problem ocp.quantity('rho', 'rho0*exp(-h/H)') ocp.quantity('Cl', '(1.5658*alfa + -0.0000)') ocp.quantity('Cd', '(1.6537*alfa^2 + 0.0612)') ocp.quantity('D', '0.5*rho*v^2*Cd*Aref') ocp.quantity('L', '0.5*rho*v^2*Cl*Aref') ocp.quantity('r', 're+h')
twostage_mass0 = 29.365e3 twostage_mass0f = twostage_mass0 - 18.8e3 twostage_mass1 = twostage_mass0 - 2*10.125e3 - 2e3 - 0.9e3 twostage_massflow0 = -131.58 twostage_massflow1 = -78.95 y_f = 100e3 if not test_run: conn = krpc.connect(name='ksp-astrogator') vessel = conn.space_center.active_vessel print('Connected with ' + vessel.name) ocp = beluga.OCP('twostage') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v_x', 'm') \ .state('y', 'v_y', 'm') \ .state('v_x', 'Thrust/current_mass*cos(theta) - D/current_mass*v_x/sqrt(v_x**2 + v_y**2)', 'm/s') \ .state('v_y', 'Thrust/current_mass*sin(theta) - D/current_mass*v_y/sqrt(v_x**2 + v_y**2) - g', 'm/s') \ .state('mass', 'mass_flow*eps', 'kg') # Define controls ocp.control('theta', 'rad') ocp.quantity('engine0', 'F0_sea*exp(-y/Hscale) + F0_vac*(1-exp(-y/Hscale))')
def test_brachistochrone_shooting(): from math import pi import beluga from beluga.ivpsol import Trajectory from beluga.bvpsol import Solution ocp = beluga.OCP('brachisto') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v*cos(theta)', 'm') \ .state('y', 'v*sin(theta)', 'm') \ .state('v', 'g*sin(theta)', 'm/s') # Define controls ocp.control('theta', 'rad') # Define constants ocp.constant('g', -9.81, 'm/s^2') # Define costs ocp.path_cost('1', '1') # Define constraints ocp.constraints() \ .initial('x-x_0', 'm') \ .initial('y-y_0', 'm') \ .initial('v-v_0', 'm/s') \ .terminal('x-x_f', 'm') \ .terminal('y-y_f', 'm') ocp.scale(m='y', s='y/v', kg=1, rad=1) shooting_solver = beluga.bvp_algorithm('Shooting') guess_maker = beluga.guess_generator('auto', start=[0, 0, 0], direction='forward', costate_guess=-0.1, control_guess = [-pi/2], use_control_guess=True) continuation_steps = beluga.init_continuation() continuation_steps.add_step('bisection') \ .num_cases(21) \ .terminal('x', 10) \ .terminal('y', -10) sol = beluga.solve(ocp, method='icrm', bvp_algorithm=shooting_solver, steps=continuation_steps, guess_generator=guess_maker) assert isinstance(sol, Trajectory) assert isinstance(sol, Solution) assert sol.t.shape[0] == sol.y.shape[0] assert sol.t.shape[0] == sol.u.shape[0] assert sol.y.shape[1] == 7 assert sol.u.shape[1] == 1 y0 = sol.y[0] yf = sol.y[-1] assert abs(y0[0] - 0) < tol assert abs(y0[1] - 0) < tol assert abs(y0[2] - 0) < tol assert abs(y0[3] + 0.0667) < tol assert abs(y0[4] - 0.0255) < tol assert abs(y0[5] + 0.1019) < tol assert abs(sol.t[-1] - 1.8433) < tol assert abs(yf[0] - 10) < tol assert abs(yf[1] + 10) < tol assert abs(yf[2] - 14.0071) < tol assert abs(yf[3] + 0.0667) < tol assert abs(yf[4] - 0.0255) < tol assert abs(yf[5] - 0) < tol assert abs(y0[3] - yf[3]) < tol assert abs(y0[4] - yf[4]) < tol sol = beluga.solve(ocp, method='traditional', bvp_algorithm=shooting_solver, steps=continuation_steps, guess_generator=guess_maker) y0 = sol.y[0] yf = sol.y[-1] assert sol.t.shape[0] == sol.y.shape[0] assert sol.t.shape[0] == sol.u.shape[0] assert sol.y.shape[1] == 6 assert sol.u.shape[1] == 1 assert abs(y0[0] - 0) < tol assert abs(y0[1] - 0) < tol assert abs(y0[2] - 0) < tol assert abs(y0[3] + 0.0667) < tol assert abs(y0[4] - 0.0255) < tol assert abs(y0[5] + 0.1019) < tol assert abs(sol.t[-1] - 1.8433) < tol assert abs(yf[0] - 10) < tol assert abs(yf[1] + 10) < tol assert abs(yf[2] - 14.0071) < tol assert abs(yf[3] + 0.0667) < tol assert abs(yf[4] - 0.0255) < tol assert abs(yf[5] - 0) < tol assert abs(y0[3] - yf[3]) < tol assert abs(y0[4] - yf[4]) < tol
"""Brachistochrone example.""" from math import pi import beluga ocp = beluga.OCP('missle') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.quantity('xbardot','cos(psi)*cos(gam)') ocp.quantity('ybardot','sin(psi)*cos(gam)') ocp.quantity('zbardot','-sin(gam)') ocp.state('xbar', 'xbardot', 'nd')\ .state('ybar', 'ybardot', 'nd')\ .state('zbar', 'zbardot', 'nd')\ .state('psi', '10*abar', 'nd') ocp.control('abar','nd') ocp.control('gam','nd') ocp.quantity('xbar2dot','vbar2*cos(psi2)*cos(gam2)') ocp.quantity('ybar2dot','vbar2*sin(psi2)*cos(gam2)') ocp.quantity('zbar2dot','-vbar2*sin(gam2)') ocp.state('xbar2', 'xbar2dot', 'nd')\ .state('ybar2', 'ybar2dot', 'nd')\ .state('zbar2', 'zbar2dot', 'nd')\ .state('psi2', '10*abar2', 'nd')\ .state('vbar2', '0', 'nd/s') ocp.control('abar2','nd') ocp.control('gam2','nd')
import logging from math import pi, sqrt import numpy as np import matplotlib.pyplot as plt from scipy import interpolate test_run = False countdown = 3 conn = krpc.connect(name='ksp-astrogator') if not test_run: vessel = conn.space_center.active_vessel print('Connected with ' + vessel.name) ocp = beluga.OCP('goddard') # Define independent variables ocp.independent('t', 's') # Define quantities used in the problem ocp.quantity('drag', '1/2 * d * v**2 * rho0 * exp(-h/H) * pi * (A/2)**2') # Define equations of motion ocp.state('h', 'v', 'm') \ .state('v', '(thrust*(thrust_max_sea*exp(-h/H) + thrust_max_vac*(1-exp(-h/H))) - drag)/m - g', 'm/s') \ .state('m', '-thrust*c', 'kg') # Define controls ocp.control('thrust', '1')
import krpc import logging from math import pi import numpy as np import matplotlib.pyplot as plt from scipy import interpolate test_run = False countdown = 3 if not test_run: conn = krpc.connect(name='ksp-astrogator') vessel = conn.space_center.active_vessel print('Connected with ' + vessel.name) ocp = beluga.OCP('ssto') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v_x', 'm') \ .state('y', 'v_y', 'm') \ .state('v_x', '(F_sea*exp(-y/Hscale) + F_vac*(1-exp(-y/Hscale)))/mass*cos(theta) - D/mass*v_x/sqrt(v_x**2 + v_y**2)', 'm/s') \ .state('v_y', '(F_sea*exp(-y/Hscale) + F_vac*(1-exp(-y/Hscale)))/mass*sin(theta) - D/mass*v_y/sqrt(v_x**2 + v_y**2) - g', 'm/s') \ .state('mass', 'md*eps', 'kg') initial_mass = 10.665e3 Hscale = 5600 F_sea = 205.16e3 F_vac = 240e3
def test_planarhypersonic(): from math import pi import beluga ocp = beluga.OCP('planarHypersonic') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('h', 'v*sin(gam)', 'm') \ .state('theta', 'v*cos(gam)/r', 'rad') \ .state('v', '-D/mass - mu*sin(gam)/r**2', 'm/s') \ .state('gam', 'L/(mass*v) + (v/r - mu/(v*r^2))*cos(gam)', 'rad') # Define quantities used in the problem ocp.quantity('rho', 'rho0*exp(-h/H)') ocp.quantity('Cl', '(1.5658*alfa + -0.0000)') ocp.quantity('Cd', '(1.6537*alfa^2 + 0.0612)') ocp.quantity('D', '0.5*rho*v^2*Cd*Aref') ocp.quantity('L', '0.5*rho*v^2*Cl*Aref') ocp.quantity('r', 're+h') # Define controls ocp.control('alfa', 'rad') # Define constants ocp.constant('mu', 3.986e5 * 1e9, 'm^3/s^2') # Gravitational parameter, m^3/s^2 ocp.constant('rho0', 0.0001 * 1.2, 'kg/m^3') # Sea-level atmospheric density, kg/m^3 ocp.constant('H', 7500, 'm') # Scale height for atmosphere of Earth, m ocp.constant('mass', 750 / 2.2046226, 'kg') # Mass of vehicle, kg ocp.constant('re', 6378000, 'm') # Radius of planet, m ocp.constant('Aref', pi * (24 * .0254 / 2)**2, 'm^2') # Reference area of vehicle, m^2 ocp.constant('h_0', 80000, 'm') ocp.constant('v_0', 4000, 'm/s') ocp.constant('h_f', 80000, 'm') ocp.constant('theta_f', 0, 'rad') # Define costs ocp.terminal_cost('-v^2', 'm^2/s^2') # Define constraints ocp.constraints() \ .initial('h-h_0', 'm') \ .initial('theta', 'rad') \ .initial('v-v_0', 'm/s') \ .terminal('h-h_f', 'm') \ .terminal('theta-theta_f', 'rad') ocp.scale(m='h', s='h/v', kg='mass', rad=1) bvp_solver = beluga.bvp_algorithm('Shooting', algorithm='SLSQP', tolerance=1e-6) guess_maker = beluga.guess_generator( 'auto', start=[80000, 0, 4000, -90 * pi / 180], direction='forward', costate_guess=-0.1) continuation_steps = beluga.init_continuation() continuation_steps.add_step('bisection') \ .num_cases(11) \ .const('h_f', 0) \ .const('theta_f', 0.01 * pi / 180) continuation_steps.add_step('bisection') \ .num_cases(11) \ .const('theta_f', 5.0 * pi / 180) continuation_steps.add_step('bisection') \ .num_cases(11) \ .const('rho0', 1.2) sol = beluga.solve(ocp, method='traditional', bvp_algorithm=bvp_solver, steps=continuation_steps, guess_generator=guess_maker) y0 = sol.y[0] yf = sol.y[-1] y0e = [ 8.00000000e+04, 0.00000000e+00, 4.00000000e+03, 1.95069984e-02, -1.68249327e+01, 1.21634197e+06, -2.83598229e+03, -6.15819100e-17 ] yfe = [ 5.23214346e-04, 8.72664626e-02, 2.69147623e+03, -9.38246813e-01, 5.46455659e+02, 1.21634197e+06, -5.38295257e+03, 1.67911185e-01 ] tfe = 144.5678 assert sol.t.shape[0] == sol.y.shape[0] assert sol.t.shape[0] == sol.u.shape[0] assert sol.y.shape[1] == 8 assert sol.u.shape[1] == 1 assert abs((y0[0] - y0e[0]) / y0e[0]) < tol assert abs((y0[1] - y0e[1])) < tol assert abs((y0[2] - y0e[2]) / y0e[2]) < tol assert abs((y0[3] - y0e[3]) / y0e[3]) < tol assert abs((y0[4] - y0e[4]) / y0e[4]) < tol assert abs((y0[5] - y0e[5]) / y0e[5]) < tol assert abs((y0[6] - y0e[6]) / y0e[6]) < tol assert abs((y0[7] - y0e[7])) < tol assert abs((sol.t[-1] - tfe) / tfe) < tol assert abs((yf[0] - yfe[0])) < tol assert abs((yf[1] - yfe[1]) / yfe[1]) < tol assert abs((yf[2] - yfe[2]) / yfe[2]) < tol assert abs((yf[3] - yfe[3]) / yfe[3]) < tol assert abs((yf[4] - yfe[4]) / yfe[4]) < tol assert abs((yf[5] - yfe[5]) / yfe[5]) < tol assert abs((yf[6] - yfe[6]) / yfe[6]) < tol assert abs((yf[7] - yfe[7]) / yfe[7]) < tol
from math import pi import beluga ocp = beluga.OCP('heatRate') # Define independent variables ocp.independent('t', 's') # Define quantities used in the problem ocp.quantity('rho','rho0*exp(-h/H)') ocp.quantity('Cl','(1.5658*alfa + -0.0000)') ocp.quantity('Cd','(1.6537*alfa^2 + 0.0612)') ocp.quantity('D','0.5*rho*v^2*Cd*Aref') ocp.quantity('L','0.5*rho*v^2*Cl*Aref') ocp.quantity('r','re+h') # Define equations of motion ocp.state('h','(v*sin(gam))','m') \ .state('theta','v*cos(gam)/r','rad') \ .state('v','(-D/mass - mu*sin(gam)/r**2)','m/s') \ .state('gam','L/(mass*v) + (v/r - mu/(v*r^2))*cos(gam)','rad') # Define controls ocp.control('alfa','rad') # Define costs ocp.terminal_cost('-v^2','m^2/s^2') # Planetary constants ocp.constant('mu', 3.986e5*1e9, 'm^3/s^2') # Gravitational parameter, m^3/s^2 ocp.constant('rho0', 1.2, 'kg/m^3') # Sea-level atmospheric density, kg/m^3
def test_zermelo_custom_functions(): import beluga ocp = beluga.OCP('zermelos_problem') def drift_x(x, y): return 0 def drift_y(x, y): return ((x - 5)**4 - 625) / 625 ocp.custom_function('drift_x', drift_x) ocp.custom_function('drift_y', drift_y) # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'V*cos(theta) + epsilon*drift_x(x,y)', 'm') \ .state('y', 'V*sin(theta) + epsilon*drift_y(x,y)', 'm') # Define controls ocp.control('theta', 'rad') # Define constants ocp.constant('V', 10, 'm/s') ocp.constant('epsilon', 0.001, '1') ocp.constant('x_f', 0, 'm') ocp.constant('y_f', 0, 'm') # Define costs ocp.path_cost('1', '1') # Define constraints ocp.constraints() \ .initial('x', 'm') \ .initial('y', 'm') \ .terminal('x-x_f', 'm') \ .terminal('y-y_f', 'm') ocp.scale(m='x', s='x/V', rad=1) bvp_solver = beluga.bvp_algorithm('Shooting', derivative_method='fd', tolerance=1e-4, max_error=100, max_iterations=100) guess_maker = beluga.guess_generator('auto', start=[0, 0], control_guess=[0], use_control_guess=True, direction='forward') continuation_steps = beluga.init_continuation() continuation_steps.add_step('bisection') \ .num_cases(10) \ .const('x_f', 10) continuation_steps.add_step('bisection') \ .num_cases(10) \ .const('y_f', 10) continuation_steps.add_step('bisection') \ .num_cases(10) \ .const('epsilon', 1) sol = beluga.solve(ocp, method='icrm', bvp_algorithm=bvp_solver, steps=continuation_steps, guess_generator=guess_maker) from beluga.ivpsol import Trajectory assert isinstance(sol, Trajectory)
"""Ground vehicle path planning problem.""" from math import * import beluga import logging ocp = beluga.OCP('dubin') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x','V*cos(theta)','m') \ .state('y','V*sin(theta)','m') \ .state('theta','-V/L*delta','rad') # Define quantities used in the problem # Define controls ocp.control('delta', 'rad') # Define constants ocp.constant('L', 1.0, 'm') ocp.constant('V', 1.0, 'm/s') ocp.constant('rad2sec', 1.0, 's/(rad^2)') ocp.constant('w1', 0.5, 'nd') ocp.constant('steeringLim', 30 * pi / 180, 'rad') # Define costs ocp.path_cost('w1*delta**2 + (1)', 's') # Define constraints ocp.constraints() \
from math import pi import beluga ocp = beluga.OCP('jammer') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('xbar', 'cos(psi)*cos(gam)', 'nd')\ .state('ybar', 'sin(psi)*cos(gam)', 'nd')\ .state('zbar', '-sin(gam)', 'nd')\ .state('psi', '10*abar', 'nd') ocp.control('abar', 'nd') ocp.control('gam', 'nd') ocp.state('xbar2', 'vbar2*cos(psi2)*cos(gam2)', 'nd')\ .state('ybar2', 'vbar2*sin(psi2)*cos(gam2)', 'nd')\ .state('zbar2', '-vbar2*sin(gam2)', 'nd')\ .state('psi2', '10*abar2', 'nd')\ .state('vbar2', '0', 'nd/s') ocp.control('abar2', 'nd') ocp.control('gam2', 'nd') ocp.constant('xc1', -0.1, 'nd') ocp.constant('slope', 40, 'nd') ocp.constant('safeDist', 0.02, 'nd') ocp.constant('unsafeDist', 0.000001, 'nd') # Near target ocp.constant('ymax', 0.2, 'nd') ocp.constant('xc', -0.6, 'nd')
"""Unconstrained planar hypersonic trajectory problem. Entry flight-path angle is constrained so the vehicle enters the atmosphere fairly steep. It performs a skip maneuver to reach it's target.""" from math import * import beluga import logging ocp = beluga.OCP('planarHypersonic') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('h','v*sin(gam)','m') \ .state('theta','v*cos(gam)/r','rad') \ .state('v','-D/mass - mu*sin(gam)/r**2','m/s') \ .state('gam','L/(mass*v) + (v/r - mu/(v*r^2))*cos(gam)','rad') # Define quantities used in the problem ocp.quantity('rho', 'rho0*exp(-h/H)') ocp.quantity('Cl', '(1.5658*alfa + -0.0000)') ocp.quantity('Cd', '(1.6537*alfa^2 + 0.0612)') ocp.quantity('D', '0.5*rho*v^2*Cd*Aref') ocp.quantity('L', '0.5*rho*v^2*Cl*Aref') ocp.quantity('r', 're+h') # Define controls ocp.control('alfa', 'rad')
"""Constrained Double integrator problem .""" import beluga # Rename this and/or move to optim package? ocp = beluga.OCP('brysonDenhamConstrained') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v','m') \ .state('v', 'u','m/s') # Define controls ocp.control('u','m/s') # Define costs ocp.path_cost('u**2','m**2/s') # Define constraints ocp.constraints() \ .initial('x-x_0','m') \ .initial('v-v_0','m/s') \ .terminal('x-x_f','m') \ .terminal('v-v_f','m/s') \ .path('xlim','x','<',0.18,'m') \ .independent('tf - 1','s') # Fixed final time ocp.scale(m=1, s=1, kg=1, rad=1, nd=1)
def test_planarhypersonic(): from math import pi import beluga ocp = beluga.OCP('planarHypersonic') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('h', 'v*sin(gam)', 'm') \ .state('theta', 'v*cos(gam)/r', 'rad') \ .state('v', '-D/mass - mu*sin(gam)/r**2', 'm/s') \ .state('gam', 'L/(mass*v) + (v/r - mu/(v*r^2))*cos(gam)', 'rad') # Define quantities used in the problem ocp.quantity('rho', 'rho0*exp(-h/H)') ocp.quantity('Cl', '(1.5658*alfa + -0.0000)') ocp.quantity('Cd', '(1.6537*alfa^2 + 0.0612)') ocp.quantity('D', '0.5*rho*v^2*Cd*Aref') ocp.quantity('L', '0.5*rho*v^2*Cl*Aref') ocp.quantity('r', 're+h') # Define controls ocp.control('alfa', 'rad') # Define constants ocp.constant('mu', 3.986e5 * 1e9, 'm^3/s^2') # Gravitational parameter, m^3/s^2 ocp.constant('rho0', 0.0001 * 1.2, 'kg/m^3') # Sea-level atmospheric density, kg/m^3 ocp.constant('H', 7500, 'm') # Scale height for atmosphere of Earth, m ocp.constant('mass', 750 / 2.2046226, 'kg') # Mass of vehicle, kg ocp.constant('re', 6378000, 'm') # Radius of planet, m ocp.constant('Aref', pi * (24 * .0254 / 2) ** 2, 'm^2') # Reference area of vehicle, m^2 # Define costs ocp.terminal_cost('-v^2', 'm^2/s^2') # Define constraints ocp.constraints() \ .initial('h-h_0', 'm') \ .initial('theta-theta_0', 'rad') \ .initial('v-v_0', 'm/s') \ .terminal('h-h_f', 'm') \ .terminal('theta-theta_f', 'rad') ocp.scale(m='h', s='h/v', kg='mass', rad=1) bvp_solver = beluga.bvp_algorithm('Shooting') guess_maker = beluga.guess_generator('auto', start=[80000, 0, 4000, -90 * pi / 180], direction='forward', costate_guess=-0.1) continuation_steps = beluga.init_continuation() continuation_steps.add_step('bisection') \ .num_cases(11) \ .terminal('h', 0) \ .terminal('theta', 0.01 * pi / 180) continuation_steps.add_step('bisection') \ .num_cases(11) \ .terminal('theta', 5.0 * pi / 180) continuation_steps.add_step('bisection') \ .num_cases(11) \ .const('rho0', 1.2) sol = beluga.solve(ocp, method='traditional', bvp_algorithm=bvp_solver, steps=continuation_steps, guess_generator=guess_maker) y0 = sol.y[0] yf = sol.y[-1] y0e = [80000, 0, 4000, 0.0195, -16.8243, 1212433.8085, -2836.0620, 0] yfe = [0, 0.0873, 2691.4733, -0.9383, 546.4540, 1212433.8085, -5382.9467, 0.1840] tfe = 144.5677 assert sol.t.shape[0] == sol.y.shape[0] assert sol.t.shape[0] == sol.u.shape[0] assert sol.y.shape[1] == 8 assert sol.u.shape[1] == 1 assert abs((y0[0] - y0e[0]) / y0e[0]) < tol assert abs((y0[1] - y0e[1])) < tol assert abs((y0[2] - y0e[2]) / y0e[2]) < tol assert abs((y0[3] - y0e[3]) / y0e[3]) < tol assert abs((y0[4] - y0e[4]) / y0e[4]) < tol assert abs((y0[5] - y0e[5]) / y0e[5]) < tol assert abs((y0[6] - y0e[6]) / y0e[6]) < tol assert abs((y0[7] - y0e[7])) < tol assert abs((sol.t[-1] - tfe) / tfe) < tol assert abs((yf[0] - yfe[0])) < tol assert abs((yf[1] - yfe[1]) / yfe[1]) < tol assert abs((yf[2] - yfe[2]) / yfe[2]) < tol assert abs((yf[3] - yfe[3]) / yfe[3]) < tol assert abs((yf[4] - yfe[4]) / yfe[4]) < tol assert abs((yf[5] - yfe[5]) / yfe[5]) < tol assert abs((yf[6] - yfe[6]) / yfe[6]) < tol assert abs((yf[7] - yfe[7]) / yfe[7]) < tol
import beluga import logging ocp = beluga.OCP('zermelos_problem') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'V*cos(theta)', 'm') \ .state('y', 'V*sin(theta) - cur', 'm') \ # .state('cur', '0', 'm/s') # Define controls ocp.control('theta', 'rad') # Define constants ocp.constant('V', 10, 'm/s') ocp.constant('x_f', 0, 'm') ocp.constant('y_f', 0, 'm') ocp.parameter('cur', 'm/s') # Define costs ocp.path_cost('1', '1') # Define constraints ocp.constraints() \ .initial('x', 'm') \ .initial('y', 'm') \ .terminal('x-x_f', 'm') \
import beluga import logging ocp = beluga.OCP() # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('r', 'v_r', 'L') \ .state('theta', 'v_theta/r', 'rad') \ .state('v_r', 'v_theta**2/r - mu/r**2 + Tf*cos(alpha)', 'L/s') \ .state('v_theta', '-v_r*v_theta/r + Tf*sin(alpha)', 'L/s') \ .state('m', 'mdot', 'M') # Define quantities used in the problem ocp.quantity('Tf', 'T/m') # Define controls ocp.control('alpha', 'rad') # Define constants ocp.constant('mu', 1, 'L^3/s^2') ocp.constant('T', 0.1, 'M*L/s^2') ocp.constant('r_0', 1, 'L') ocp.constant('theta_0', 0, 'rad') ocp.constant('v_r_0', 0, 'L/s') ocp.constant('v_theta_0', 1, 'L/s') ocp.constant('m_0', 1, 'M') ocp.constant('v_r_f', 0, 'L/s') ocp.constant('t_f', 1, 's')
"""Brachistochrone example with path constraint.""" import beluga import logging ocp = beluga.OCP('boundedBrachistochrone') # Define independent variables ocp.independent('t', 's') # Define equations of motion ocp.state('x', 'v*cos(theta)', 'm') \ .state('y', 'v*sin(theta)','m') \ .state('v', 'g*sin(theta)','m/s') # Define controls ocp.control('theta','rad') # Define constants ocp.constant('g',-9.81,'m/s^2') ocp.constant('xlim',1.0,'m') # Define costs ocp.path_cost('1','s') # Define constraints ocp.constraints() \ .initial('x-x_0','m') \ .initial('y-y_0','m') \ .initial('v-v_0','m/s') \ .terminal('x-x_f','m') \ .terminal('y-y_f','m') \