View License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video

Highlights from
Convert ECI to ECEF Coordinates

4.4 | 11 ratings Rate this file 37 Downloads (last 30 days) File Size: 3.83 KB File ID: #28233 Version: 1.7
image thumbnail

Convert ECI to ECEF Coordinates


Darin Koblick (view profile)


17 Jul 2010 (Updated )

Transform ECI position, velocity and acceleration to ECEF position, velocity & acceleration.

| Watch this File

File Information

Convert ECI (CIS, Epoch J2000.0) Coordinates to WGS 84 (CTS, ECEF) Coordinates. This function has been vectorized for speed.

Example Function Call:
>> [r_ECEF v_ECEF a_ECEF] = ECItoECEF(JD,r_ECI,v_ECI,a_ECI);

JD is the Julian Date vector [1 x N] (units are in days)
r_ECI is the position vector [3 x N] (any units are permitted)
v_ECI is the velocity vector [3 x N] (any units are permitted)
a_ECI is the acceleration vector [3 x N] (any units are permitted)


Julian Date To Greenwich Mean Sidereal Time inspired this file.

MATLAB release MATLAB 7.5 (R2007b)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (30)
20 Feb 2017 Sulav

Sulav (view profile)


Is this program good for converting a vector in ECI frame to a vector in ECEF frame? ( Not a position vector )

02 Sep 2016 An Nguyen

11 Jul 2016 Graeme Ramsey

You can generate the ECI to ECEF 3X3 transformation matrix using the built-in MATLAB command dcmeci2ecef

Comment only
26 May 2016 Xun Pan

04 Mar 2016 Yaguang Yang

Hi Darin,

I ran the program and see the following error message. May I miss something?

Undefined command/function 'bsxfun'.

Error in ==> ECItoECEF>MultiDimMatrixMultiply at 71
C = sum(bsxfun(@times,A,repmat(permute(B',[3 2 1]),[size(A,2) 1 1])),2);

Error in ==> ECItoECEF at 62
r_ECEF = squeeze(MultiDimMatrixMultiply(T3D(THETA),r_ECI));

Error in ==> spacecraft_orbit at 40
[r_ECEF v_ECEF a_ECEF] = ECItoECEF(jdv,rOrbit,vOrbit,aOrbit);


Comment only
21 Feb 2015 Manu

Manu (view profile)

I think the routine is wrong. As mentioned by drake in 2012, there needs to be a precession matrix to go from J2000 to current epoch of ECEF, and that involves a change of the z-axis. The routine computes the new position through a simple rotation around the z-axis. I have compared the results from this routine to conversions using other algorithms (in particular JPL NAIF SPICE routines) and I find differences of ~ 20 km in x, y and z coordinates for times in the year 2015. I am not sure where the differences come from, but the absence of precession is likely the problem.

01 Sep 2013 Darin Koblick

Darin Koblick (view profile)


The two code lines you are referencing are trying to find the midnight that occurs before the provided Julian Date.

As written, the first check will be true if the Julian date occurs after midnight and 12+ hours before the time.

As written, the second check will be true if the Julian date occurs after midnight and less than 12 hours before the time.

If both checks are true, the code will use the last midnight that occurred. This is the desired functionality.

Because I am rounding down on the Julian date and subtracting a half day, there is no possible way that jd could be less than jdMin.


Comment only
29 Aug 2013 Chad Hawes

29 Aug 2013 Chad Hawes

In your JD2GMST function, I have a question related to the following two lines:

jd0(jd>jdMin) = jdMin(jd>jdMin);
jd0(jd>jdMax) = jdMax(jd>jdMax);

This appears to be limiting the Julian day between a lower bound and an upper bound. Don't you want the first line to be:

jd0(jd<jdMin) = jdMin(jd<jdMin);

Otherwise, it would appear that no actual lower bounding occurs...


Comment only
27 Mar 2013 João Carneiro

I have been importing some ECI data from the OrbitTools C++ library and have stumbled upon some weird behavior.

In MATLAB I am using your functions to transform ECI to ECEF and then using the MATLAB function, ecef2geodetic to transform into normal azimuth/elevation/height coordinate space.

The weird behavior is that despite having smooth ECI data (smooth as in no jumps in the data) as inputs, I am getting discontinuous ECEF data (graph for r_ECEF(1,:) and r_ECEF(2,:) looks like saw). This is happening for GOES-8 and GOES-15 satellite data.

What is weirder is that on a macro scale (ignoring variations, including the sudden discontinuities), the position of the satellite in the mapa mundi seems to be correct.

28 Jun 2012 Darin Koblick

Darin Koblick (view profile)


J2000 is factored into the ECI to ECEF conversion routine through the call to JD2GAST.m (converts Julian Date to Greenwhich Apparent Sidereal Time). In order to do this, the effects of nutation are considered, and depend on the correct number of Julian centuries since J2000.

Comment only
25 Jun 2012 drake

drake (view profile)

Dear Darin,

It seems that this code considers the rotaion about Z-axis, or the earth's rotation axis only. However, the most commonly used ECI frame is J2000 which is defined at 1 January 2000, so I believe the effects of precession and nutation should be considered in the conversion between ECI(J2000) and ECEF.
Please let me know your opinion.

Comment only
28 May 2012 Darin Koblick

Darin Koblick (view profile)


You are correct, thank you for spotting that mistake. I should have left everything in degrees since the mean obliquity of the ecliptic is referenced directly in the final computation.
The new parameters for the mean obliquity should be:

EPSILONm = 23.439291-0.0130111.*T - 1.64E-07.*(T.^2) + 5.04E-07.*(T.^3);

This corresponds to the estimates contained in Vallado, Fundamentals of Astrodynamics and Applications, Second edition, (EQ 3-53). 2001.

Thank you again for double checking my work.

Comment only
22 May 2012 Johan

Johan (view profile)

This function is great.
Although i think i found a mistake in your JD2GAST file.
When calculating the EPSILONm shouldn't the first number be 84381.448 and not 84381448 to make sure EPSILONm is calculate in arcseconds.
Shouldn't you convert EPSILONm from arcseconds to degrees like you did with dPSI and dEPSILON?

08 Apr 2012 Darin Koblick

Darin Koblick (view profile)

The following ECI coordinate information

rECI = [-2392.11241452386

vECI = [3.27682054057320

t = 2453937.82777778;

Will yield an ECEF position and velocity of

rECEF = [-15615.6915464865

vECEF = [-0.253618011215938

This was obtained using the routines provided by CelesTrak found from

The ECItoECEF.m routine I posted on the FileExchange comes very close to this with the following vectors:

rECF = [ -15618.7911316673

vECF = [-0.253618011215938

The problem is your ECEF position and velocity vectors do not correspond to each other.

A very easy way to check this is to compute the magnitude of your position vectors.

The magnitude of the first ECI position vector you have provided is: 26,366.726420485 km

The magnitude of the ECEF solution should be exactly the same as the magnitude in the ECI reference frame.

The magnitude of your ECEF position vector is 31,124.2960748149 km.

Hopefully this solves your problem.

Comment only
08 Apr 2012 Muhammad Shaikh

I am only posting here first five values of each of the vectors you asked for. They are actually long arrays of more than 1000 values.

GPS XYZ Position in ECI:
-0.239211241452386 -1.707812336086469 1.994541959448508
-0.238883560243254 -1.707992218920763 1.994429990702043
-0.238555873840528 -1.708172064621368 1.994317978585847
-0.238228182457349 -1.708351873071436 1.994205923172916
-0.237900485894857 -1.708531644380220 1.994093824395386

GPS XYZ Velocity in ECI:
3.276820540573197 -1.799032931682451 -1.119482444956503
3.276872512702608 -1.798661610033275 -1.119916159551723
3.276924413465574 -1.798290250160732 -1.120349848764825
3.276976242828717 -1.797918852306742 -1.120783512313681
3.277028000823877 -1.797547416246293 -1.121217150461423

GPS XYZ Position in ECEF:
2.486257771277870 -0.525992080845330 1.796962071713202
2.486219408921021 -0.526173379273422 1.796962071713202
2.486181033343849 -0.526354674903637 1.796962071713202
2.486142644546566 -0.526535967734976 1.796962071713202
2.486104242529370 -0.526717257766510 1.796962071713202

GPS XYZ Velocity in ECEF:
-1.932463623657266 -1.485322200484253 -1.119482444956503
-1.933172003035996 -1.485054282646371 -1.119916159551723
-1.933880318496407 -1.484786276830892 -1.120349848764825
-1.934588569639623 -1.484518183130969 -1.120783512313681
-1.935296756821210 -1.484250001479990 -1.121217150461423

Juliandate Vector:

Comment only
07 Apr 2012 Darin Koblick

Darin Koblick (view profile)

The MATLAB function juliandate.m should be fine. Can you please post the epoch, the position/velocity vector in ECI coordinates, and your ECF solution?

Comment only
07 Apr 2012 Muhammad Shaikh

Thanks Darin for your reply.
I am using matlab function 'juliandate' to convert my time to julian date format. I have searched whether it is a J2000 format but could not find anything on Mathworks page. Can you please help me for this as well.

Comment only
05 Apr 2012 Darin Koblick

Darin Koblick (view profile)

Check to make sure your time vector is in J2000 format, not Unix Time (epoch should be starting 01/01/2000 12:00:00).

Comment only
04 Apr 2012 Muhammad Shaikh

I am having some problems in calculating ECEF data. In my calculations, the satellite positions are calculated at the wrong side of Earth (globe) in the same plan they are now being calculated. Can you guide me for this please? Note, the data I am giving to the function is verified and I can easily say that my calculations can wrong, the data can't be. Please help.

27 Feb 2012 Martin Fuchs

Maybe something like this but I am not sure ???

if (~isempty(a_ECEF) && (~isempty(r_ECEF)) a_ECI = MultiDimMatrixTranspose(T3D(THETA))*a_ECEF' + 2*MultiDimMatrixTranspose(Tdot3D(THETA,omega_e))*v_ECEF' + MultiDimMatrixTranspose(Tdotdot3D(THETA,omega_e))*r_ECEF'; else a_ECI = []; end

function Tdot = Tdotdot3D(THETA,omega_e)
Tdot = zeros([3 3 length(THETA)]);
Tdot(1,1,:) = -omega_e^2.*cosd(THETA);
Tdot(1,2,:) = -omega_e^2.*sind(THETA);
Tdot(2,1,:) = -Tdot(1,2,:);
Tdot(2,2,:) = Tdot(1,1,:);

Comment only
27 Feb 2012 Martin Fuchs

Could you also provide accelerations ?

10 Jan 2012 Syed Zohaib Ali

Hi Darin

Now its working fine. I was passing JD argument in a wrong way.


Comment only
09 Jan 2012 Darin Koblick

Darin Koblick (view profile)


Send me your test case and I will take a look at it.


Comment only
09 Jan 2012 Syed Zohaib Ali


I am facing problem in converting 1441 values of position and velocity vectors from ECI to ECEF. It seems that function works fine. When 93 out of 1441 values were passed to the function it gave values for x,y & z components which I thought are correct but when 186 out of 1441 values were passed to the function, the initial 93 x & y values were different from the one that I got by passing only 93 values, z components were the same. similarly when more values were passed the x&y were different except the z-component.
can you please guide what could be the problem?

Comment only
26 Nov 2011 lin yue

17 Dec 2010 7ate9

7ate9 (view profile)

Excellent function - fast, and I verified a limited number of test cases. Thank you!

01 Nov 2010 Ismail

Ismail (view profile)

Ok .. now it works fine !
Thanks Darin !

Comment only
28 Oct 2010 Darin Koblick

Darin Koblick (view profile)


You are more than likely using the wrong dimensions for r_ECI.
This is specified in my input requirements as [3 x N].

r_ECI = [10.7148713368681e+003; ...
-7.10368453661470e+003; ...

In other words, transpose the r_ECI input for the correct answer.

Comment only
27 Oct 2010 Ismail

Ismail (view profile)


Is it normal to obtain six values in the r_ECEF and v_ECEF matrices instead of just 3 ?

** Example **
10.7148713368681e+003 -7.10368453661470e+003 -22.0702973475812e+003


-7.72362036417280e+003 5.12056195755438e+003 15.9089729291096e+003
-13.0369714274984e+003 8.64317726477505e+003 26.8533169340802e+003
10.7148713368681e+003 -7.10368453661470e+003 -22.0702973475812e+003

-3.39040857672452e+000 86.2958941276462e-003 1.16863824970067e+000
-3.55490372276425e+000 -1.29159124693780e+000 -2.49278765365527e+000
3.38461399614162e+000 754.648420343670e-003 1.09531334972829e+000


Comment only
01 Mar 2012 1.1

Added acceleration transformation update to code. This now supports all position, velocity and acceleration vectors.

01 Mar 2012 1.4

Updated vector inputs and outputs to include the acceleration term.

02 Mar 2012 1.5

Added another code attachment since the last attachment didn't appear to make it through.

29 May 2012 1.7

Updated mean obliquity of elliptic equation to be consistent with units. All units in this equation are in degrees.

Contact us