Welcome to Keen Software House Forums! Log in or Sign up to interact with the KSH community.
  1. You are currently browsing our forum as a guest. Create your own forum account to access all forum functionality.

Finding thrust when autopilot is enabled

Discussion in 'Programming (In-game)' started by Jon Turpin, Sep 9, 2017.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Jon Turpin Apprentice Engineer

    Messages:
    161
    As the title says, I'm trying to figure out how I can echo the amount of thrust being used by the auopilot.

    I've set up a script that accounts for CurrentThrust and ThrustOverride, and both work great when I'm piloting the ship, but when I turn AP on, they stay at zero. I would assume that it has to be using the thrusters somehow, so what function do I call to show this?

    End game - I'm looking to find out how long it takes the drone to reach max speed (100m/s) from it's current speed when it detects a target, so I can just use 100 as a constant speed for calculating an intercept and just add the time it takes to get to 100 to the time variable. Also, the distance traveled during the acceleration is subtracted from the distance to target.

    And I'm wondering if the AP will use more than one axis of thrust to boost acceleration - testing flight logic myself, I saved 11.6 seconds using two axis of thrust simultaneously, and 16.7 seconds using three axis. I don't believe the AP uses such logic from what I've seen, but I can't be sure if I can't see the current acceleration applied to the ship (as I'm using a = f/m to calculate, I need the force of the thrusters to be > 0).

    Code so far:
    Code:
    List<IMyThrust> thrusters = new List<IMyThrust>();
    GridTerminalSystem.GetBlocksOfType<IMyThrust>(thrusters);
    
    float curThrust = 0;
    float ovrThrust = 0;
              
    foreach (var thruster in thrusters)
    {
        curThrust += thruster.CurrentThrust;
        ovrThrust += thruster.ThrustOverride;
    }
    
    MyShipMass massStats = remote.CalculateShipMass();
    
    int mass = massStats.PhysicalMass;
    
    var myAccel = curThrust / mass;
              
    MyShipVelocities vel = remote.GetShipVelocities();
    var myvel = vel.LinearVelocity;
    var velocity = myVel.Length();
    
    if (!remote.IsAutoPilotEnabled && velocity == 0)
    {
        num = 0;
    }
    else num += 1/60;
    
    if (velocity >= 100)
    {
        Me.CustomData = "Time of Acceleration to 100: " + num;
        var timer = GridTerminalSystem.GetBlockWithName("SM Timer") as IMyTimerBlock;
        timer.Enabled = false;
    }
    
    Video of what I'm talking about:



    So if autopilot doesn't actually use the thrusters, how is it creating thrust?
     
    Last edited: Sep 9, 2017
  2. Georgik Apprentice Engineer

    Messages:
    186
    It must be a bug. CurrentThrust should return actual thrust no matter who/what is a source.

    Workaround:
    You can use IMyShipController.MoveIndicator, (which should work with AP too). But this involves much more work to get right results (orientation matrix).
     
  3. Jon Turpin Apprentice Engineer

    Messages:
    161
    Alrighty, then, I'll have to play around with the calculations. I now wish I had held more stock in math back in the day. I distinctly remember thinking "I'll never use this. Ever!"

    One other thing you may be able to help with - Trying to change Rotational Velocity from rad/s to m/s, using velocity = radius * rad/s. How/where do I find the radius for the equation?

    Thanks!
     
  4. Georgik Apprentice Engineer

    Messages:
    186
    I think you are looking for distance of point rotating with x [rad/s] around of some center of rotation. Be more specific, otherwise I'm not sure how can I help :)
     
  5. Jon Turpin Apprentice Engineer

    Messages:
    161
    Sorry, I'll try to explain better:

    In the above video, you'll notice that I have my Rotational Velocity shown. However the velocity as is denotes radians per second. This velocity is the rotational velocity of the drone, which I'm using to see how long it takes the drone to turn in the direction of a calculated intercept point.

    As such, I would like to figure out how fast (in meters per second) the drone can turn, in order to calculate how long it will take the drone to turn 1 degree, which will then be used to calculate how long (total) it takes the drone to turn and start moving toward the target.

    I also will need some way to figure out which way the drone is facing - haven't figured this part out yet, either. Guessing World Matrix and Orientation is involved, somehow.

    I've been playing around with WorldABB this morning, and am thinking this might be the way to calculate the radius for the equation "Velocity (m/s) = Radius * Radians/sec".

    Code:
    var bBox = cockpit.WorldAABBHr; // not sure what the diff is between WorldABB and WorldABBHr ?? They both give the same numbers..
    var boxMax = bBox.Max; // Max point of Bounding Box
    var boxCenter = bBox.Center; // Center of BBox
    
    var boxRadius = (boxMax - boxCenter).Length(); // MAYBE the radius?
    
    And I will note that it's been forever since I've messed with these sorts of equations, so I'm very rust, to say the least - barney style it for me if possible :p

    EDIT: And just to add, Move Indicator is unaffected by the autopilot. All axis remain at 0 :/
    --- Automerge ---
    EDIT 2: So I ripped apart a lidar script, and noticed they are calculating target radius by subtracting bBox.Min from bBox.Max. I would think that the ship radius would be from the center point, but seems it is from the minimum edge of the bBox to the maximum edge?
     
    Last edited: Sep 9, 2017
  6. Georgik Apprentice Engineer

    Messages:
    186
    Nope, I still don't get why you are trying to convert Rotational Velocity from rad/s to m/s, because afaik you can't.
    If you have something rotating, the whole thing (all points in its body) are rotating with the same Rotational Velocity.

    As you know, m/s refers to how fast something is moving. You can't convert rotation of body to move velocity, because points don't move with the same velocity. The furthest ones are translating with the biggest velocity, and the center in fact is not moving at all. And here comes the formula:
    "Velocity(m/s) = Radius(m)*RotationalVelocity(rad/s)"

    Point in a body rotating with velocity of 1 rad/s mounted in a distance of 1 meter from center of rotation is moving with velocity 1 m/s.

    If you want to get how many seconds will it take to rotate by 1 degree, use something like:
    Code:
    float degreesPerSecond=180*rotvel/Math.PI;
    float timePerDegree=1/degreesPerSecond;
    --- Automerge ---
    If I misunderstood something, I apologize.

    As for AP MoveIndicator, it has to be a bug, since in documentation it says MoveIndicator contains input from both user and AP.
     
  7. Jon Turpin Apprentice Engineer

    Messages:
    161
    You quote the exact formula that I am trying to solve, and my question was - what is the "radius" piece for a ship? As you are 100% correct that something moving at 1 rad/s with a radius of 1 will be rotating at 1 m/s. There has to be a radius calculated for a grid, and a way to retrieve it.

    I'm guessing, as you state that all points are moving with the same rotational velocity, that this is why the script I went through is using min edge of bounding box to max edge, instead of center of bbox to max edge.

    I do like how you used the radian-degree conversion as a workaround for my calculation, as well!

    Thank you :)
    --- Automerge ---
    Actually, I think I just found it!

    Code:
    shipRadius = BoundingSphereD.CreateFromBoundingBox(Me.CubeGrid.WorldAABB).Radius;
    
    Yes? No? Maybe?
     
  8. Georgik Apprentice Engineer

    Messages:
    186
    WorldAABB thing... Your aproach visualised:
    [​IMG]
    Code:
    Creates the smallest BoundingSphereD that can contain a specified BoundingBoxD.
    Radius there means distance from the center to edge points.

    Can you please explain why do you want get Velocity[m/s]? What calculations is it going to be used for? I read something about determining needed time to rotate to a target, but this is achieved by Rotational Velocity.
     
  9. Jon Turpin Apprentice Engineer

    Messages:
    161
    Correct, however when I determine the intercept point, autopilot doesn't automatically start to move in that direction unless it is already aligned to the vector. So I need to add in the time it takes to rotate from my current forward vector to the intercept vector, so that I don't end up flying to where the target was 3 seconds ago.

    This is the code I'm using, however currently this results in an infinite delta. I need to work the numbers to find the average velocity of rotation in m/s and use that as a constant rather than querying my current rotational velocity.

    Code:
    var radius = BoundingSphereD.CreateFromBoundingBox(Me.CubeGrid.WorldAABB).Radius;
    var rot_r_PerSec = remote.GetShipVelocities().AngularVelocity.Length();
    var rot_m_PerSec = radius * rot_r_PerSec;
    var delta = Vector3D.Distance(forwardVector, targetPosition) / rot_m_PerSec;
    
    t += delta;
    
    return targetPosition + (targetDirection * targetSpeed * t);
    
    --- Automerge ---
    I also know, through testing the last few days, that it takes the autopilot approximately 39 seconds to reach maximum speed, and am trying to figure out how to use acceleration as a function of time to more accurately set the intercept vector. Currently, if my speed is 0, I have it set to 1, and set a flag to recalculate on the next run, which will eventually get me there, but I take a rather large curve to do so. I noticed in the lidar script that I mentioned earlier that it is using thrust and gyro override to align the vectors while in flight, however the code is nearly 100k characters, and is more advanced in implementation that I understand, currently.

    From what I can tell, he/she is calculating the difference between the two vectors, then figuring out which thrusters are opposite the direction needed to align, and applying thrust where needed, along with spinning (if missiles only have thrusters on one side) using the gyro to ensure thrust is applied in the proper direction.
     
    • Like Like x 1
  10. Georgik Apprentice Engineer

    Messages:
    186
    Right. Abandon your idea of precisely computing time need for AP to rotate to a target. Angular velocity is not constant, maybe not even linear.
    And to finish conversion thing. You take normalized direction vector, which has maximum length of 1, and gets distance from target position (which is +-same as target position). And dividing it by rot_m_PerSec gives you some random value.

    You should just compute angle between your forward direction and direction to target, convert it to radians if it isn't already, and then divide it by some conatant linear velocity
     
  11. Jon Turpin Apprentice Engineer

    Messages:
    161
    Hmm. Can you provide a snippet for computing that angle? I'm learning how to code all this as I go. And correct, angular velocity isn't constant, which is why I'm getting the infinite delta when I'm not actually rotating at time of detection, which is why I'm looking to get an average (simply by showing my angular velocity on an lcd and having it rotate 180 degrees, 235 degrees, 90, and 45 several times to see what the max velocity is and take the average), since I do need a constant value.

    Here is how I'm calculating forwardVector:
    Code:
    var forwardPosition = remote.Position + Base6Directions.GetIntVector(remote.Orientation.TransformDirection(Base6Directions.Direction.Forward));
    var forward = remote.CubeGrid.GridIntegerToWorld(forwardPosition);
    forwardVector = Vector3D.Normalize(forward - remote.GetPosition());
    
     
  12. Georgik Apprentice Engineer

    Messages:
    186
    But average angular velocity will change depending on target angle.
    Tomorrow I will take a look at finding angle, there should be some method, or just use something like cross/dot product.
     
    • Like Like x 1
  13. Jon Turpin Apprentice Engineer

    Messages:
    161
    Yes, but I can't imagine by much. The AP doesn't adjust speed based on distance - it just goes at max speed until it reaches the point at which slowing down will allow it to stop at the given point. And I don't know that I need it to be perfect. Getting it close may be good enough. Thanks for checking on the angle calculation!
    --- Automerge ---
    I found the equation for finding the angle :)

    Code:
    var targetVector = Vector3D.Normalize((targetPosition - currentPosition) * targetSpeed * run);
    var dotVector = Vector3D.Dot(targetVector, forwardVector);
    var magVector = (targetVector.Length() * forwardVector.Length());
    var angDiff = Math.Acos(dotVector / magVector);
    
     
  14. Georgik Apprentice Engineer

    Messages:
    186
    Yes, that's it. BTW targetVector and forwardVector have both length one, Math.Acos(dotVector) should be enough.
     
    • Like Like x 1
  15. Jon Turpin Apprentice Engineer

    Messages:
    161
    Hmm, the equation I found was

    angle = Acos(dotProduct(V1, V2) / magProduct(V1, V2))

    So is the dot product supposed to be with the vector as is? ie. targetVector and forwardVector, not normalized?
    --- Automerge ---
    I guess I don't fully understand the whole dot product result - I watched a few tutorials yesterday to get some idea, but I'm thinking I may not have all the facts on it
    --- Automerge ---
    I think I see what you mean - are you saying that, when I divide the dot by the magnitude, I'm essentially "normalizing" them, and since I've already normalized the vectors, I just need to take the dot?

    Going to play with the equation and see if I get same results to test my above theory :)

    Still having trouble getting the drone to lead the target, though. I literally copied the calculation process from the script I downloaded, plugged in all the info I saw them using, ensured that I was getting speeds/distances the same way, and still the drone goes to where the target is at time of detection, not where target will be in x seconds.

    Pretty sure it has to do with my speed being too low, which is causing the time equation to return a result of 0, and since the lead vector is "tgtPosition + (tgtSpeed * tgtDirection * time)" it is just adding 0 to target position.

    I've scoured the net to find how I can use acceleration as a function of speed (so I can use a semi-constant), found a couple of promising equations, but they seem to require more information than I have at time of vector calculation. ie I kinda NEED the intercept vector to use the equation, which puts me in a catch 22.
    --- Automerge ---
    So after testing, I found you are correct. I spit out the angles using normalized vectors (just dotting the dotVector as above), and using the vectors as they were(dividing dot by mag), and here are the results:
    Code:
    Target Vector One /*Normalized*/: {X:-0.886511584992804 Y:-0.411400952171382 Z:-0.211769842579219}
    Target Vector Two: {X:-10.8500214517117 Y:-5.03513911366463 Z:-2.59185257554054}
    Forward Vector One /*Normalized*/: {X:0.895648009918329 Y:0.415503207252567 Z:0.158656002383038}
    Forward Vector Two: {X:0.447824001312256 Y:0.207751601934433 Z:0.0793280005455017}
    Dot Prod One: -0.998539308611222
    Dot Prod Two: -6.11056472018221
    Angle One: 176.902796487819
    Angle Two: 176.90279648782
    
    Now to calculate a good average degree/per second rotation speed :)
     
    Last edited: Sep 11, 2017
  16. Georgik Apprentice Engineer

    Messages:
    186
    Its because dot product is defined as
    a.b = |a|*|b|*cosA
    therefore:
    cosA = a.b / (|a|*|b|)

    And if a and b are both normalized, then (|a|*|b|) can be skipped. (|b| means length of the vector)
     
    • Informative Informative x 1
  17. Ronin1973 Master Engineer

    Messages:
    4,242
    Every block in a rotating grid can have its own velocity. However, they all share the same period of rotation.

    As you travel further out from the center of gravity, blocks travel faster by nature since they have to cover more distance than a block turning near the center of gravity. There is also a maximum rotational velocity for large and small grids in Keen's code. I forget where it's defined, but it is defined. Rotating grids can collide with other grids and the game has limits as far as being able to detect a collision, phasing through other grids, and calculating the repercussions.

    So to compound your calculations, the game will slow down the maximum rotational speed based on the furthest block from the center of gravity.

    The final point, it may be near impossible to calculate when a grid will occupy a specific orientation: speed limits, rotational limits, gyroscopic overshoots, etc.
     
  18. Jon Turpin Apprentice Engineer

    Messages:
    161
    Just another kink in the chain :/

    But what I ended up doing was setting the calculation to find the angle (in degrees) between my forward vector and the toTarget vector, setting another calculation to define my degree/sec rotational velocity, and setting a condition that says: if autopilot is enabled -> if forward velocity == 0 (ship hasn't started moving toward target yet) -> pipe the current rotational velocity to Me.CustomData (appended) every tick. I then take and split the customData up by " : " add all the numbers together, and divide by the string[].count to get an average.

    I set up the experiment by creating a waypoint, and hardcoding that waypoint into the script so it can calculate the angle. Then, pipe all the numbers to an LCD so I can see exactly what my angle is between forward and target vectors. After that, I simply incremented the angle by 10-12 degrees from 10 - 180, then using pitch angle to do the same.

    I noticed immediately that, while -I- can rotate at a maximum of 53ish degrees per second by mouse/arrow keys, the autopilot sticks at around 44, constantly slowing itself down so as not to go any higher. So, after about 2 hours of testing, I came up with approximately 36.67 degree/sec average speed, which I use to calculate how long it will take to rotate a number of degrees (approximated, of course) and I multiply by a factor of 1.2 to account for the fact that, at wider angles, the ship will reach a higher degree/sec rotation.

    Code:
    //basically
    if (targetSpeed > 0)
    {
    	var dotVector = Vector3D.Dot(targetVector, forwardVector);
            var angDiff = 180 * Math.Acos(dotVector) / Math.PI;
    
    	double rot_d_PerSec = 36.67;
    	delta = (angleDiff  > 90 ? (angleDiff / (rot_d_PerSec * 1.2)) : (angleDiff / rot_d_PerSec));
    
    	t += delta;
    }
    
    --- Automerge ---
    All that said, if anyone that reads this has a solution for using a non-constant velocity (ie. using acceleration) to calculate an intercept point, PLEASE share! I've been searching for what feels like forever for a viable solution, but haven't found anything that works as of yet.
    --- Automerge ---
    Update: I've found the equation I was looking for! The kinematic equation:

    s(t) = Pi + Vi(t) + 0.5(a)(t)^2

    Where s(t) is position at a given time (t), Pi is initial position, Vi is initial velocity, and a is acceleration.

    Time to do some calculations!
     
    Last edited: Sep 12, 2017
  19. Ronin1973 Master Engineer

    Messages:
    4,242
    You're going to run into some non-real world issues. First and foremost is how Space Engineers handles acceleration in a new vector when you're traveling at max speed over your original vector. If you're traveling at 100m/s in a straight line, then rotate your craft 90 degrees and accelerate (no inertial dampeners), you'd have would be moving at a speed greater than 100 m/s relative to the game world as a product of the two vectors. But since there's a limit, how does the engine handle that?

    There's another thread regarding calculating the impact points of dumb-bombs. The bombs never land where they are predicted to fall due to the speed limit. Until it's common knowledge of how the game engine handles maneuvering at full speed, you really can't predict where any intercept point should be. In your case, you're trying to create an intercept point of a maneuvering object by using another maneuvering object which is exponentially harder to do versus a free falling object landing on a static object.
     
  20. Jon Turpin Apprentice Engineer

    Messages:
    161
    Actually, not true, if using a remote control. Reason being that the remote refuses to turn while moving at any speed above ~2 m/s. So when the raycast finds a target, the ship stops, then turns toward the intercept vector, then moves forward toward it. I've been testing the drone for nearly 2 weeks straight now, and am very close to a working product. There are some minor deviations in the calculations that randomly send me where the target JUST was, but it's close. I've added a couple seconds to the time to account for the wobble factor of the autopilot when settling in on a vector. And divide the angle by the time it takes to rotate to zero (using the avg rotational velocity).

    Now, when I am able to remove thruster control from the remote and use override, your point will stand, however currently the remote negates any thrust override for some reason (bug report posted alrdy).

    When I get all the kinks worked out, I'll post a demo :)
     
  21. Georgik Apprentice Engineer

    Messages:
    186
    I hope they will fix it soon, but in the meantime, I found overriding thrusters while Thruster Control is ON quite... working.
     
    • Like Like x 1
  22. Jon Turpin Apprentice Engineer

    Messages:
    161
    No kidding? Counterintuitive, for sure. But I'll have to try it!
     
  23. Georgik Apprentice Engineer

    Messages:
    186
    The thing is (I am not sure about your implementation), but if you turn on override, game would do nothing with it, and at least dampeners in that direction won't fire.
    On the other hand, you can rotate, then disabling AP, turn off dampeners, enable override and that's it.
     
  24. Jon Turpin Apprentice Engineer

    Messages:
    161
    This is what I've been thinking. Once I get the kinks worked out, have the AP rotate to the intercept vector, then script it so that once there is forward movement above say 10 m/s, flip the switch and hit the burners.
     
Thread Status:
This last post in this thread was made more than 31 days old.