CELX: Finding a moving observer's current vector.

All about writing scripts for Celestia in Lua and the .cel system
Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

CELX: Finding a moving observer's current vector.

Post #1by buggs_moran » 05.03.2008, 15:51

In Celx, how do you make a vector out of your current position and speed (no object selected) in celx? I do not want to use focus, center or any of the like...

For instance:
I am traveling in space, in general, no aim, no destination, just travelling. Then, suddenly, I have an urge to go to Neptune.

- I know how to get my current position (call it obsPos).
- I know how to get Neptune's position. (call it plaPos).
- The vector (vtoPlanet) from obsPos to plaPos is obsPos-plaPos.
- The vector (vcurrent) is what I need to know how to do.

From there I plan to
- find the angle between the vectors. acos(vcurrent * vtoPlanet)
- find the upvector, (vtoPlanet ^ vcurrent)
- and turn towards the planet with a rotation
--------local yaw=celestia:newrotation(upvector, angle)
--------celestia:getobserver():rotate(yaw)
Homebrew:
WinXP Pro SP2
Asus A7N8X-E Deluxe
AMD Athlon XP 3000/333 2.16 GHz
1 GB Crucial RAM
80 GB WD SATA drive
ATI AIW 9600XT 128M

Vincent
Developer
Posts: 1356
Joined: 07.01.2005
With us: 20 years
Location: Nancy, France

Re: CELX: Finding a moving observer's current vector.

Post #2by Vincent » 05.03.2008, 16:04

buggs_moran wrote:The vector (vcurrent) is what I need to know how to do.

I'm not sure about what you mean by vcurrent, but observer:getorientation() will return the observer's orientation as a quaternion (x, y, z, w):

Code: Select all

obs = celestia:getobserver()
rot = obs:getorientation()

Then you should be able to get the (x, y, z) vector using:

Code: Select all

vect = rot:imag()
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3

chris
Site Admin
Posts: 4211
Joined: 28.01.2002
With us: 23 years
Location: Seattle, Washington, USA

Post #3by chris » 05.03.2008, 17:17

The only way that I think you can get the observer velocity is to take the difference in position between two subsequent frames. More or less this:

Code: Select all

p0 = obs:getposition()
t0 = celestia:gettime()
wait(0)
p1 = obs:getposition()
t1 = celestia:gettime()

v = (p1 - p0) / (t1 - t0)


Now, calling an extra wait to compute the velocity isn't really desirable. You should probably add the code to save the current position and time to the place you're calling wait() now.

--Chris

Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

Post #4by buggs_moran » 06.03.2008, 13:21

Thank you Vincent and Chris.

It is not working the way I had hoped, but you information is useful. I will have to keep trying. I get very strange angles that do not point in the direction I expect. I am sure I am missing something fundamental. I will keep plugging away...
Homebrew:

WinXP Pro SP2

Asus A7N8X-E Deluxe

AMD Athlon XP 3000/333 2.16 GHz

1 GB Crucial RAM

80 GB WD SATA drive

ATI AIW 9600XT 128M

Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

Post #5by buggs_moran » 09.03.2008, 21:23

Okay, I am very confused.

Shouldn't the following code go to my starting position then,
1) get the observer position
2) get the position of the object, planets[i] (from a table)
3) get vector x,y,z for observer and normalize it
4) get a vector from the observer to the object, planets[i] and normalize it
5) find the angle between the vectors
6) find the cross product of the vectors and therefore the "up" vector between 3 & 4
7) turn to the object, planets[i]

or am I being WAY too simplistic? I get the feeling this is the case.

Code: Select all

      
obs = celestia:getobserver()
sol = celestia:find("Sol")
celestia:select(sol)
obs:gotolonglat(sol, math.rad(45), math.rad(0), 1e10)
wait (5.0)


obsPosition = obs:getposition()
objPosition = planets[i]:getposition()

obsrot = obs:getorientation()
v_obs = obsrot:imag()
v_obsn = v_obs:normalize()

v_obj = objPosition - obsPosition
v_objn = v_obj:normalize()

angle = math.acos(v_objn * v_obsn)
upvector = (v_objn ^ v_obsn)
      
local quat=celestia:newrotation(upvector, angle/50)
for i=1,50 do
   celestia:getobserver():rotate(quat)
   wait(0)
end--for
Homebrew:

WinXP Pro SP2

Asus A7N8X-E Deluxe

AMD Athlon XP 3000/333 2.16 GHz

1 GB Crucial RAM

80 GB WD SATA drive

ATI AIW 9600XT 128M

Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

Post #6by buggs_moran » 12.03.2008, 02:07

I am just bumping this in case it got missed... Sorry if it aggravates anyone...
Homebrew:

WinXP Pro SP2

Asus A7N8X-E Deluxe

AMD Athlon XP 3000/333 2.16 GHz

1 GB Crucial RAM

80 GB WD SATA drive

ATI AIW 9600XT 128M

Vincent
Developer
Posts: 1356
Joined: 07.01.2005
With us: 20 years
Location: Nancy, France

Post #7by Vincent » 12.03.2008, 06:49

buggs_moran wrote:I am just bumping this in case it got missed... Sorry if it aggravates anyone...

Buggs,

You can also simply get v_obsn using:

Code: Select all

v_obs = sol:getposition() - obsPosition
v_obsn = v_obs:normalize()

Or more generally:

Code: Select all

v_obs = planet[i-1]:getposition() - obsPosition
v_obsn = v_obs:normalize()

I'm not sure this will fix your problem, though.
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3

Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

Post #8by buggs_moran » 12.03.2008, 09:48

The problem with both of those is that it will not give me the angle between my current direction and the object I want to go to...
Homebrew:

WinXP Pro SP2

Asus A7N8X-E Deluxe

AMD Athlon XP 3000/333 2.16 GHz

1 GB Crucial RAM

80 GB WD SATA drive

ATI AIW 9600XT 128M

Vincent
Developer
Posts: 1356
Joined: 07.01.2005
With us: 20 years
Location: Nancy, France

Post #9by Vincent » 12.03.2008, 10:58

buggs_moran wrote:The problem with both of those is that it will not give me the angle between my current direction and the object I want to go to...

What about defining upvector as the upvector for observer?

Code: Select all

upvector = celestia:newvector(0, -1, 0)
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3

Vincent
Developer
Posts: 1356
Joined: 07.01.2005
With us: 20 years
Location: Nancy, France

Post #10by Vincent » 12.03.2008, 11:39

Buggs,

Another alternative would be to convert obsPosition, objPosition and solPosition from universal coodinates to the observer's local frame coordinates:

Code: Select all

obsPosition = obs:getposition()
objPosition = obj:getposition()
solPosition = sol:getposition()

obs_frame = celestia:newframe("observer", sol)

obsPos = obs_frame:to(obsPosition)
objPos = obs_frame:to(objPosition)
solPos = obs_frame:to(solPosition)

v_obs = solPos - obsPos
v_obsn = v_obs:normalize()

v_obj = objPos - obsPos
v_objn = v_obj:normalize()

angle = math.acos(v_objn * v_obsn)

Then, you could effectively define upvector as:

Code: Select all

v_up = (v_objn ^ v_obsn)
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3

Topic author
buggs_moran
Posts: 835
Joined: 27.09.2004
With us: 20 years 4 months
Location: Massachusetts, USA

Post #11by buggs_moran » 13.03.2008, 00:24

But the problem is that I do not want to reference another body like the Sun... I am essentially trying to duplicate the "center" command, without using the center command...
Homebrew:

WinXP Pro SP2

Asus A7N8X-E Deluxe

AMD Athlon XP 3000/333 2.16 GHz

1 GB Crucial RAM

80 GB WD SATA drive

ATI AIW 9600XT 128M

Vincent
Developer
Posts: 1356
Joined: 07.01.2005
With us: 20 years
Location: Nancy, France

Post #12by Vincent » 13.03.2008, 12:00

buggs_moran wrote:But the problem is that I do not want to reference another body like the Sun... I am essentially trying to duplicate the "center" command, without using the center command...

Well, here's another way to do that:

Code: Select all

obsPosition = obs:getposition()
objPosition = obj:getposition()

d_obj = objPosition:distanceto(obsPosition)

obs:gotodistance(obj, d_obj)
wait(3)
@+
Vincent

Celestia Qt4 SVN / Celestia 1.6.1 + Lua Edu Tools v1.2
GeForce 8600 GT 1024MB / AMD Athlon 64 Dual Core / 4Go DDR2 / XP SP3


Return to “Scripting”