Limit rotation within a volume
I'm working on a turret controller. The turret has a certain range of motion (it can't tip down past a certain point and it can't fire behind itself at a certain point).
I'm using a joystick for input and the joystick axes are mapped to different axes for Quaternion.AngleAxis rotations. The rotations work great, but the way I'm limiting the rotation doesn't. It works in the sense that it limits the rotation correctly, but I think because I'm totally halting the rotation calculation, it gets stuck and/or stops - it feels "sticky" at the edges. Pulling the joystick away from the limit-zone get things going again, but I'm looking for the turret to glide across the boundary I'm establishing.
I can't just test for Euler values, because many of the x,y,z Euler values are blended throughout the range of motion, so limiting it "in space" seems like the right starting point.
Thoughts?
using UnityEngine;
using System.Collections;
public class TargetInput : MonoBehaviour
{
public float deadzone = 0.25f;
public float angularVelocity = 0.5f;
public GameObject target;
private Vector2 stickInput;
private Quaternion lastRotation;
void Update ()
{
stickInput = new Vector2 (Input.GetAxis ("Horizontal"), Input.GetAxis ("Vertical"));
if (stickInput.magnitude < deadzone) {
stickInput = Vector2.zero;
} else {
Vector3 axisX = transform.forward;
Vector3 axisY = transform.right;
transform.rotation = Quaternion.AngleAxis (stickInput.x * angularVelocity, axisX) * transform.rotation;
transform.rotation = Quaternion.AngleAxis (stickInput.y * angularVelocity, axisY) * transform.rotation;
if (target.transform.position.z < 0.1f || target.transform.position.y > 3.8f) {
transform.rotation = lastRotation;
}
lastRotation = transform.rotation;
}
}
}
This might help a bit. The turret is double articulated and I'm using a target object to drive the articulation. Basically I want the target to rotate within the region I've highlighted on the dome. It's not quite the full upper hemisphere, and the rear quarter of the dome is truncated. In the code above, I test if the target object has rotated outside of the bottom plane or the back plane and pause the calculation. But I'm getting a "sticky" behavior at the edges rather than it just deflecting off the boundary smoothly.
Another bit is that I'm using the resultant look-at angles to drive a couple of servos. This part works fine as shown in the video - but in this iteration, I was driving Euler Angles directly (which resulted in gimbal lock at the north pole). I'm hoping to avoid that by using the Quaternions, but it's causing other problems.