Space Engineers

Space Engineers

Not enough ratings
Torpedo
   
Award
Favorite
Favorited
Unfavorite
Type: World
File Size
Posted
Updated
12.340 KB
11 Jan, 2015 @ 12:41pm
11 Jan, 2015 @ 2:40pm
2 Change Notes ( view )

Subscribe to download
Torpedo

Description
This is a torpedo i made using BlueG's radar mod.
Trigger the LoopTimer to start the homing system. If the torpedo sees a target (currently set to small ships with a max distance of 900m), it will start the thrusters and try to hit it.
Its pretty smart in the way it follows the target. It uses the target velocity to find an intercepting course. Also (what actually is more important) the gyro control system is very good.
Ordinary homing methods are using the gyros in a way, that they cant turn very fast and still be precice. What i mean by that is: The missile finds a target to the right.
It triggers the gyro as long as it is not aligned with the target. If it is aligned with the target it turns the gyro off, BUT: The missile is still in rotation and will continue to rotate until the gyros manage to breake the motion. That means it will overshoot.
That gets more problematic with increasing gyro strength. This torpedo calulates the angular speed and estimates how long the torpedo would still rotate if the gyros would be turned off. That way it can turn the gyros off earlier, to prevent overshooting.
With all of that fancy stuff, the chance to hit a fast traveling object is increased a lot. The code is pretty long, but i cleaned it up and put some comments in. As i said in a comment in my code, i am going to explaing the "crazy function" getPoph (point of potential hit):

---------------Crazy math things start---------------
This function calculates where it would be physically possible to hit the target. Lets see what informations we have (and need), followed by how they are named in the formulas later:
-Position of the torpedo: P
- Speed of the torpedo (using also the direction would be too complicated, so the calculation is simplified and only uses speed): S
- Position of the target: Tp
- Velocity (speed and direction) of the target: V
- Time: t

To make things simpler, assume that the torpedo is at the origin of our coordinate system. To do this, shift the target position using the torpedo position.
If the torpedo is at the origin, the target is at the position Q:
Q = Tp - P

Assuming the target wont change direction, it would follow a ray described as:
r(t) = Q + t * V

Now we have to know, where our torpedo could be after a given time t. Because we dont take direction into account, points on a sphere around the origin (torpedo) are possible.
In a given time t, it would travel the distance s:
s(t) = S * t;

This is also the radius of the sphere.

Calculating the collision point of the sphere and the ray would lead to a potential hit point. It is a point, where the torpedo and the target could be after some given time. Equation:
|r(t)| = s(t)
The point can be interpreted as a vector from the origin to the target. The length of this vector is the distance to our torpedo / origin.
s(t) is the radius of the sphere which makes this equation understandable i hope :D

Writing that out would be:
sqrt((Q1 + t * V1)² + (Q2 + t * V2)² + (Q3 + t * V3)²) = S * t
For the individual components i added 1, 2 and 3 behind the names.

One can calculate the solution with any CAS. Here's a wolfram alpha link: http://www.wolframalpha.com/input/?i=solve+sqrt%28%28Q1+%2B+t+*+V1%29%C2%B2+%2B+%28Q2+%2B+t+*+V2%29%C2%B2+%2B+%28Q3+%2B+t+*+V3%29%C2%B2%29+%3D+S+*+t+for+t
There are two solutions. Only the positive one (the seccond one in the wolfram alpha link) is useful. Noone wants negative time (time travel isnt possible unless you have a tardis :D).
This solution is the first longer equation you can see in my code, but we arent done yet.

There is a possibility that hitting the target with the current parameters is physically impossible. Thats bad of course. But it doesnt mean we dont want to follow the target in some way. But how exactly?
If there is no intersection at all, the above solution would lead to "Not a Number (NaN)", because of negative root or division by zero. The best point to fly towards to would be the point, where the distance from the target to the sphere is minimal.
Okay distance from target to sphere:
d(t) = |r(t)| - s(t)

How to find out where this function has its minimum? If examining this distance function, one can see, that it gets smaller and smaller until it has reached its minimal value and again climbs up. So there is a turning point.
That means the derivative is zero at this point. Calculating the derivative can also be done using a CAS:
http://www.wolframalpha.com/input/?i=D[sqrt%28%28Q1+%2B+t+*+V1%29%C2%B2+%2B+%28Q2+%2B+t+*+V2%29%C2%B2+%2B+%28Q3+%2B+t+*+V3%29%C2%B2%29+-+S+*+t%2Ct]

Now we need to know where d'(t) is zero. I used a CAS again to solve d'(t)=0. But sadly the computation is so complicated, that wolfram alpha struggles to get a result in time. I did get it to solve a few times, but most of the time it will refuse. If you have another CAS, cou could use that, or try your luck with:
http://www.wolframalpha.com/input/?i=Solve[%282+V1+%28Q1%2bt+V1%29%2b2+V2+%28Q2%2bt+V2%29%2b2+V3+%28Q3%2bt+V3%29%29%2f%282+sqrt%28%28Q1%2bt+V1%29^2%2b%28Q2%2bt+V2%29^2%2b%28Q3%2bt+V3%29^2%29%29-S%3d0%2ct]&incParTime=true

d'(t)=0 written out is:
(2 V1 (Q1+t V1)+2 V2 (Q2+t V2)+2 V3 (Q3+t V3))/(2 sqrt((Q1+t V1)^2+(Q2+t V2)^2+(Q3+t V3)^2))-S=0

There are again two solutions, where only one is important:
t2=(-sqrt((2Q1 S² V1 - 2Q1 V1³ - 2Q1 V1 V2² - 2Q1 V1 V3² + 2Q2 S² V2 - 2Q2 V1² V2 - 2Q2 V2³ - 2Q2 V2 V3² + 2Q3 S² V3 - 2Q3 V1² V3 - 2Q3 V2² V3 - 2Q3 V3³)² - 4 (S² V1² + S² V2² + S² V3² - V1^4 - 2V1² V2² - 2V1² V3² - V2^4 - 2V2² V3² - V3^4) (Q1² S² - Q1² V1² - 2Q1 Q2 V1 V2 - 2Q1 Q3 V1 V3 + Q2² S² - Q2² V2² - 2Q2 Q3 V2 V3 + Q3² S² - Q3² V3²)) - 2Q1 S² V1 + 2Q1 V1³ + 2Q1 V1 V2² + 2Q1 V1 V3² - 2Q2 S² V2 + 2Q2 V1² V2 + 2Q2 V2³ + 2Q2 V2 V3² - 2Q3 S² V3 + 2Q3 V1² V3 + 2Q3 V2² V3 + 2Q3 V3³) / (2 (S² V1² + S² V2² + S² V3² - V1^4 - 2V1² V2² - 2V1² V3² - V2^4 - 2V2² V3² - V3^4))
That is the long equation you can see in my function.

We now have two solutions: t1, which is the simple intersection with the sphere and t2, which is this crazy formula.
If t1 is defined (not NaN) we obviously use that, because its the correct intersection and can actually be reached in time. If there is no solution found for t1 or t1 is negative, we have to use t2. If t2 is negative we allready missed the closest point. This is the worst case. In my code i set t2=0 in this case, which is the best thing one can do in this situation. If t2 is NaN i set it to 0 too. But that shouldnt happen, because it should always have a solution, if t1 is not solvable.

Okay, we decided which t to use. Now we just have to use it in the ray equation (r(t)) to find out where to aim. Thats it.
---------------Crazy math things end---------------

Final Note:
Due to some splifications, hitting is still not guaranteed, but a lot more likely then simple methods. My sample torpedo also doesnt do a lot of damage. It isnt supposed to, it is only a testing torpedo to show the capabilities of this method. The program could run on any other missile design (make sure to adapt breaking torque).
Also, because of a limited turning radius, there is a situation where the torpedo orbits around the target. This happens if the torpedo is slow and the target is stationary. If the torpedo misses (if you manage to dodge for example), it would turn, but since it also thrusts forward, it cant turn fast enough and as i said orbits around.

Finaly i want to thank BlueG whose radar mod made this possible in the first place.
13 Comments
Return of Bob 21 Sep, 2015 @ 3:29pm 
I think its the grid-pivot changning, but im not sure...
Return of Bob 21 Sep, 2015 @ 2:52pm 
i could need some help here, i used your script to make a missile that works when pasted and fired in empty space, but after puting them on mergeblocks and making timerblocks fire them in a staggerd fire mode, the get to a stand still in space, with a Execption cought; "Input string was not in a correct format" I find it very strange since exacly the same missile works perfecly fine aslong as i dont use mergeblocks/timers...

Thanks inbeforehand

Böb
Lynnuxx 26 Mar, 2015 @ 4:12pm 
GridIntegerToWorld is not available anymore. Change line 243, 244 to

var p = mult(localAxis[0], x(lP)) + mult(localAxis[1], y(lP)) + mult(localAxis[2], z(lP))
+ radar.GetPosition();

and in function getGridData():

//Get world coordinates of the center block
var tO = centerBlock.GetPosition();
//Get world coordinates for positions, that are shifted in all three axes aroud the center block.
var tX = tO + veci(10, 0, 0);
var tY = tO + veci(0, 10, 0);
var tZ = tO + veci(0, 0, -10);
Baleur 22 Feb, 2015 @ 3:25pm 
Im wanting to adapt this to simply get a self built turret (with rotors and fixed weapons) to track a target (triggering the guns to shoot is simple enough with vanilla means). Is it possible, and if so, how?
Thanks!
dustybear 10 Feb, 2015 @ 8:55pm 
I think the author needs to replace his usage of gridintegertoworld with getposition. Otherwise this is very cool
SEMTEX 9 Feb, 2015 @ 9:44pm 
same problem here ...
dustybear 30 Jan, 2015 @ 3:28pm 
Specifically it says the code is missing a Using directive.
dustybear 30 Jan, 2015 @ 2:12am 
The programmable block is throwing out some errors now about "gridintegertoworld" being undefined. Some kind of recent change with the programmable block features?
Lynnuxx 28 Jan, 2015 @ 3:42pm 
A question since I don't know C# and the SE API well enough (yet). Can you use the Orientation property (IMyCubeBlock) of the sensor block directly for easier calculation of the absolute position of the target ? You calculate LocalAxis for this...
Lynnuxx 28 Jan, 2015 @ 2:32pm 
Ok, you can have a ship with radar (beacon and sensors) and you can have the torpedo connected to it. The torpedo needs a beacon and radar, too. Once you identified one of the targets your ship has found to be a turret you have to assign it to the torpedo.
If the turret is [radarX] on the ships' sensor then write [radar+X] into the torpedos' sensor. Hopefully this will work ;-)