- Home /
Rotating child object causes parent to drift in position.
I am creating a simulated robot in Unity, and I am attempting to simulate Pan / Tilt functions for the head. However, going through the list of rotation methods, i found they all end up causing the parent object to drift in the plane perpendicular to the axis of rotation. Everything actually works as intended, except the parent object keeps drifting around while the head turns.
Here is the specific snippet of code:
void moveHead () {
var panRotCur = panner.gameObject.transform.localRotation;
Quaternion panTo = Quaternion.Euler(panRotCur.eulerAngles.x, panHead, panRotCur.eulerAngles.z);
if (panRotCur.y != panTo.y ) {
panner.transform.localRotation = Quaternion.Slerp(panRotCur, panTo, panTiltSpeed *Time.deltaTime);
Debug.Log ("Pan thing is panning the thing");
}
}
And here is the full thing:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
public class roboSim : MonoBehaviour {
//Robot Body & General Movement
public GameObject robotBody; //Body of the robot.
Rigidbody Body;
public float turnSpeed = 0.2f; //How fast do i turn?
public float moveSpeed = 0.2f; //How fast does it look like i move?
float[] float4Imu = {0.0f, 0.0f, 0.0f, 0.0f};
float[] float3Imu = {0.0f, 0.0f, 0.0f};
//Body orientaiton in meat space
Quaternion bodyRot;
Quaternion getRot;
//Global Management
public Material[] statusMaterials; //blue, green, yellow, red
Robot robot; //Reference to data from Robot Class
IDictionary<string, string> IMUData;
//Wheel Management
public GameObject rightWheel;
public GameObject leftWheel;
//Renderer for the wheels
Renderer leftRend;
Renderer rightRend;
bool moveLeftWheel = false;
bool moveRightWheel = false;
float moveTime = 1.0f;
bool triggerMovement = false;
//Gripper Management
public GameObject gripperLeft;
public GameObject gripperRight;
/* Each gripper bit has an open and closed position stored,
and a target position which switches between the two. */
Vector3 leftGripperPos;
Vector3 leftGripClosePos;
Vector3 rightGripperPos;
Vector3 rightGripClosePos;
Vector3 leftGripTargetPos;
Vector3 rightGripTargetPos;
public bool closeGrip;
bool triggerGrip = false;
public float gripperMoveDist = 1.0f;
public float gripSpeed = 1.0f;
Renderer leftGripperRend;
Renderer rightGripperRend;
// Use this for initialization
void Start () {
//Find the robot object in order to get data to run the simulation
if (GameObject.Find ("Robot")) {
robot = GameObject.Find("Robot").GetComponent<Robot>();
} else {
//Debug.Log ("RoboSim not connecting to Robot");
}
//Robot will be moved by acting upon a rigid body... I think : D
Body = robotBody.GetComponent<Rigidbody> ();
bodyRot = robotBody.GetComponent<Transform> ().rotation;
//Get Renderer for Left and Right Wheels
leftRend = leftWheel.GetComponent<Renderer> ();
rightRend = rightWheel.GetComponent<Renderer> ();
//Managing gripper Setup
//Get the gripper status from Constants, which is determined by the chat.
closeGrip = Constants.gripperClose;
leftGripperPos = gripperLeft.gameObject.GetComponent<Transform> ().localPosition;
rightGripperPos = gripperRight.gameObject.GetComponent<Transform> ().localPosition;
leftGripClosePos = new Vector3 (leftGripperPos.x + gripperMoveDist,
leftGripperPos.y,
leftGripperPos.z);
rightGripClosePos = new Vector3 (rightGripperPos.x - gripperMoveDist,
rightGripperPos.y,
leftGripperPos.z);
leftGripperRend = gripperLeft.GetComponent<Renderer> ();
rightGripperRend = gripperRight.GetComponent<Renderer> ();
rightGripTargetPos = rightGripperPos;
leftGripTargetPos = leftGripperPos;
}
// Update is called once per frame
void Update () {
//Simulate input if the robot is not live to help with testing
if (Constants.robotLive == false) {
var inputSignal = simulateInput ();
if (inputSignal.sqrMagnitude > 0.05f * 0.05f) {
//Body.MovePosition(Body.position + (moveSpeed * Time.deltaTime) * inputSignal); //move in direction
var targetRotation = Quaternion.LookRotation (inputSignal);
Body.MoveRotation (Body.rotation.EaseTowards (targetRotation, turnSpeed));
}
} else {
//Get variables from the robot / skynet if the robot is live.
moveGripper ();
fetchIMU ();
bodyRot = Quaternion.Euler(0.0f, float3Imu[0], 0.0f);
Body.MoveRotation (Body.rotation.EaseTowards (bodyRot, turnSpeed));
//robotBody.transform.localRotation = bodyRot;
}
moveHead();
}
//Logic for moving the gripper graphic on the robot sim.
void moveGripper() {
closeGrip = Constants.gripperClose;
//Debug.Log ("Left Gripper Pos: " + leftGripperPos);
//Debug.Log ("Right Gripper Pos: " + rightGripperPos);
//Debug.Log ("Gripper Targets: " + leftGripTargetPos + " " + rightGripTargetPos);
if (closeGrip == true) {
leftGripTargetPos = leftGripClosePos;
rightGripTargetPos = rightGripClosePos;
//Debug.Log("Gripper Triggered");
} else if (closeGrip == false) {
leftGripTargetPos = leftGripperPos;
rightGripTargetPos = rightGripperPos;
}
gripperLeft.transform.localPosition =
Vector3.Lerp (gripperLeft.transform.localPosition,
leftGripTargetPos,
gripSpeed * Time.deltaTime);
gripperRight.transform.localPosition =
Vector3.Lerp (gripperRight.transform.localPosition,
rightGripTargetPos,
gripSpeed * Time.deltaTime);
var leftGripCur = gripperLeft.transform.localPosition;
var rightGripCur = gripperRight.transform.localPosition;
if (Vector3.Distance (leftGripCur, leftGripTargetPos) > 0.05f ||
Vector3.Distance (rightGripCur, rightGripTargetPos) > 0.05f) {
leftGripperRend.sharedMaterial = statusMaterials [1];
rightGripperRend.sharedMaterial = statusMaterials [1];
} else {
leftGripperRend.sharedMaterial = statusMaterials[0];
rightGripperRend.sharedMaterial = statusMaterials[0];
}
}
//Manage Head movement ----------------------------------------------------------
public float panHead = 0;
public float tiltHead = 0;
public GameObject panner;
public GameObject tilter;
bool changePan = false;
bool changeTilt = false;
//Pan Rot Y, Tilt RotX
float panY;
float tiltX;
public float panTiltSpeed = 1;
void startHead() {
}
void moveHead () {
var panRotCur = panner.gameObject.transform.localRotation;
Quaternion panTo = Quaternion.Euler(panRotCur.eulerAngles.x, panHead, panRotCur.eulerAngles.z);
if (panRotCur.y != panTo.y ) {
panner.transform.localRotation = Quaternion.Slerp(panRotCur, panTo, panTiltSpeed *Time.deltaTime);
Debug.Log ("Pan thing is panning the thing");
}
}
//Simulate input when the robot is not live.-----------------------------------
Vector3 simulateInput() {
var simulateInput = new Vector3 (
Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical"),
Input.GetAxisRaw("Zed")
);
if (Input.GetKeyDown (KeyCode.F)) {
Debug.Log("Key F is Down Yo");
moveLeftWheel = true;
moveRightWheel = true;
leftRend.sharedMaterial = statusMaterials[1];
rightRend.sharedMaterial = statusMaterials[1];
triggerMovement = true;
StartCoroutine("moveDuration");
}
if (Input.GetKeyDown (KeyCode.O)) {
if (Constants.gripperClose == true) {
Constants.gripperClose = false;
} else if (Constants.gripperClose == false) {
Constants.gripperClose = true;
}
}
moveGripper();
return simulateInput;
}
IEnumerator moveDuration () {
if (triggerMovement == true && moveLeftWheel == true || moveRightWheel == true) {
Debug.Log ("Movement Triggered");
triggerMovement = false;
yield return new WaitForSeconds (moveTime);
moveLeftWheel = false;
moveRightWheel = false;
leftRend.sharedMaterial = statusMaterials [0];
rightRend.sharedMaterial = statusMaterials [0];
Debug.Log ("Movement Complete");
} else {
Debug.Log("We already movin yo!");
}
}
void fetchIMU () {
IMUData = robot.getIMUVariables();
if (IMUData != null) {
try {
float qx = (float)Convert.ToDouble(IMUData["quaternion_x"]);
float qy = (float)Convert.ToDouble(IMUData["quaternion_y"]);
float qz = (float)Convert.ToDouble(IMUData["quaternion_z"]);
float qw = (float)Convert.ToDouble(IMUData["quaternion_w"]);
float ex = (float)Convert.ToDouble(IMUData["euler_heading"]);
float ey = (float)Convert.ToDouble (IMUData["euler_roll"]);
float ez = (float)Convert.ToDouble (IMUData["euler_pitch"]);
float[] efloat = float3Imu;
if (ex >= 0.0f) {
efloat[0] = ex;
}
if (ey >= 0.0f) {
efloat[1] = ey;
}
if (ez >= 0.0f) {
efloat[2] = ez;
}
/*Debug.Log ("Euler Rotation - Heading:" + efloat[0] +
" Roll: " + efloat[1] +
" Pitch: " + efloat[2]);*/
float3Imu = efloat;
if (qx >= 0.0f) {
float4Imu[0] = qx;
}
if (qy >= 0.0f) {
float4Imu[1] = qy;
}
if (qz >= 0.0f) {
float4Imu[2] = qz;
}
if (qw >= 0.0f) {
float4Imu[3] = qw;
}
//Quaternion IMURot = new Quaternion(qx, qy, qz, qw);
//bodyRot = IMURot;
getRot = new Quaternion(float4Imu[0],
float4Imu[1],
float4Imu[2],
float4Imu[3]);
} catch(KeyNotFoundException) {}
//getRot = new Quaternion(qx, qy, qz, qw);
/*Debug.Log ("IMU = x: " + float4Imu[0] +
" y: " + float4Imu[1] +
" z: " + float4Imu[2] +
" w: " + float4Imu[3]);*/
//foreach (KeyValuePair<string, string> entry in IMUData) {
//Debug.Log ("Key");
//Debug.Log (entry.Key);
//Debug.Log ("Value");
//Debug.Log (entry.Value);
}
//} else {
//Debug.Log("No IMU Data found");
//}
}
}
Answer by jillytot · Sep 27, 2016 at 08:36 PM
So it looks like the rigid body used to control the parent object was being interfered with by the child rotation. I fixed the problem by simply checking the "Is Kinematic" box on the parent object.
Your answer
Follow this Question
Related Questions
Rotation and position centres are wrong 1 Answer
Child world location 3 Answers
Flip over an object (smooth transition) 3 Answers
Issue with viewport rotation values. 0 Answers