-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCameraFromIMU.cs
147 lines (125 loc) · 5.12 KB
/
CameraFromIMU.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
using UnityEngine;
using System.Collections;
using System;
using Tinkerforge;
public class CameraFromIMU : MonoBehaviour {
private static string _host = "localhost";
private static int _port = 4223;
private static string _uid = "6wUjm3"; // Change to your UID
private static BrickIMU _imu;
private static IPConnection _ipcon;
private static Quaternion _q = new Quaternion(0.0f,0.0f,0.0f,1.0f);
private static Quaternion _qOrigin = new Quaternion(0.0f,0.0f,0.0f,1.0f);
private static Quaternion _qPrevious = new Quaternion(0.0f,0.0f,0.0f,1.0f);
public float _speed = 100.0f; // Forwards speed.
public float _maxStrafeVelocity = 100.0f; // Max speed left and right.
public float _strafeKeyProportion = 0.0f; // Current left/right key press proportion (-ve = left, +ve = right).
public float _updownKeyProportion = 0.0f; // Current up/down key press proportion.
public float _rotateLeftRightKeyAngle = 0.0f; // Current angular rotation around world's up axis caused by Q/E keys.
public float _maxLiftVelocity = 25.0f; // Velocity upwards when up is pressed (eventually, when left and right are down).
public float _maxFallVelocity = 50.0f; // Velocity downwards when pressing downwards.
public float _yawInfluenceFromRoll = 0.01f;
// Use this for initialization
void Start () {
_ipcon = new IPConnection(); // Create connection to brickd
_imu = new BrickIMU(_uid, _ipcon); // Create device object
_ipcon.Connect(_host,_port); // Add device to IP connection
// Don't use device before it is added to a connection
// Set period for quaternion callback to 10ms
_imu.SetQuaternionPeriod(10);
// Register quaternion callback to QuaternionCB
_imu.Quaternion += QuaternionCB;
// Set rotational origin to however the IMU is pointing at the start.
float x,y,z,w;
_imu.GetQuaternion(out x, out y, out z, out w);
_qOrigin.w = w;
_qOrigin.x = x;
_qOrigin.y = y;
_qOrigin.z = z;
_imu.LedsOff(); // Turn LEDs off.
_imu.SetConvergenceSpeed( 5 ); // 5ms convergence.
}
// Quaternion callback
static void QuaternionCB(BrickIMU sender, float x, float y, float z, float w)
{
//Debug.Log("x: " + x + "\ny: " + y + "\nz: " + z + "\nw: " + w + "\n");
_qPrevious = _q; // Save q to qPrevious
_q.w = w;
_q.x = x;
_q.y = y;
_q.z = z;
}
void OnApplicationExit() {
_ipcon.Disconnect();
}
void OnGUI() {
GUI.Box( new Rect( 5, 5, 200, 24*2 ),
"Quaternion: " + _q.ToString() + "\n" +
"Camera: " + transform.rotation.ToString() );
}
// Update is called once per frame
void Update () {
// Conjugate of current quaternion:
float x,y,z,w;
x = -_q.x;
y = -_q.y;
z = -_q.z;
w = _q.w;
// Multiply with origin quaternion:
float xn,yn,zn,wn;
wn = w * _qOrigin.w - x * _qOrigin.x - y * _qOrigin.y - z * _qOrigin.z;
xn = w * _qOrigin.x + x * _qOrigin.w + y * _qOrigin.z - z * _qOrigin.y;
yn = w * _qOrigin.y - x * _qOrigin.z + y * _qOrigin.w + z * _qOrigin.x;
zn = w * _qOrigin.z + x * _qOrigin.y - y * _qOrigin.x + z * _qOrigin.w;
// Rotate the camera relative to the world frame axes, by the roll pitch yaw of the IMU.
Quaternion q = new Quaternion( xn, yn, zn, wn );
transform.rotation = Quaternion.identity;
transform.Rotate( Vector3.right * q.eulerAngles.x, Space.World );
transform.Rotate( Vector3.forward * q.eulerAngles.y, Space.World );
transform.Rotate( Vector3.up * q.eulerAngles.z, Space.World );
// Strafe according to left/right keys.
//_strafeKeyProportion = Input.GetAxis("Horizontal");
if (Input.GetKey (KeyCode.A))
_strafeKeyProportion = -1.0f;
else if (Input.GetKey (KeyCode.D))
_strafeKeyProportion = 1.0f;
else
_strafeKeyProportion = 0.0f;
transform.Translate( Vector3.right * _strafeKeyProportion * _maxStrafeVelocity * Time.deltaTime );
// Rise/fall (w.r.t. to the *world*'s z-axis) according to up/down keys.
//_updownKeyProportion = Input.GetAxis("Vertical");
if (Input.GetKey (KeyCode.W))
_updownKeyProportion = 1.0f;
else if (Input.GetKey (KeyCode.S))
_updownKeyProportion = -1.0f;
else
_updownKeyProportion = 0.0f;
if( _updownKeyProportion > 0.0f )
{
transform.Translate( Vector3.up * _updownKeyProportion * _maxLiftVelocity * Time.deltaTime, Space.World );
}
else
{
transform.Translate( Vector3.up * _updownKeyProportion * _maxFallVelocity * Time.deltaTime, Space.World );
}
// Rotate around up world's up axis by Q/E keys.
if (Input.GetKey (KeyCode.Q))
_rotateLeftRightKeyAngle = (_rotateLeftRightKeyAngle-1.0f) % 360.0f;
else if (Input.GetKey (KeyCode.E))
_rotateLeftRightKeyAngle = (_rotateLeftRightKeyAngle+1.0f) % 360.0f;
// But also rotate around world axis by an amount proportional to roll.
Debug.Log( q.eulerAngles.y );
float roll = q.eulerAngles.y;
if( roll > 180.0f ){
roll = roll - 360.0f;}
if(roll > 90.0f){
roll = 180.0f - roll;}
else if(roll < -90.0f){
roll = -180.0f - roll;}
_rotateLeftRightKeyAngle = (_rotateLeftRightKeyAngle - (roll * _yawInfluenceFromRoll)) % 360.0f;
// Do that rotation.
transform.Rotate( Vector3.up * _rotateLeftRightKeyAngle, Space.World );
// Fly forwards.
transform.Translate(Vector3.forward * Time.deltaTime * _speed);
}
}