Lambert method for in-plane transfer

I'm trying to solve the transfer between a circular orbit with 200km radius and an orbit with 200km perigee and 8000km apogee.

The optimal transfer is hoffman, however, izzo.lambert from poliastro gives different result.

My code:

from astropy import units as u
from poliastro.bodies import Earth
from poliastro.iod import izzo
from poliastro.core.elements import coe2rv
from poliastro.util import norm
import math
import time

Earth_k = Earth.k
Req = Earth.R.to(u.km).value

def keplerian2cartesian(kepler):

a=(kepler[0]+kepler[1]+Req*2)*1000/2 * u.m
e=(kepler[0]-kepler[1])/(kepler[0]+kepler[1]+Req*2)

(R,V)=coe2rv(Earth.k,a,e,kepler[2],kepler[3],kepler[4],kepler[5])

return [R * u.m] + [V * u.m/u.s]

# Checking different transfer times
def transfer_time(DV_min,vector0,vector,period):

init_t=10
t_value=init_t
(r0,r,v0,v)=(vector0[0],vector[0],vector0[1],vector[1])

while init_t<period:

tof = init_t * u.min

try:
(f_v0, f_v), = izzo.lambert(Earth_k, r0, r, tof)
except:
init_t+=1
continue

DV0=norm(f_v0-v0).value*1000
DV=norm(f_v-v).value*1000

if(DV0+DV<DV_min):
t_value=init_t
DV0_value=DV0
DV_value=DV
DV_min=DV0+DV

init_t+=1

return (t_value,DV_value,DV0_value)

# Checking different initial and final true anomalies
def transfer_tetta(kepler0,kepler):
DV_min=100000
final_tetta=0

a=(kepler[0]+kepler[1]+Req*2)*1000/2
period=math.ceil(math.sqrt((a**3/Earth.k.value)*4*(math.pi)**2)/60)

while final_tetta<360:
init_tetta=0
while init_tetta<360:
vector0=keplerian2cartesian(kepler0 + [init_tetta*math.pi/180])
vector =keplerian2cartesian(kepler  + [final_tetta*math.pi/180])
try:
(init_t,DV,DV0)=transfer_time(DV_min,vector0,vector,period)
except:
init_tetta+=5
continue

if DV+DV0<DV_min:
DV_min=DV+DV0
(t_value,DV0_value,DV_value,init_tetta_value,final_tetta_value)=(init_t,DV0,DV,init_tetta,final_tetta)

init_tetta+=5
final_tetta+=5

print("t: ", t_value, "DV_init: ", DV0_value,"DV_final: ", DV_value)
print("DV: ", DV_min)
print("Init tetta: ", init_tetta_value, "Final tetta: ", final_tetta_value)

# 1->2
transfer_tetta([200,  200, 64.3*math.pi/180, 0, 300*math.pi/180],[8000, 200, 64.3*math.pi/180, 0, 300*math.pi/180])

• – astrojuanlu Apr 12 '20 at 15:48
• @astrojuanlu Yes, thanks. – Leeloo Apr 12 '20 at 15:51
• @PeterNazarenko I think your tag edits (adding Python) are good, one is still pending and I assume will be accepted soon. There are several more questions tagged with poliastro that don't have it yet. Some still have room for one more tag. Some of mine don't but please feel free to delete a less-important one and replace it with Python if you like. Thanks! – uhoh Sep 19 '20 at 12:20
• @uhoh Ok, thank you! – Peter Nazarenko Sep 19 '20 at 15:44

You need to take into account that the Hohmann transfer and the Lambert solution receive different inputs and are therefore not equivalent.

• The Hohmann transfer is known to be the optimal two-impulse transfer between two coplanar, circular orbits. There are several proofs to this. The initial and final states are defined by position and velocity. Therefore, we already know what are the initial and final velocities we want to achieve, and the Hohmann transfer just gives us the two impulses needed to reach the final state.
• The Lambert problem "is concerned with the determination of an orbit from two position vectors and the time of flight". In other words: the initial velocity before the transfer and the final velocity after the transfer are not specified. Therefore:
• When the transfer angle is 180 degrees, there is an infinite number of trajectories with the same departure and arrival velocity that take us from the initial to the final position.
• The algorithm doesn't know whether the initial and final orbits are coplanar or not, because there are no such orbits. Remember: we only have the position vectors.
• The algorithm will tell us which velocities does the transfer orbit have at the initial and final position. But it's on us to compute the total cost of the transfer!
• The time of flight is an input, not an output.

In my opinion they can't be compared, because they don't have the same amount of information about the problem. They serve different purposes. I might be wrong about this, but I would need you to describe in detail what exactly do you want to achieve.

If the objective is just checking that "given two positions separated 180 degrees and the time of flight that results from the Hohmann transfer, I want to see whether the Lambert method gives me the same solution", the question makes no sense, and the problem is ill-posed anyway.

If both orbits are in the same plane, then the optimal solution will be called hohmann transfer where you need to start from perigee of the inner orbit towards an apogee of the outer orbit. So you will start from 200 km perigee and end at 8000 km apogee.

I hope this is clear now.

• Welcome to space! Do you have any thoughts on why the Lambert solver is recommending impulses at true anomalies other than 0 and 180 degrees? – uhoh Apr 12 '20 at 6:15
• I think you need an optimizer along with the Lambert solver. Lambert solver is not capable of getting the optimal solution between two orbits. It just calculates the needed Delta V between the given positions and time of flight. – Ahmed Abbdein Apr 12 '20 at 6:23
• I see. I'm no expert in this, but I wonder if it would be good to add that additional explanation back into to your answer post? In Stack Exchange comments are considered temporary and some readers don't read them. – uhoh Apr 12 '20 at 6:35
• @AhmedAbbdein I made a loop through different true anomalies and time of flights. So, it should give expected result. Do you have an experience with izzo.lambert() from poliastro? – Leeloo Apr 12 '20 at 12:52