A strange tilt when using alignAxisToVect

Hi. I wrote some code for aligning a sentry towards the enemy. I am using two elements for the sentry, each parented to an empty, and I am using alignAxisToVect to align those empties to the enemy.


The lower element (yellow) should only rotate on the Z axis, and the upper element (red) should only rotate on the Y axis. I have managed to do so with the lower element by assigning a zero to one of the numbers in the vector, however, the same doesn’t work with the upper element. Also, the upper element has a slight tilt.

Please help.


from bge import logic


scene = logic.getCurrentScene()


cube = scene.objects["Cube"]
pivot_z = scene.objects["PivotZ"]
pivot_x = scene.objects["PivotX"]


def main():
            
    vector_x = list(pivot_x.getVectTo(cube))
    pivot_x.alignAxisToVect(vector_x[1], 0, 1.0)


    vector_z = list(pivot_z.getVectTo(cube))
    vector_z[1][2] = 0
    pivot_z.alignAxisToVect(vector_z[1], 0, 1.0)

aiming_tilt.blend (434 KB)

Hi! It’s normal. Maybe this file can help you to understand the mechanism of alignAxisToVect:

http://www.pasteall.org/blend/35988

Your file with alignment of Y axis to a new empty:

http://www.pasteall.org/blend/35989

You need to calculate the cross product between the parent rotation vector and target vector.
Here is an old script that I have written for somebody else, which had the same problem.
It has also limit the up and down rotation.
You need to modify the script for your needs.


from bge import logic
from math import *
from mathutils import *

cont = logic.getCurrentController()
own = cont.owner

max = -30 # Grad
min = 10 # Grad

vec = Vector((1,0,0))
oriP = own.parent.worldOrientation
vec2 = oriP*vec
vec3 = own.getVectTo(own["object"])
vec4 = vec2.cross(vec3[1])
own.alignAxisToVect(vec4, 2, own["speed"])

# Lokaler Winkel
ori = own.localOrientation
ang = degrees(ori.to_euler().x) 
#print (ang)

# Winkel begrenzen
if ang < max:
    own.localOrientation = [radians(max), 0.0, 0.0]
if ang > min:
    own.localOrientation = [radians(min), 0.0, 0.0]

Also align axis to vect is (was) a little bit broken, it sometimes causes strange flipping at certain angles. There’s a couple of thteads here that describe alternative methods if you can search for them.

@youle Yeah, that first file makes things clearer. Thank you for the correction. This is a simple and great solution. It will work nicely.

@HG1 I have actually tried calculating the cross product previously, but it seems I did it wrong. Thank you for the script.

@Smoking_mirror I’ll try working with alignAxis for now, if problems appear I will seek out alternatives. Thank you for the warning.

You can use a second alignAxisToVect to lock the axis you want to restrict.

For the lower part try something like:


from mathutils import Vector   #import this if you dont have it already

vec = pivot_x.getVectTo(cube)[1]
vec2 = pivot_y.getVectTo(pivot_x)[1]

#align lower yellow part
pivot_x.alignAxisToVect(vec,0,1.0)                   #Align X axis to cube local vector
pivot_x.alignAxisToVect(Vector([0,0,1]),2,1.0)    #Align Z axis to global Z vector ([0,0,1])

#pivot red turret part

pivot_y.alignAxisToVect(vec,0,1.0)                   #Align Y axis to cube local vector
pivot_y.alignAxisToVect(vec2,1,1.0)                 #Align X axis to base's local vector

Untested, and probably doesn’t work as-is, but you get the idea. Rather than trying to correct a Vector, just use a second alignment call.

Thing is, alignAxisToVect will only concern itself with the axis you’re wanting it to align. It doesn’t care if it has to roll the other two axes to get it to where it needs to be, which results in unintended ‘tilting’.

yeah

I just use a second point of referance like a empty or the base objects

object.worldOrientation.col[0] etc

from bge import logic


scene = logic.getCurrentScene()


cube = scene.objects["Cube"]
pivot_z = scene.objects["PivotZ"]
pivot_x = scene.objects["PivotX"]


def main():
            
    vector_x = list(pivot_x.getVectTo(cube))
    pivot_x.alignAxisToVect(vector_x[1], 0, 1.0)
## guessed but I think I am close, can't see the axis orientation of the gun. X is forward so I tried y
    pivot_x.alignAxisToVect(pivot_z.worldOrientation.col[1] ,1, 1)




    vector_z = list(pivot_z.getVectTo(cube))
    vector_z[1][2] = 0
    pivot_z.alignAxisToVect(vector_z[1], 0, 1.0)