Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Lork
Oct 15, 2007
Sticks to clorf

Subyng posted:

Xposting from games forum since this is probably a better place to ask? Anyone have any idea why my player is moving when it shouldn't be? In Unity, I'm trying to keep them at the origin. I have on every FixedUpdate() player.transform.position = Vector3.zero (or player.transform.position = player.transform.position - player.transform.position) after my actual movement code (which uses Rigidbody.Addforce) so, the player should stay at the origin, right? But it doesn't, it still moves, just slower. I've tried searching but haven't really come up with any answers. There are no animations.

I read about some discrepancies with an object's transform and it's rigidbody position, but setting playerrigidbody.position = Vector3.zero instead makes no difference.

Before and after that line I print out the value of the transform, they're both (0,0,0). I know that physics are applied after FixedUpdate so what I would expect (aside from the transform that I print to match what the editor shows me) is that the first print statement will show me some non-zero vector (due to the movement being applied in the previous loop's physics step) and the second print statement to show (0,0,0) because I just zero'd it out in the line before.

Also, if I comment out the movement code entirely or fix the players position, when I press play, the players position gets slightly offset from the origin for no apparent reason.

What the heck is going on? :psyduck:

edit: I simplified the movement code. Previously my player was moving under the effects of gravity and thrust. I got rid of the gravity component. My print statements are showing what I expected now, but my player is still moving when it should be being reset to (0,0,0) every FixedUpdate().


When you say the player is moving, do you mean they're moving farther and farther away from the origin, or that they visibly move just a little bit and then zip back to the origin repeatedly? Can you post your unabridged Update and FixedUpdate here?

Lork fucked around with this message at 01:40 on May 26, 2016

Adbot
ADBOT LOVES YOU

Obsurveyor
Jan 10, 2003

Subyng posted:

edit: I simplified the movement code. Previously my player was moving under the effects of gravity and thrust. I got rid of the gravity component. My print statements are showing what I expected now, but my player is still moving when it should be being reset to (0,0,0) every FixedUpdate().

Have you confirmed with a second object that the player is actually moving and it's not the camera?

Subyng
May 4, 2013
They are moving farther and farther from the origin. I can confirm its the player and not the camera moving because 1)the position in the editor changes and 2) the player is moving in the editor scene view.

Here's some more information that I just discovered: when my player is accelerating, they drift away from the origin. When my player is moving at a constant velocity, their position does not change, which is the expected behaviour. That suggests to me that the drift is due to the difference in velocity at every update. But I don't understand why that's happening.

code:
void FixedUpdate () {

		for (int i = 0; i < go.Length; i++) {
			ApplyAcceleration (i, Vector3.zero + GetThrust (i));
		}
		go [0].transform.position = go [0].transform.position - go [0].transform.position;
}

	public void ApplyAcceleration(int goIndex, Vector3 gVector){
		Rigidbody rb = go[goIndex].GetComponent<Rigidbody> ();
		rb.AddForce (gVector, ForceMode.Acceleration);
	}

	public Vector3 GetThrust(int goIndex){
		Body body = go [goIndex].GetComponent<Body> ();
		float thrust = body.maxThrust * body.Thrust * timeScale;
		Vector3 gVector = go [goIndex].transform.forward * thrust;
		return gVector;
	}

This is everything that hasn't been commented out. My player is go[0].

Subyng fucked around with this message at 03:00 on May 26, 2016

Triarii
Jun 14, 2003

The sequence of events is this:

1. Your FixedUpdate(). Some acceleration is applied to the rigidbody.
2. The engine's physics tick. The rigidbody's velocity and acceleration takes effect and moves the object.
3. (Most of the time) The Update() step occurs, and then the scene is rendered. You see the object at a non-zero position.
4. goto 1.

Subyng
May 4, 2013
That...makes sense. Thanks

So I need to be able to modify the position after the physics step...urgh

Or alternatively, change all my movement vectors so the player never even moves

Subyng fucked around with this message at 03:16 on May 26, 2016

Triarii
Jun 14, 2003

Subyng posted:

That...makes sense. Thanks

So I need to be able to modify the position after the physics step...urgh

Or alternatively, change all my movement vectors so the player never even moves

Obviously I don't know your whole situation, but if all you're trying to do is keep the player in the middle of the screen, you generally want to let the player move and keep the camera centered on him.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

Subyng posted:

That...makes sense. Thanks

So I need to be able to modify the position after the physics step...urgh

Or alternatively, change all my movement vectors so the player never even moves

I'm not sure exactly what you're up to, but when I was working on an infinite jumper in Unity, I pinned the player in place, and moved the entire world around him. That worked like a charm.

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

Is there a reason why the player needs to be physics enabled at the same time as being pinned to the origin?

Subyng
May 4, 2013

Dr. Stab posted:

Is there a reason why the player needs to be physics enabled at the same time as being pinned to the origin?

Nope! But I just changed it so that the player does not have any physics applied to it. Unfortunately I still need the ability to "undo" a physics step for something else. Even manually changing a rigidbody's position with rigidbody.position, according to the documentation, that change is only applied during the physics step and not instantaneously.

Uhh Nope
May 20, 2016

Subyng posted:

Nope! But I just changed it so that the player does not have any physics applied to it. Unfortunately I still need the ability to "undo" a physics step for something else. Even manually changing a rigidbody's position with rigidbody.position, according to the documentation, that change is only applied during the physics step and not instantaneously.

Just a thought: Does trying to set the Transform's position at an Update() step work? I'm pretty sure this also moves the rigidbody and would allow you to move it outside of a FixedUpdate() step.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
Are there any good guides or tutorials for how to set up a system to handle entity logic via scripts in a native program written in C++? As far as I can tell setting up a C/C++ program to use Python or LUA for a function isn't too complicated a task, but I'd love some guidance on how to set up a system in a reasonable way such that I can write entity specific logic in separate scripts so I can do some rapid prototyping/hotswap code for balancing.

Mr Shiny Pants
Nov 12, 2012

Subyng posted:

Nope! But I just changed it so that the player does not have any physics applied to it. Unfortunately I still need the ability to "undo" a physics step for something else. Even manually changing a rigidbody's position with rigidbody.position, according to the documentation, that change is only applied during the physics step and not instantaneously.

Any reason why "IsKinematic" won't work?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Joda posted:

Are there any good guides or tutorials for how to set up a system to handle entity logic via scripts in a native program written in C++? As far as I can tell setting up a C/C++ program to use Python or LUA for a function isn't too complicated a task, but I'd love some guidance on how to set up a system in a reasonable way such that I can write entity specific logic in separate scripts so I can do some rapid prototyping/hotswap code for balancing.
You need to actually understand the languages to understand their C bindings, so start there if you haven't already.

Python is kind of complicated but Lua's C API is very simple.

I'd recommend starting here:
https://www.lua.org/pil/24.html

Lua's API is almost entirely stack manipulation. Any call to the Lua API consumes some number of stack arguments and pushes more on to the stack. When you call a Lua function from the Lua API, you specify how many results you want, and it extends or truncates the result set to the number that you specified.

The other important part of this is that all of the evaluation data exists in a slot, and any Lua call that looks at a single value accepts an index that references a slot. Positive indexes are relative to the start of the argument list passed to the function, negative indexes are relative to the top of the stack, and there are a few special indexes like the registry.

The one very important limitation of all of this is that object references ONLY exist in Lua's internal environment. There is no way to get a reference to a Lua object as a value in the C code. If you want a value that represents a Lua object, then you need something like a lookup table that you can use to find the object by looking in the Lua state.

The reverse isn't true. You can create "userdata" objects, which are pointers to data with lifetime managed by Lua, or "light userdata" objects, which are just raw pointers that Lua doesn't do any lifetime management on.

Subyng
May 4, 2013
Thanks for all the input, everyone.

Mr Shiny Pants posted:

Any reason why "IsKinematic" won't work?

IsKinematic makes the object unaffected by physics. I need the object to be affected by physics, but with the ability to instantly undo the change. I might be able to set isKinematic to true, move the object,and then set it back to false? I'll need to experiment with that.

What I'm trying to do is make the game real-life scaled. Gameplay implications aside (I'm just making this for fun, it doesn't have to be truly "playable"), I'm trying to find a way to get around floating point limitations. For example, I have the player at the origin, and a planet 9400units (1km = 1 unit, largest scale I can have, for various reasons). The player will be falling toward the planet, but because they are fixed at the origin, actually the planet is moving toward the player. Except at that distance, the planet moves just 0.0001 units per physics step, which is smaller than my resolution since you can only have 7 significant digits, so the planet won't move.

Previously, I had a pretty nice solution where I would accumulate the displacement vector (how much it was supposed to move) in a variable and at each FixedUpdate()I would add that displacement to the planet's position. I check if the planet actually changed position, and if not, the displacement vector grows in magnitude by the amount it "should have moved" until it crosses the "resolution threshold" and cause the planet to actually change position, at which point I would reset that displacement vector to zero. This relied on me knowing how much the player is supposed to displace, which I only know by applying a force to the player, storing the displacement in a variable, then resetting the player back to the origin.

Since the player is no longer subject to forces, when I apply a force to the planet instead, and it doesn't move, I don't know how much it would have moved if not for the resolution limit.

Subyng fucked around with this message at 23:44 on May 26, 2016

Obsurveyor
Jan 10, 2003

Subyng posted:

IsKinematic makes the object unaffected by physics. I need the object to be affected by physics, but with the ability to instantly undo the change. I might be able to set isKinematic to true, move the object,and then set it back to false? I'll need to experiment with that.

Have you tried the Rigidbody.MovePosition/MoveRotation? These are what you're supposed to use in FixedUpdate to tell physics about any manual changes you're making.

Mr Shiny Pants
Nov 12, 2012

Subyng posted:


Since the player is no longer subject to forces, when I apply a force to the planet instead, and it doesn't move, I don't know how much it would have moved if not for the resolution limit.

Why not do the calculation yourself instead of letting Unity do it and use that? You would only have to do it to reach the resolution threshold and let Unity take over from there.

At these distances I would not even calculate it and just fake it, would you see the difference as a player?

Game development seems to be all about smoke and mirrors.

Mr Shiny Pants fucked around with this message at 15:17 on May 27, 2016

Subyng
May 4, 2013

Obsurveyor posted:

Have you tried the Rigidbody.MovePosition/MoveRotation? These are what you're supposed to use in FixedUpdate to tell physics about any manual changes you're making.

Yeah, and I managed a solution using rigidbody.position and using a variable attached to a script to store an objects position on the previous frame, and using an invisible rigidbody placed at the origin to represent the far away object. I apply physics to this invisible object and apply the translation to the far away object. Not the cleanest way of doing it but it works.

Mr Shiny Pants posted:

Why not do the calculation yourself instead of letting Unity do it and use that? You would only have to do it to reach the resolution threshold and let Unity take over from there.

At these distances I would not even calculate it and just fake it, would you see the difference as a player?

Game development seems to be all about smoke and mirrors.

I thought about doing the calculation manually like that, but I thought it might cause some weirdness since apparently FixedUpdate does not use a fixed timestep.

As for faking it, yeah, I mean I want to get it as close to real as possible just for the satisfaction of it. What I think is neat about my "accumulated displacement" solution is that a far away object might skip ahead and instantaneously move a distance of 10 timesteps ahead, but the object is so far away that you don't notice that the object is moving at a lower temporal resolution than nearby ones. There's your smoke and mirrors ;)

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe

OneEightHundred posted:

You need to actually understand the languages to understand their C bindings, so start there if you haven't already.

Python is kind of complicated but Lua's C API is very simple.

I'd recommend starting here:
https://www.lua.org/pil/24.html

Lua's API is almost entirely stack manipulation. Any call to the Lua API consumes some number of stack arguments and pushes more on to the stack. When you call a Lua function from the Lua API, you specify how many results you want, and it extends or truncates the result set to the number that you specified.

The other important part of this is that all of the evaluation data exists in a slot, and any Lua call that looks at a single value accepts an index that references a slot. Positive indexes are relative to the start of the argument list passed to the function, negative indexes are relative to the top of the stack, and there are a few special indexes like the registry.

The one very important limitation of all of this is that object references ONLY exist in Lua's internal environment. There is no way to get a reference to a Lua object as a value in the C code. If you want a value that represents a Lua object, then you need something like a lookup table that you can use to find the object by looking in the Lua state.

The reverse isn't true. You can create "userdata" objects, which are pointers to data with lifetime managed by Lua, or "light userdata" objects, which are just raw pointers that Lua doesn't do any lifetime management on.

Thanks for this. If I'm understanding everything correctly, if I do decide to go with Lua, and I want my scripts to be able to access certain data structures in my model (like for instance a full array of all other entities,) I can use light userdata objects? Having copies of everything for both the application as well as the lua environment seems unfeasible just in terms of time spent on memory operations.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Joda posted:

Thanks for this. If I'm understanding everything correctly, if I do decide to go with Lua, and I want my scripts to be able to access certain data structures in my model (like for instance a full array of all other entities,) I can use light userdata objects? Having copies of everything for both the application as well as the lua environment seems unfeasible just in terms of time spent on memory operations.
Yes, though obviously you need to be careful about not letting light userdata linger in the Lua environment after it's been freed. The way I'd recommend doing it is having a single proxy object (table) in Lua that contains a light userdata value and handles all of the calls to it, and remove the light userdata when your C/C++ code frees the object.

There are Lua binding libraries that can implement some of this for you too, but I've never bothered because the C API is so simple.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul
If I have a cylinder of radius x units perpendicular to and intersecting a plane, how can I calculate the required z value for the cylinder relative to the plane if I want a curve of exactly y units of cylinder to be showing through the plane?



For example, if the plane is at z=0, and the cylinder has a radius of 6.2428 units, where do I place the z of the cylinder so that the height of the curve on one side of the plane is precisely 2.002 units?

I would really appreciate it if someone could help break this down into discrete operations I can convert to code.

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

Some back of the envelope math says that z = sqrt(x^2 - (y^2)/4)

Subyng
May 4, 2013

Dr. Stab posted:

Some back of the envelope math says that z = sqrt(x^2 - (y^2)/4)

Yup. Draw a line from the middle of the cylinder to where it intersects the plane. That's the hypotenuse of a right angle triangle. Then use the pythagorean theorem.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

Dr. Stab posted:

Some back of the envelope math says that z = sqrt(x^2 - (y^2)/4)

Thank you for the reply. I tried that formula, but the result only filled about 80% of the space (I was trying to show one unit-height of arc.)

Subyng posted:

Yup. Draw a line from the middle of the cylinder to where it intersects the plane. That's the hypotenuse of a right angle triangle. Then use the pythagorean theorem.

Where the cylinder intersects the place is what I am trying to solve for. I have a radius, and a desired arc chord.

I looked around, and found the terminology I needed: sagitta. The answer I get from calculating the sagitta, and subtracting the smaller answer from the radius of the cylinder, is the same as Dr. Stab's formula to three significant digits, but the resulting arc still doesn't fill the space as entered into either formula. I'm not sure what's up.

I want to fill one unit.
Radius of cylinder: 5.729583 units
Desired chord: 1 unit
Result: 0.0219
Z: 5.729583 - .0219 = 5.707683


By manually adjusting, I get to 5.7018, but I have no idea where that's coming from, and it's not useful. I need to be able to calculate this on the fly. Maybe it's a quirk of the renderer, but it seems like they'd have that down, by now. The camera is orthographic, so it isn't like I'm looking from an angle.

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

Is the cylinder a cylinder or some extruded n-gon? What are you working with here?

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

Dr. Stab posted:

Is the cylinder a cylinder or some extruded n-gon? What are you working with here?

It's a cylinder I am generating procedurally in Unity. Increasing the number sides does help, if that's what you're thinking. I was just coming here to post that I tried that.

Edit: By which I mean, it helps enough to be a workable solution at a reasonable number of faces. Thanks for the help.

Centripetal Horse fucked around with this message at 22:42 on May 29, 2016

xgalaxy
Jan 27, 2004
i write code
Unreal Engine 4.12 released. I think my favorite thing is the full scene FBX importing.

WarpedLichen
Aug 14, 2008


Centripetal Horse posted:

It's a cylinder I am generating procedurally in Unity. Increasing the number sides does help, if that's what you're thinking. I was just coming here to post that I tried that.

Edit: By which I mean, it helps enough to be a workable solution at a reasonable number of faces. Thanks for the help.

I believe the default unity cylinder is a 20 sided n-gon but you're drawing really shallow curves so maybe there's a better way instead of moving a whole cylinder.

Programmer Humor
Nov 27, 2008

Lipstick Apathy

xgalaxy posted:

Unreal Engine 4.12 released. I think my favorite thing is the full scene FBX importing.

Oh, they finally got around to adding this, huh? That's good. It looks like they even package the scene in a single asset to make reimporting stuff easy.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

WarpedLichen posted:

I believe the default unity cylinder is a 20 sided n-gon but you're drawing really shallow curves so maybe there's a better way instead of moving a whole cylinder.

It seems to have been mostly the not-quite-roundness of the object that was the problem. When I switched to procedural generation, and upped the number of faces, the problem went away.

I have another mathish question. I want to make two factors (speed and distance) converge at 0 (or one reach its maximum while the other reaches 0) based on time. I've worked out a couple of ways to get any two of those factors to match up, but at the expense of the third. I am using a pretty standard construct:

code:
        for (float t = 0; t <= targetTime t += Time.deltaTime)
        {
		Lerp, or whatever, stuff here
        }
I can get the distance to reach 0 along with the timer by doing something like this:
code:
distanceThisFrame = totalDistance * lerpFactor - alreadyTraveled;
alreadyTraveled += distanceThisFrame;
The problem with this is that, if the speed the object is traveling doesn't happen to match up with the first totalDistance * lerpFactor, the effect can be very jarring. The object is cooking along, when it suddenly jerks to half its speed, then slows down to 0 as it approached its destination. I want to slow down from the objects current speed to 0, while reducing distance to the target to 0 over a period of time.

Alternatively, I can get speed to reach 0 with the timer, but when speed reaches 0, there is no guarantee that I've covered the proper distance.

I feel like this is a problem I have encountered, before, but I can't seem to get my head around it, this time. I'm also kind of afraid I already hit on the right solution, but messed up one of the factors, so I didn't get the result I was expecting.

WarpedLichen
Aug 14, 2008


Centripetal Horse posted:

It seems to have been mostly the not-quite-roundness of the object that was the problem. When I switched to procedural generation, and upped the number of faces, the problem went away.

I have another mathish question. I want to make two factors (speed and distance) converge at 0 (or one reach its maximum while the other reaches 0) based on time. I've worked out a couple of ways to get any two of those factors to match up, but at the expense of the third. I am using a pretty standard construct:

code:
        for (float t = 0; t <= targetTime t += Time.deltaTime)
        {
		Lerp, or whatever, stuff here
        }
I can get the distance to reach 0 along with the timer by doing something like this:
code:
distanceThisFrame = totalDistance * lerpFactor - alreadyTraveled;
alreadyTraveled += distanceThisFrame;
The problem with this is that, if the speed the object is traveling doesn't happen to match up with the first totalDistance * lerpFactor, the effect can be very jarring. The object is cooking along, when it suddenly jerks to half its speed, then slows down to 0 as it approached its destination. I want to slow down from the objects current speed to 0, while reducing distance to the target to 0 over a period of time.

Alternatively, I can get speed to reach 0 with the timer, but when speed reaches 0, there is no guarantee that I've covered the proper distance.

I feel like this is a problem I have encountered, before, but I can't seem to get my head around it, this time. I'm also kind of afraid I already hit on the right solution, but messed up one of the factors, so I didn't get the result I was expecting.

It sounds like you want to accelerate your object to a stop.

This is simply a system of 2 equations:
distance = initial velocity * t + 1/2(acceleration) * t^2
initial velocity + (a * t) = 0

This implies that:
acceleration = - initial velocity / t
distance = .5(initial velocity) * t

Solve for time to get acceleration, then decrease your velocity by acceleration each step.

WarpedLichen fucked around with this message at 05:57 on Jun 3, 2016

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

Do you need the time at which it reaches the destination to be exact? If you're linearly interpolating distance then there's no solution You're essentially trying to make a triangle with a particular height, a particular base, and a particular area. Unfortunately, two of these things define the third.

If time is variable, then you can simply linearly interpolate speed over a time of 2* initial distance/initial speed. Or, to reduce inaccuracies due to the non-continuous nature of the simulation, you can interpolate position along the curve

d = (t^2)/4d0 + t*v0 + d0
so, something like
currentDistance = elapsedTime*elapsedTime/(4f*startingDistance) - elapsedTime*startingSpeed + startingDistance

I haven't checked this, so I may have gotten some of the signs wrong, but it's just supposed to be the integral of the velocity curve.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

WarpedLichen posted:

It sounds like you want to accelerate your object to a stop.

Yeah. I guess I do. I probably could have saved myself some headaches by thinking of it that way.

WarpedLichen posted:

This is simply a system of 2 equations:
distance = initial velocity * t + 1/2(acceleration) * t^2
initial velocity + (a * t) = 0

This implies that:
acceleration = - initial velocity / t
distance = .5(initial velocity) * t

Solve for time to get acceleration, then decrease your velocity by acceleration each step.

Plugging in some numbers, I get:
code:
600 = 400 * 3 + .5x * 3^2 = -133.333
As you said, that's -400 / t. That gets my velocity to 0 over time, but time would have to equal 4.5 to get my distance to 0. You said to solve for time, but time is (supposed to be) a known quantity. I'm misunderstanding something.


Dr. Stab posted:

Do you need the time at which it reaches the destination to be exact? If you're linearly interpolating distance then there's no solution You're essentially trying to make a triangle with a particular height, a particular base, and a particular area. Unfortunately, two of these things define the third.

If time is variable, then you can simply linearly interpolate speed over a time of 2* initial distance/initial speed. Or, to reduce inaccuracies due to the non-continuous nature of the simulation, you can interpolate position along the curve

d = (t^2)/4d0 + t*v0 + d0
so, something like
currentDistance = elapsedTime*elapsedTime/(4f*startingDistance) - elapsedTime*startingSpeed + startingDistance

I haven't checked this, so I may have gotten some of the signs wrong, but it's just supposed to be the integral of the velocity curve.

That depends on how exact "exact" is. I want to be able to specify time, and hit distance and velocity goals +/- a reasonable amount. If you're just talking about the fact that a linear interpolation may never reach its destination, because "t" in my loop may never reach the time target, that's not a big deal. I can deal with that in multiple ways.

Dr. Stab
Sep 12, 2010
👨🏻‍⚕️🩺🔪🙀😱🙀

I mean that if you have a constant acceleration, you can't fix all three of initial speed, initial distance and arrival time. There's only one way to apply constant acceleration and stop at a point, given initial velocity and distance, and it takes a fixed amount of time.

If you also want to fix arrival time, acceleration needs to be variable.

You want to pick a curve for your velocity wrt time where v(0) = your initial velocity, v(target time) = 0 and the area under the curve over that range is your distance.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

Dr. Stab posted:

I mean that if you have a constant acceleration, you can't fix all three of initial speed, initial distance and arrival time. There's only one way to apply constant acceleration and stop at a point, given initial velocity and distance, and it takes a fixed amount of time.

If you also want to fix arrival time, acceleration needs to be variable.

You want to pick a curve for your velocity wrt time where v(0) = your initial velocity, v(target time) = 0 and the area under the curve over that range is your distance.

I see what you mean. I understand that something in there has to be variable. I was planning on velocity being the variable term. Distance is fixed, and I want time to remain as close to fixed as possible, but a linear velocity change is not only unnecessary, but kind of undesirable for my purposes. Any suggestions as to what I should be reading if I want to construct my own curves for this purpose? I have essentially no math education. I taught myself algebra and babby's first calculus like twelve years ago for some college entrance exams, but I haven't touched it, since. I think what I want here is a function so that y = 0 at an x of time, but also with some specific area under it... maybe?

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Centripetal Horse posted:

I see what you mean. I understand that something in there has to be variable. I was planning on velocity being the variable term. Distance is fixed, and I want time to remain as close to fixed as possible, but a linear velocity change is not only unnecessary, but kind of undesirable for my purposes. Any suggestions as to what I should be reading if I want to construct my own curves for this purpose? I have essentially no math education. I taught myself algebra and babby's first calculus like twelve years ago for some college entrance exams, but I haven't touched it, since. I think what I want here is a function so that y = 0 at an x of time, but also with some specific area under it... maybe?

If I understand you correctly, you have an initial velocity and position, and you want to reach a final velocity (0) and position at a fixed time. In other words you need x(t) such that the values of x and it's derivatives (the velocity) are fixed at the times t_i and t_f. It's been a while but I think this is what you want: https://en.wikipedia.org/wiki/Cubic_Hermite_spline, in particular the first section "Interpolation on a single interval." These splines let you fix a curves values and derivatives over an interval. You're going to use the spline to get x(t), although you can get the v(t) by taking the derivative.

They key points are that you start at x(t_i) = x_i and end at x(t_f) = x_f, and that the slope (dx/dt = v) is v_i at t = t_i and 0 at t = t_f.

If you get lost I can help you through it. There might also be more helpful introductions on the internet than wikipedia.

HappyHippo fucked around with this message at 18:30 on Jun 3, 2016

WarpedLichen
Aug 14, 2008


Centripetal Horse posted:

I see what you mean. I understand that something in there has to be variable. I was planning on velocity being the variable term. Distance is fixed, and I want time to remain as close to fixed as possible, but a linear velocity change is not only unnecessary, but kind of undesirable for my purposes. Any suggestions as to what I should be reading if I want to construct my own curves for this purpose? I have essentially no math education. I taught myself algebra and babby's first calculus like twelve years ago for some college entrance exams, but I haven't touched it, since. I think what I want here is a function so that y = 0 at an x of time, but also with some specific area under it... maybe?

So you can flex initial velocity and you have a fixed time right?

So let's say you have:

starting distance: 600
time: 3 seconds

Plugging that in to the distance equation:
600 = v0 * (3) + .5 (a) (9)

Plugging that in to the speed equation:
v0 = -a * (3)
v0 = (600 - 4.5a) / 3

solve that and you get:
v0 = 400
a = -133.3

You can do that programmatically in code fairly easily, I'm sure there's a ton of examples for a simple linear equation solver.

If you want to introduce a non linear acceleration curve you just have to introduce some jerk to your system which gives you a bit more to play with and allows you to fix initial velocity as well.

Centripetal Horse
Nov 22, 2009

Fuck money, get GBS

This could have bought you a half a tank of gas, lmfao -
Love, gromdul

HappyHippo posted:

If I understand you correctly, you have an initial velocity and position, and you want to reach a final velocity (0) and position at a fixed time. In other words you need x(t) such that the values of x and it's derivatives (the velocity) are fixed at the times t_i and t_f. It's been a while but I think this is what you want: https://en.wikipedia.org/wiki/Cubic_Hermite_spline, in particular the first section "Interpolation on a single interval." These splines let you fix a curves values and derivatives over an interval. You're going to use the spline to get x(t), although you can get the v(t) by taking the derivative.

They key points are that you start at x(t_i) = x_i and end at x(t_f) = x_f, and that the slope (dx/dt = v) is v_i at t = t_i and 0 at t = t_f.

If you get lost I can help you through it. There might also be more helpful introductions on the internet than wikipedia.

You do understand correctly. Assuming _i, and _f, mean something like, "initial," and "final," then I think I understand what you're saying in a vague, conceptual way. I am almost certain to be lost trying to follow the Wikipedia explanation, though. Glancing over it, I felt OK until I hit the tangent "m" in the first equation. I'm also not sure what the difference is for my purposes between the unit interval and the arbitrary interval. It seems that the unit interval being [0, 1] suits my purposes, because I can just divide and multiply my way to the "full-sized" number, where 0 = 0, and 1 = my maximum value, or vice-versa, right?



WarpedLichen posted:

So you can flex initial velocity and you have a fixed time right?

Yes, it can flex some. Flexing too much is what caused me to come here for help, though. If the difference between the starting velocity and the velocity after one run through the loop is too great, the effect looks terrible.

WarpedLichen posted:

So let's say you have:

starting distance: 600
time: 3 seconds

Plugging that in to the distance equation:
600 = v0 * (3) + .5 (a) (9)

Plugging that in to the speed equation:
v0 = -a * (3)
v0 = (600 - 4.5a) / 3

solve that and you get:
v0 = 400
a = -133.3

You can do that programmatically in code fairly easily, I'm sure there's a ton of examples for a simple linear equation solver.

If you want to introduce a non linear acceleration curve you just have to introduce some jerk to your system which gives you a bit more to play with and allows you to fix initial velocity as well.

Right. That's what I got, and my steps look the same as yours. It's easy to translate to code. What I'm not following, is where the 600 goes in all of that. If I accelerate from 400 to 0 at 133.33 per second for 3 seconds, I only cover a distance of (400 - 133.33) + ((400 - 133.33) - 133.33) + ((400 - 133.33 - 133.33) - 133.33), right? I can solve the equation easily enough, and the right side sure does equal 600, but I can't figure out how I travel 600 units. The 4.5 that we divide away makes 600, but it's gone.

I'll read that link on "jerk" as soon as I can. You say that allows me to fix initial velocity, which would be nice.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

WarpedLichen posted:

So you can flex initial velocity and you have a fixed time right?

So let's say you have:

starting distance: 600
time: 3 seconds

Plugging that in to the distance equation:
600 = v0 * (3) + .5 (a) (9)

Plugging that in to the speed equation:
v0 = -a * (3)
v0 = (600 - 4.5a) / 3

solve that and you get:
v0 = 400
a = -133.3

You can do that programmatically in code fairly easily, I'm sure there's a ton of examples for a simple linear equation solver.

If you want to introduce a non linear acceleration curve you just have to introduce some jerk to your system which gives you a bit more to play with and allows you to fix initial velocity as well.

But they also have an initial velocity that they don't want to change suddenly:

Centripetal Horse posted:

The problem with this is that, if the speed the object is traveling doesn't happen to match up with the first totalDistance * lerpFactor, the effect can be very jarring. The object is cooking along, when it suddenly jerks to half its speed, then slows down to 0 as it approached its destination. I want to slow down from the objects current speed to 0, while reducing distance to the target to 0 over a period of time.

Alternatively, I can get speed to reach 0 with the timer, but when speed reaches 0, there is no guarantee that I've covered the proper distance.

I feel like this is a problem I have encountered, before, but I can't seem to get my head around it, this time. I'm also kind of afraid I already hit on the right solution, but messed up one of the factors, so I didn't get the result I was expecting.

This can't be solved with a fixed acceleration. Unless I've misunderstood the problem, Centripetal Horse should use the spline approach I mentioned above.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Centripetal Horse posted:

You do understand correctly. Assuming _i, and _f, mean something like, "initial," and "final," then I think I understand what you're saying in a vague, conceptual way. I am almost certain to be lost trying to follow the Wikipedia explanation, though. Glancing over it, I felt OK until I hit the tangent "m" in the first equation. I'm also not sure what the difference is for my purposes between the unit interval and the arbitrary interval. It seems that the unit interval being [0, 1] suits my purposes, because I can just divide and multiply my way to the "full-sized" number, where 0 = 0, and 1 = my maximum value, or vice-versa, right?

You're close. Yep, i and f are for initial and final. The "tangent" m is your velocity. Tangent = first derivative, and first derivative = velocity (when the function is position). So the m0 in that equation would be the initial velocity, and m1 would be the final (so zero for you). (In the arbitrary interval section these are m_k and m_(k+1), respectively).

You're on the right track with the unit interval and the arbitrary interval, the thing is that the arbitrary interval section has done all the work of multiplying/dividing to convert one to the other.

Adbot
ADBOT LOVES YOU

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
It might also be confusing because of the variable names, so let's just make it easy.

The four functions are:
code:
h00[t] := 2 t^3 - 3 t^2 + 1;
h10[t] := t^3 - 2 t^2 + t;
h01[t] := -2 t^3 + 3 t^2;
h11[t] := t^3 - t^2;
Then plugging into the equation for the arbitrary interval:
code:
x[t] = h00[(t - ti)/(tf - ti)] xi + h10[(t - ti)/(tf - ti)] (tf - ti) vi + h01[(t - ti)/(tf - ti)] xf + h11[(t - ti)/(tf - ti)] (tf - ti) vf
x[t] = ((t - ti)^3/(tf - ti)^3 - (t - ti)^2/(tf - ti)^2)*(tf - ti)*vf + 
 ((t - ti)^3/(tf - ti)^3 - (2*(t - ti)^2)/(tf - ti)^2 + (t - ti)/(tf - ti))*(tf - ti)*
  vi + ((-2*(t - ti)^3)/(tf - ti)^3 + (3*(t - ti)^2)/(tf - ti)^2)*xf + 
 (1 + (2*(t - ti)^3)/(tf - ti)^3 - (3*(t - ti)^2)/(tf - ti)^2)*xi
The parameters are initial and final position (xi and xf), initial and final velocity (vi and vf) and initial and final time (ti and tf).

For example, starting at xi=0 and stoping at xi=600, over a time period from ti =0 and ending at tf = 3, and with an initial velocity of vi = 150 and stopping with vf = 0, we get:

code:
x[t] = 600*(t^2/3 - (2*t^3)/27) + 450*(t/3 - (2*t^2)/9 + t^3/27)
The velocity is the first derivative of this:
code:
v[t] = 600*((2*t)/3 - (2*t^2)/9) + 450*(1/3 - (4*t)/9 + t^2/9)
And if we plot (blue is x[t], red is v[t]):

You can see we start at x=0, end at x=600, start with v=150, and end with v=0 and that t runs from 0 to 3.

This post brought to you by Mathematica, which did most of the work.

HappyHippo fucked around with this message at 16:48 on Jun 4, 2016

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply