Solved! Basically what I needed to do was orient the quaternion to the rocket's current orientation around the forward vector. I was only supplying the forward vector, which was not enough to know if I had any amount of "roll" around the forward vector.
So I ended up making a quaternion of the current rocket rotation from the current matrix, and multiplying that by the limit_rotation quaternion from before. Then I set that back to a matrix plugged that into the rotation portion of the rockets matrix(Instead of multiplying the two matrices).
[source lang="java"]Quaternion transform_rotation = Quaternion.setFromMatrix(R1Matrix).normalize(); Quaternion head = new Quaternion(0, R1head.getX(), R1head.getY(), R1head.getZ()).normalize(); Quaternion newvec = new Quaternion(0, newtargvec.getX(), newtargvec.getY(), newtargvec.getZ()).normalize(); Quaternion rot = head.rotBetween(newvec).normalize(); float turn_threshold = 0.999874f; // maxrot is the rockets maximum rotation angle (2) rot = Quaternion.limit_rotation(rot, turn_threshold).multQ(transform_rotation); float[] qmat = rot.toMatrix(); for (int i= 0; i< 10; i++){ R1Matrix[i] = qmat[i]; }[/source]
Thank you so much Álvaro, your code worked perfectly to limit the rotation of the quaternion.
 Home
 » Viewing Profile: Posts: JM33
JM33
Member Since 04 May 2011Offline Last Active Dec 16 2012 12:55 PM
Community Stats
 Group Members
 Active Posts 28
 Profile Views 1,258
 Submitted Links 0
 Member Title Member
 Age Age Unknown
 Birthday Birthday Unknown

Gender
Not Telling
Posts I've Made
In Topic: Incremental rotation towards target 3D
11 December 2012  02:30 AM
In Topic: Incremental rotation towards target 3D
18 November 2012  09:30 PM
OK, yes I was very confused, and I never needed to solve for i,j,k in the first place.
The code you gave me works as often as the original code I had with angle/axis, however with the opposite effect. Basically if my plane is upside down I hit the target, otherwise not. If I remove the lines to negate the quaternion when q.real() is less than 0, I get the original results (plane upside down = miss & plane right side up = hit).
If you have any suggestion or insight please let me know. I feel like this is really close to the right solution as the rotation is being correctly limited to the maximum rotation, but still needs to be inverted properly. I am wondering if there is anything that can be referenced to determine when to negate the quaternion, such as the up vectors of the rocket and target?
Here is my code asis:
[source lang="java"]Vector3D targvec = new Vector3D(targetmatrix[12], targetmatrix[13], targetmatrix[14]);Vector3D R1pos = new Vector3D(R1Matrix[12], R1Matrix[13], R1Matrix[14]);Vector3D R1head = new Vector3D(R1Matrix[8], R1Matrix[9], R1Matrix[10]);Vector3D newtargvec = targvec.subtract(R1pos);newtargvec = newtargvec.normalize();R1head = R1head.normalize();Quaternion head = new Quaternion(0, R1head.getX(), R1head.getY(), R1head.getZ()).normalize();Quaternion newvec = new Quaternion(0, newtargvec.getX(), newtargvec.getY(), newtargvec.getZ()).normalize();Quaternion rot = head.rotBetween(newvec).normalize();float turn_threshold = 0.9998477f; // cos(maxrot/2) = cos(1)Quaternion newq = rot.limit_rotation(rot, turn_threshold); // see Quaternion code belowfloat[] qmat = newq.toMatrix(); Matrix.multiplyMM(R1Matrix, 0, R1Matrix, 0, qmat, 0);[/source]
And my relative Quaternion functions:
[source lang="java"]public Quaternion limit_rotation(Quaternion q, float min_real_part) {if (q.real() <= min_real_part  q.real() >= min_real_part) return q;if(q.real() < 0){ q = q.multF(1); // negate quaternion}float desired_unreal_length = FloatMath.sqrt(1  min_real_part * min_real_part);float old_unreal_length = q.unreal().abs(); Quaternion limit = new Quaternion(min_real_part, q.x * (desired_unreal_length / old_unreal_length), q.y * (desired_unreal_length / old_unreal_length), q.z * (desired_unreal_length / old_unreal_length));Log.i("QuatLimit", "Result = w: " + Float.toString(min_real_part) + ", x:" + Float.toString(limit.x) + ", y:" + Float.toString(limit.y) + ", z:"+ Float.toString(limit.z)); return limit;}public Quaternion(float real) { this.w = real; this.x = 0; this.y = 0; this.z = 0;}public float real() { return this.w;}public Quaternion unreal() { return new Quaternion(0, this.x, this.y, this.z);}public float abs() { return FloatMath.sqrt(x * x + y * y + z * z + w * w);}public Quaternion (float w, float x, float y, float z) { this.set(w, x, y, z);}public Quaternion multF(float scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; this.w *= scalar; return this;}[/source]
The code you gave me works as often as the original code I had with angle/axis, however with the opposite effect. Basically if my plane is upside down I hit the target, otherwise not. If I remove the lines to negate the quaternion when q.real() is less than 0, I get the original results (plane upside down = miss & plane right side up = hit).
If you have any suggestion or insight please let me know. I feel like this is really close to the right solution as the rotation is being correctly limited to the maximum rotation, but still needs to be inverted properly. I am wondering if there is anything that can be referenced to determine when to negate the quaternion, such as the up vectors of the rocket and target?
Here is my code asis:
[source lang="java"]Vector3D targvec = new Vector3D(targetmatrix[12], targetmatrix[13], targetmatrix[14]);Vector3D R1pos = new Vector3D(R1Matrix[12], R1Matrix[13], R1Matrix[14]);Vector3D R1head = new Vector3D(R1Matrix[8], R1Matrix[9], R1Matrix[10]);Vector3D newtargvec = targvec.subtract(R1pos);newtargvec = newtargvec.normalize();R1head = R1head.normalize();Quaternion head = new Quaternion(0, R1head.getX(), R1head.getY(), R1head.getZ()).normalize();Quaternion newvec = new Quaternion(0, newtargvec.getX(), newtargvec.getY(), newtargvec.getZ()).normalize();Quaternion rot = head.rotBetween(newvec).normalize();float turn_threshold = 0.9998477f; // cos(maxrot/2) = cos(1)Quaternion newq = rot.limit_rotation(rot, turn_threshold); // see Quaternion code belowfloat[] qmat = newq.toMatrix(); Matrix.multiplyMM(R1Matrix, 0, R1Matrix, 0, qmat, 0);[/source]
And my relative Quaternion functions:
[source lang="java"]public Quaternion limit_rotation(Quaternion q, float min_real_part) {if (q.real() <= min_real_part  q.real() >= min_real_part) return q;if(q.real() < 0){ q = q.multF(1); // negate quaternion}float desired_unreal_length = FloatMath.sqrt(1  min_real_part * min_real_part);float old_unreal_length = q.unreal().abs(); Quaternion limit = new Quaternion(min_real_part, q.x * (desired_unreal_length / old_unreal_length), q.y * (desired_unreal_length / old_unreal_length), q.z * (desired_unreal_length / old_unreal_length));Log.i("QuatLimit", "Result = w: " + Float.toString(min_real_part) + ", x:" + Float.toString(limit.x) + ", y:" + Float.toString(limit.y) + ", z:"+ Float.toString(limit.z)); return limit;}public Quaternion(float real) { this.w = real; this.x = 0; this.y = 0; this.z = 0;}public float real() { return this.w;}public Quaternion unreal() { return new Quaternion(0, this.x, this.y, this.z);}public float abs() { return FloatMath.sqrt(x * x + y * y + z * z + w * w);}public Quaternion (float w, float x, float y, float z) { this.set(w, x, y, z);}public Quaternion multF(float scalar) { this.x *= scalar; this.y *= scalar; this.z *= scalar; this.w *= scalar; return this;}[/source]
In Topic: Incremental rotation towards target 3D
15 November 2012  02:43 AM
Well, I have to create my own quaternion class, and I didn't have an unreal() method so I was just trying to figure that out. I found through a search that with quaternions, i = j = k = sqrt(1).
[source lang="java"]public double unreal() { double i = FloatMath.sqrt(1); double unreal = this.x*i + this.y*i + this.z*i; return unreal; }[/source]
However, I just plugged that in and it didn't work. So I will check over some of my code.
[source lang="java"]public double unreal() { double i = FloatMath.sqrt(1); double unreal = this.x*i + this.y*i + this.z*i; return unreal; }[/source]
However, I just plugged that in and it didn't work. So I will check over some of my code.
In Topic: Incremental rotation towards target 3D
14 November 2012  10:31 PM
Sorry Alvaro, the documentation didn't help me as it does not show how they calculate the unreal part. If you say the unreal part is "0 + xi +yj +zk", then how do I get the value of i,j,k?
In my last post I had assumed the unreal part was 0 + q.x+q.y+q.z by making i,j and k equal to 1. As I said that produced bad results. I don't think setting them to zero would work, but I also tried multiplying each by the real part "w". Again bad results.
Sorry for not understanding, I think I'm struggling to understand the imaginary part of quaternions. It seems sometimes i,j,k just get dropped (meaning value of 1), and sometimes they are zero. I really appreciate your help.
In my last post I had assumed the unreal part was 0 + q.x+q.y+q.z by making i,j and k equal to 1. As I said that produced bad results. I don't think setting them to zero would work, but I also tried multiplying each by the real part "w". Again bad results.
Sorry for not understanding, I think I'm struggling to understand the imaginary part of quaternions. It seems sometimes i,j,k just get dropped (meaning value of 1), and sometimes they are zero. I really appreciate your help.
In Topic: Incremental rotation towards target 3D
14 November 2012  02:19 AM
Yes that helps!
Now the part I don't understand is the q.unreal(), what is going on there? My assumption based on q= w +xi + yj + zk is that the unreal part is x+y+z. However when I tried that I got strange results. Thank you for your help
Now the part I don't understand is the q.unreal(), what is going on there? My assumption based on q= w +xi + yj + zk is that the unreal part is x+y+z. However when I tried that I got strange results. Thank you for your help