################################################################################ # # Orbital library for gnuplot # - Version : 3.0 beta HSG_libver = "3.0 beta"; # - Author : Helton da Silva Gaspar # - Mail : helton.s.gaspar@ufsc.br # - Date : 04 / 08 / 2023 HSG_libdate = "2023-08-04"; # ################################################################################ ################################################################################ # # DESCRIPTION # # This library gathers useful functions for plotting orbits. It contains # four main packages: # 1. rv2** whose functions convert fixed cartesian coordinates to # keplerian elements # 2. eo2** whose functions convert keplerian elements to fixed cartesian # coordinates # 3. polar and perifocal frame functions # 4. time/position functions # 5. constants # # DEFINITIONS AND UNIFORMITY # p stands for the semilatus rectum # a stands for the semimajor axis ( a==p case e==1 ) # e stands for the eccentricity # I stands for the inclination # O stands for the longitude of the ascending node # w stands for the argument of periapsis # f stands for the true anomaly # M stands for the mean anomaly # E stands for the eccetric anomaly # n stands for the mean motion # T stands for the period # t stands for the flight time since periapsis # C3 stands for the specific mechanical energy # mu stands for the mass parameter (G*mass) # gamma stands of the flight path angle # # FUNCTIONS WITHIN THE rv2** PACKAGE # In order to keep uniformity, all the package functions must have the # following parameters as argument: mu, x, y, z, vx, vy and vz # rv2**(mu,x,y,z,vx,vy,vz) # despite not all of them are necessary for some of the functions. # # SYNOPSIS rv2**(mu,x,y,z,vx,vy,vz), where ** may be one of the following: # ** = p,a,e,I,O,w,f,n,T,C3,gamma # # FUNCTIONS WITHIN THE eo2** PACKAGE # In order to keep uniformity, all the package functions must have the # following parameters as argument: mu, a, e, I, O, w and f. # rv2**(mu,a,e,I,O,w,f) # despite not all of them are necessary for some of the functions. # # SYNOPSIS eo2**(mu,a,e,I,O,w,f), where ** may be one of the following: # ** = x,y,z,vx,vy,vz,n,T,t # # FUNCTIONS WITHIN THE POLAR PACKAGE # - polp(a,e) returns semilatus rectum given a and e # - polr(a,e,f) returns range from focus given a, e and f # - poldrdf(a,e,f) returns the derivative dr/dr given a, e and f # # FUNCTIONS OF THE PERIFOCAL FRAME PACKAGE # - x_pq(a,e,w,f) returns the x coordinate within the perifocal frame # - y_pq(a,e,w,f) returns the y coordinate within the perifocal frame # - vr(mu,a,e,f) returns the radial component of the velocity # - vt(mu,a,e,f) returns the transversal component of the velocity # - vx_pq(mu,a,e,w,f) returns the x component of the velocity # - vy_pq(mu,a,e,w,f) returns the y component of the velocity # - gamma(e,f) returns the flight path angle # # FUNCTIONS WITHIN THE TIME/POSITION PACKAGE # - f2E(e,f) returns eccetric anomaly given e and f # - E2M(e,E) returns mean anomaly given e and E # - f2M(e,f) returns mean anomaly given e and f # - M2E(e,M) returns eccetric anomaly given e and M # - E2f(e,E) returns true anomaly given e and E # - M2f(e,M) returns true anomay given e and M # - t2E(n,e,t) returns eccetric anomaly given n, e and t # - t2f(n,e,t) returns true anomaly given n, e and t # - M2t(n,M) returns flight time since periapsis given n and M # - f2t(n,e,f) returns flight time since periapsis given n, e and f # - t2M(n,t) returns flight time since periapsis given n and t # ################################################################################ ################################################################################ # ## Package of constants liborb_nrmax = 100; #maximum number of iterations for Newton Raphson algorithm liborb_nrdE = 0.0; #residual value from Newton Raphson iterations liborb_zero = 1.000000000000000000e-08; #limit value to consider somme quantities as null liborb_inf = 1.23456789876543210e1000; #this value stands for infinity value liborb_deg = 1.745329251994329547e-02; #1 degree in radians liborb_gon = 1.570796326794896697e-02; #1 gradian in radians liborb_hpi = 1.570796326794896558e+00; #half pi liborb_dpi = 6.283185307179586232e+00; #double pi liborb_au = 1.495978707000000000e+11; #m liborb_G = 6.674080000000000335e-11; #m^3/kg s^2 liborb_musun = 1.327541252800000000e+20; #m^3/s^2 liborb_mumer = 2.203900081014675781e+13; #m^3/s^2 liborb_muven = 3.249606376090141250e+14; #m^3/s^2 liborb_muear = 3.987256375298450625e+14; #m^3/s^2 liborb_mulua = 4.904338898288770508e+12; #m^3/s^2 liborb_mumar = 4.284176672342150781e+13; #m^3/s^2 liborb_mujup = 1.267525686099165120e+17; #m^3/s^2 liborb_musat = 3.795254329314348000e+16; #m^3/s^2 liborb_muura = 5.796369087341472000e+15; #m^3/s^2 liborb_munep = 6.838681433981858000e+15; #m^3/s^2 liborb_ioang = 1.0; #input and output angles (1.0 for radians | liborb_deg for degrees) liborb_curang= "rad"; ################################################################################ # ## math sub-pack #Magnitude and squared magnitude of vector U liborb_mag2(Ux,Uy,Uz) = Ux*Ux + Uy*Uy + Uz*Uz; liborb_mag (Ux,Uy,Uz) = sqrt( liborb_mag2(Ux,Uy,Uz) ); #Wrap around x within the domain xmin <= x <= xmax liborb_wrap(x,xmin,xmax) = xxmax\ ? liborb_wrap(x-xmax+xmin,xmin,xmax)\ : x; # linear interpolation of the points (0,a) (1,b) lin(a,b,u) = (1-u)*a+u*b; # Euler angles rotations liborb_Rx(x,y,z,a,b,c) = x*( cos(a*liborb_ioang)*cos(c*liborb_ioang)-sin(a*liborb_ioang)*cos(b*liborb_ioang)*sin(c*liborb_ioang) ) - y*( cos(a*liborb_ioang)*sin(c*liborb_ioang) + sin(a*liborb_ioang)*cos(b*liborb_ioang)*cos(c*liborb_ioang) ) + z*sin(a*liborb_ioang)*sin(b*liborb_ioang); liborb_Ry(x,y,z,a,b,c) = x*( sin(a*liborb_ioang)*cos(c*liborb_ioang)+cos(a*liborb_ioang)*cos(b*liborb_ioang)*sin(c*liborb_ioang) ) - y*( sin(a*liborb_ioang)*sin(c*liborb_ioang) - cos(a*liborb_ioang)*cos(b*liborb_ioang)*cos(c*liborb_ioang) ) - z*cos(a*liborb_ioang)*sin(b*liborb_ioang); liborb_Rz(x,y,z,a,b,c) = x* sin(b*liborb_ioang)*sin(c*liborb_ioang) + y* sin(b*liborb_ioang)*cos(c*liborb_ioang) + z*cos(b*liborb_ioang); ################################################################################ # ## conversion from "fixed" cartesian coordinates to keplerian elements #vector specific angular momentum liborb_hx(x,y,z,vx,vy,vz) = y*vz-z*vy; liborb_hy(x,y,z,vx,vy,vz) = z*vx-x*vz; liborb_hz(x,y,z,vx,vy,vz) = x*vy-y*vx; liborb_h2(x,y,z,vx,vy,vz) = liborb_mag2( y*vz-z*vy, z*vx-x*vz, x*vy-y*vx ); #eccentricity vector liborb_ex(mu,x,y,z,vx,vy,vz) = x*(liborb_mag2(vx,vy,vz)*1.0/mu-1.0/liborb_mag(x,y,z)) - vx*(x*vx+y*vy+z*vz)*1.0/mu; liborb_ey(mu,x,y,z,vx,vy,vz) = y*(liborb_mag2(vx,vy,vz)*1.0/mu-1.0/liborb_mag(x,y,z)) - vy*(x*vx+y*vy+z*vz)*1.0/mu; liborb_ez(mu,x,y,z,vx,vy,vz) = z*(liborb_mag2(vx,vy,vz)*1.0/mu-1.0/liborb_mag(x,y,z)) - vz*(x*vx+y*vy+z*vz)*1.0/mu; liborb_rv2C3(mu,x,y,z,vx,vy,vz) = 0.5*liborb_mag2(vx,vy,vz) - mu*1.0/liborb_mag(x,y,z); liborb_rv2p(mu,x,y,z,vx,vy,vz) = liborb_h2(x,y,z,vx,vy,vz)*1.0/mu; liborb_rv2a(mu,x,y,z,vx,vy,vz) = ( aux1=liborb_rv2C3(mu,x,y,z,vx,vy,vz) )**2 < liborb_zero**2\ ? liborb_rv2p(mu,x,y,z,vx,vy,vz)\ : abs(0.5*mu/aux1); liborb_rv2e(mu,x,y,z,vx,vy,vz) = liborb_rv2C3(mu,x,y,z,vx,vy,vz) == 0.0\ ? 1.0\ : 0*( aux1=(liborb_mag2(vx,vy,vz)*1.0/mu-1.0/liborb_mag(x,y,z)) )\ *( aux2=(x*vx+y*vy+z*vz)*1.0/mu )\ + liborb_mag( x*aux1-vx*aux2,\ y*aux1-vy*aux2,\ z*aux1-vz*aux2); liborb_rv2I(mu,x,y,z,vx,vy,vz) = 0*( aux1=liborb_mag(liborb_hx(x,y,z,vx,vy,vz),liborb_hy(x,y,z,vx,vy,vz),0.0) )\ + atan2(aux1,liborb_hz(x,y,z,vx,vy,vz))/liborb_ioang; liborb_rv2O(mu,x,y,z,vx,vy,vz) = (abs(z)/liborb_mag(x,y,z)+abs(vz)/liborb_mag(vx,vy,vz))liborb_zero\ ? acos( (liborb_rv2p(mu,x,y,z,vx,vy,vz)/liborb_mag(x,y,z)-1.0)/aux1)*((x*vx+y*vy+z*vz)<0.0?-1:+1)/liborb_ioang\ : 0*(aux2=(abs(z)/liborb_mag(x,y,z)+abs(vz)/liborb_mag(vx,vy,vz)))\ *(aux3=aux21.0\ ? 2.0*atanh( sqrt((e-1.0)/(e+1.0))*tan(0.5*f*liborb_ioang) )/liborb_ioang\ : 2.0*atan2( sqrt(1.0-e)*sin(0.5*f*liborb_ioang),sqrt(1.0+e)*cos(0.5*f*liborb_ioang) )/liborb_ioang; liborb_E2M(e,E) = e>1.0\ ? (e*sinh(E*liborb_ioang)-E*liborb_ioang)/liborb_ioang\ : (E*liborb_ioang-e*sin(E*liborb_ioang))/liborb_ioang; liborb_f2M(e,f) = e==1.0\ ? 0.5*(aux1=tan(0.5*f*liborb_ioang))*( 1.0 + 0.33333333*aux1*aux1 )/liborb_ioang\ : liborb_E2M(e,liborb_f2E(e,f)); liborb_M2t(n,M) = M*1.0/n; liborb_f2t(n,e,f) = liborb_M2t(n,liborb_f2M(e,f)); liborb_eo2t(mu,a,e,I,O,w,f) = liborb_M2t(liborb_eo2n(mu,a,e,I,O,w,f),liborb_f2M(e,f)); liborb_nr(e,M,E0,itr) = 0*(dE=e<1.0\ ? (E0-e*sin(E0)-M)/(1.0-e*cos(E0))\ : (e*sinh(E0)-E0-M)/(e*cosh(E0)-1.0))\ + itr>0\ ? dE**2>liborb_zero**2\ ? liborb_nr(e,M,E0-dE,itr-1)\ : E0-dE\ : 0*(liborb_nrdE=dE)\ + E0-dE; liborb_t2M(n,t) = n*t; liborb_M2E(e,M) = e==1.0\ ? 1/0\ : liborb_nr(e,M*liborb_ioang,M*liborb_ioang,liborb_nrmax)/liborb_ioang; M2Err(e,M) = e==1.0\ ? 1/0\ : (M*liborb_ioang-liborb_E2M(e,liborb_nr(e,M*liborb_ioang,M*liborb_ioang,liborb_nrmax)))/liborb_ioang; liborb_E2f(e,E) = e>1.0\ ? 2.0*atan2( sqrt(1.0+e)*sinh(0.5*E*liborb_ioang) , sqrt(e-1.0)*cosh(0.5*E*liborb_ioang) )/liborb_ioang\ : 2.0*atan2( sqrt(1.0+e)*sin( 0.5*E*liborb_ioang) , sqrt(1.0-e)*cos( 0.5*E*liborb_ioang) )/liborb_ioang; liborb_M2f(e,M) = e==1.0\ ? 2.0*atan( (aux1=3.0*M*liborb_ioang+sqrt(9.0*M*M*liborb_ioang*liborb_ioang+1))**(1.0/3)-aux1**(-1.0/3) )/liborb_ioang\ : liborb_E2f(e,liborb_M2E(e,M)); liborb_t2E(n,e,t) = liborb_M2E(e,liborb_t2M(n,t)); liborb_t2f(n,e,t) = liborb_M2f(e,liborb_t2M(n,t)); ################################################################################ # ## Help "functions" more_orbital_anomalies=sprintf("\ Anomalies function are:\n\ f2E(e,f) returns eccentric anomaly given e and f\n\ E2M(e,E) returns mean anomaly given e and E\n\ f2M(e,f) returns mean anomaly given e and f\n\ M2E(e,M) returns eccentric anomaly given e and M\n\ E2f(e,E) returns true anomaly given e and E\n\ M2f(e,M) returns true anomay given e and M\n\ t2E(n,e,t) returns eccentric anomaly given n, e and t\n\ t2f(n,e,t) returns true anomaly given n, e and t\n\ M2t(n,M) returns flight time since periapsis given n and M\n\ f2t(n,e,f) returns flight time since periapsis given n, e and f\n\ t2M(n,t) returns flight time since periapsis given n and t\n\n\ Please, type:\n\ print more_orbital_nr\n\ to learn more about accuracy in Newton-Raphson method\n"); liborb_newtonraphson=sprintf("\ Newton-Raphson iteration methods are employed to solve Kepler equations:\n\ M = E - e*sin(E)\n\ M = e*sinh(E) - E\n\ for eccentric anomaly E, for eliptic and hiperbolic cases, respectively.\n\ Convergence may fail depending upon the value of the eccentricity. The closer\n\ to 1 is the eccentricity the harder is the convergence. Iterations are carried\n\ out until:\n\ | E_n - E_{n-1} | < liborb_zero (%.0e by default)\n\ or\n\ number of iterations = liborb_nrmax (%d by default)\n\n\ When recursion limit liborb_nrmax is reached, the \"error\" is saved as:\n\ liborb_nrdE = E_n - E_{n-1}\n\n\ The library also provides the function:\n\ M2Err(e,M)\n\ which allows one to infer the residual error of Newton-Raphson iteration. Such error is the\n\ difference of the resulting E converted back to M' to the original value of M.\n", liborb_zero, liborb_nrmax ); more_orbital_definitions=sprintf("\ Definitions and uniformity:\n\ - p semilatus rectum\n\ - a semimajor axis. In particular case parabolic orbits \"a\" stands for the\n\ semilaltus rectum while for the circular ones, the circumference radius.\n\ - e eccentricity\n\ - I inclination of the orbital plane\n\ - O longitude of the ascending node\n\ - w argument of periapsis\n\ - f true anomaly\n\ - M mean anomaly\n\ - E eccetric anomaly\n\ - n mean motion\n\ - T period\n\ - t flight time since periapsis\n\ - C3 specific mechanical energy\n\ - mu mass parameter (G*mass)\n"); more_orbital_constants=sprintf("\ Builtin constants are:\n\ liborb_zero is the threshold value considered as zero within some\n\ functions such as Newton-Raphson iteration or the planar\n\ orbits constrained to |z+vz|