GazeStabilization.cc
Go to the documentation of this file.
1 
2 #include "GazeStabilization.hh"
3 
4 #include <cstdio>
5 #include <iostream>
6 
8 //#include "mbs_sensor.h"
9 #include "pinv.hh"
10 
11 #include <Eigen/Dense>
12 
14 
16 {
17 
18  this->options = options;
19 
20  if (options->model == 0) // armar 4 WO torso
21  {
22  n_LB_joints = 6;
23  n_UB_joints = 7;
24  n_virt_joints = 3;
25  }
26  else if (options->model == 1) // armar 4 W torso
27  {
28  n_LB_joints = 8;
29  n_UB_joints = 7;
30  n_virt_joints = 3;
31  }
32  else if (options->model == 2) // armar 3
33  {
34  n_LB_joints = 10;
35  n_UB_joints = 5;
36  n_virt_joints = 3;
37  }
38 
39  input = new GazeStabInput(n_LB_joints, n_UB_joints);
40  output = new GazeStabOutput(n_UB_joints);
41 
42 
43  mbs_data_virt_q.reserve(get_n_all_joints() + 1);
44  mbs_data_virt_qd.reserve(get_n_all_joints() + 1);
45  mbs_data_virt_qdd.reserve(get_n_all_joints() + 1);
46 
47  optFlow_pred.resize(2);
48  gyroscopeRotation_pred.resize(3);
49 }
50 
51 
53 {
54  delete input;
55  delete output;
56  delete options;
57 }
58 
59 
61 {
62 
63  printf("hello from GazeSatb init\n");
64 
65  // create corresponding sensors
66  allocate_sensor(&sens_virt, get_n_all_joints());
67  init_sensor(&sens_virt, get_n_all_joints());
68 
69  allocate_sensor(&sens_eye, get_n_real_joints());
70  init_sensor(&sens_eye, get_n_real_joints());
71 
72  allocate_sensor(&sens_head_imu, get_n_real_joints() - 2);
73  init_sensor(&sens_head_imu, get_n_real_joints() - 2);
74 
75  qd_gaze_des = Eigen::VectorXd::Zero(get_n_gaze_joints());
76  q_UB_des = Eigen::VectorXd::Zero(n_UB_joints);
77 
78  if ((options->model == 0) || (options->model == 1)) // armar4
79  {
80  q_UB_des(2) = M_PI; // = initial configuration
81 
82  q_virt[0] = -1.9415;
83  q_virt[1] = 0.0;
84  q_virt[2] = 0.0;
85  }
86  else // armar 3
87  {
88  q_virt[0] = 1.18;
89  q_virt[1] = M_PI;
90  q_virt[2] = -M_PI / 2.;
91  }
92 
93  //input->pos_target[0] = input->qd_LB[1] + 1; // 1m in front of the robot
94 
95  // TODO use newton raphson to find the initial q_virt
96 
97  vel_xFP = Eigen::VectorXd::Zero(6);
98  pos_xFP = Eigen::Vector3d::Zero();
99  desired_vel_xFP = Eigen::VectorXd::Zero(6);
100 
101  Jac_IK.resize(6, get_n_gaze_joints());
102  Jac_FK.resize(6, get_n_all_joints());
103  inv_Jac.resize(get_n_gaze_joints(), 6);
104  null_space.resize(get_n_gaze_joints(), get_n_gaze_joints());
105 
106  last_t_ctrl = 0.;
107 
108 }
109 
111 {
112 
113  /************
114  * Get input
115  * *********/
116  double tsim = input->tsim;
117 
118  /************
119  * Forward kinematics (FK)
120  * *********/
121 
122  // copy lower body joints pos
123  for (int i = 1; i <= n_LB_joints; i++)
124  {
125  mbs_data_virt_q[i] = input->q_LB[i - 1];
126  mbs_data_virt_qd[i] = input->qd_LB[i - 1];
127  }
128 
129  // copy head joints pos
130  for (int i = n_LB_joints + 1; i <= get_n_real_joints(); i++)
131  {
132  mbs_data_virt_q[i] = input->q_UB[i - (n_LB_joints + 1)];
133  mbs_data_virt_qd[i] = input->qd_UB[i - (n_LB_joints + 1)];
134  }
135 
136  // copy virt joints pos
137  for (int i = get_n_real_joints() + 1; i <= get_n_all_joints(); i++)
138  {
139  mbs_data_virt_q[i] = q_virt[i - (get_n_real_joints() + 1)];
140  mbs_data_virt_qd[i] = qd_gaze_des(i - (n_LB_joints + 1));
141  }
142 
143  if (options->model == 0) // Armar4 WO torso
144  {
145  mbs_sensor_ArmarIV_GazeStab_virt(&sens_virt, &mbs_data_virt_q[0], &mbs_data_virt_qd[0], &mbs_data_virt_qdd[0], 1);
146  }
147  else if (options->model == 1) // Armar4 W torso
148  {
149  mbs_sensor_ArmarIV_W_Torso_virt(&sens_virt, &mbs_data_virt_q[0], &mbs_data_virt_qd[0], &mbs_data_virt_qdd[0], 1);
150  }
151  else if (options->model == 2) // Armar3
152  {
153  mbs_sensor_ArmarIII_simplified_virt(&sens_virt, &mbs_data_virt_q[0], &mbs_data_virt_qd[0], 3); // virtual fixation point
154  }
155 
156  predict_optFlow_xy();
157  predict_optFlow_index();
158  predict_IMU();
159 
160  for (int row = 0; row < 6; row++)
161  for (int col = 0; col < get_n_all_joints(); col++)
162  {
163  Jac_FK(row, col) = sens_virt.J[row + 1][col + 1];
164  }
165 
166  vel_xFP = Jac_FK.block(0, 0, 6, n_LB_joints) * input->qd_LB_des;
167 
168  for (int i = 0; i < 3; i++)
169  {
170  pos_xFP(i) = sens_virt.P[i + 1];
171  }
172 
173  for (int row = 0; row < 3; row++)
174  for (int col = 0; col < 3; col++)
175  {
176  R_xFP[row][col] = sens_virt.R[row + 1][col + 1];
177  }
178 
179  pos_err = input->pos_target - pos_xFP;
180 
181  // if (pos_err.norm() > 0.1)
182  // {
183  // ARMARX_IMPORTANT_S << "fixation point error large = " << pos_err(0) << " " << pos_err(1) << " " << pos_err(2) << " m";
184  // pos_err = 0.1 * pos_err / pos_err.norm();
185  // }
186 
187  double K1 = 0.;//5.;//100;
188  double K2 = 0.;//2.;//40;
189  double K3 = 0.;//5.;//100; // null space
190  Eigen::VectorXd drift_corr(6);
191  drift_corr << K1* pos_err, 0, K2* get_or_err(), 0;
192 
193  desired_vel_xFP = -1 * vel_xFP + drift_corr;
194 
195  /************
196  * Inverse kinematics (IK)
197  * *********/
198 
199  Jac_IK = Jac_FK.block(0, n_LB_joints, 6, get_n_gaze_joints());
200 
202  {
203  Eigen::VectorXd w(get_n_gaze_joints()); // weights
204 
205  for (int i = 0; i < get_n_gaze_joints(); i++)
206  {
207  w(i) = 1.;
208  }
209 
210  w(get_n_gaze_joints() - 3) = options->lambda * 19.13 / fabs(q_virt[0]); // zoom
211  w(get_n_gaze_joints() - 2) = options->lambda * 1.2054;
212  w(get_n_gaze_joints() - 1) = options->lambda * 2.1431;
213 
214  //w(get_n_gaze_joints() - 4) = 8.; // minimize eye motion
215 
216  inv_Jac = weightedPseudoInverse(Jac_IK, w);
217  }
218  else if (options->pseudo_inverse)
219  {
220  inv_Jac = pseudoInverse(Jac_IK);
221  }
222 
223  // null space projection
224  null_space = Eigen::MatrixXd::Identity(get_n_gaze_joints(), get_n_gaze_joints()) - inv_Jac * Jac_IK;
225 
226  Eigen::Map<Eigen::VectorXd> tmp(&input->q_UB[0], n_UB_joints);
227  Eigen::VectorXd null_space_err(get_n_gaze_joints());
228  null_space_err << K3*(q_UB_des - tmp), 0., 0., 0.; // 0 correction for virt joints
229 
230  qd_gaze_des = inv_Jac * desired_vel_xFP + null_space * null_space_err;
231 
232  //std::cout << "hello : " << Jac_IK*inv_Jac << std::endl;
233  //std::cout << "hello : " << Jac_FK.block(0,0,6,6)*qd_LB_des + Jac_IK*qd_gaze_des << std::endl;
234 
235  /************
236  * Update q_virt
237  * *********/
238 
239  double dt = tsim - last_t_ctrl;
240  if (dt > 0.1)
241  {
242  ARMARX_IMPORTANT_S << "gaze stab control perido too large = " << dt << " s";
243  dt = 0.;
244  }
245 
246  for (int i = 0; i < n_virt_joints; i++)
247  {
248  q_virt[i] += dt * qd_gaze_des(i + n_UB_joints);
249  }
250 
251  last_t_ctrl = tsim;
252 
253  /************
254  * Write output
255  * *********/
256 
257  for (int i = 0; i < n_UB_joints; i++)
258  {
259  output->qd_UB_des[i] = qd_gaze_des(i);
260  }
261 
262  //ARMARX_LOG_S << pos_err;
263  //ARMARX_IMPORTANT_S << "hello" << input->qd_LB_des[7];
264  // for (int i = 0; i < 10; i++)
265  // {
266  // ARMARX_IMPORTANT_S << "input lower body velocity " << i << " " << input->qd_LB_des[i];
267  // }
268 
269  // for (int i = 0; i < 5; i++)
270  // {
271  // ARMARX_IMPORTANT_S << "output upper body velocity " << i << " " << output->qd_UB_des[i];
272  // }
273 }
274 
276 {
277 
278  printf("hello from GazeSatb finish \n");
279 
280  // free sensors
281  free_sensor(&sens_virt);
282  free_sensor(&sens_eye);
283  free_sensor(&sens_head_imu);
284 
285 }
286 
287 
288 // predicotr part
289 void GazeStabilization::predict_IMU()
290 {
291  mbs_sensor_ArmarIII_simplified_virt(&sens_head_imu, &mbs_data_virt_q[0], &mbs_data_virt_qd[0], 1); //head IMU kin
292 
293  gyroscopeRotation_pred[0] = -1 * (sens_head_imu.R[1][1] * sens_head_imu.OM[1] + sens_head_imu.R[2][1] * sens_head_imu.OM[2] + sens_head_imu.R[3][1] * sens_head_imu.OM[3]);
294  gyroscopeRotation_pred[2] = sens_head_imu.R[1][2] * sens_head_imu.OM[1] + sens_head_imu.R[2][2] * sens_head_imu.OM[2] + sens_head_imu.R[3][2] * sens_head_imu.OM[3];
295  gyroscopeRotation_pred[1] = sens_head_imu.R[1][3] * sens_head_imu.OM[1] + sens_head_imu.R[2][3] * sens_head_imu.OM[2] + sens_head_imu.R[3][3] * sens_head_imu.OM[3];
296 }
297 
298 void GazeStabilization::predict_optFlow_xy()
299 {
300  // TODO (use head orientation to select x and y optical flow axis)
301 
302  //optFlow_pred[0] = atan2(sens_virt.V[2], q_virt[0]);
303  optFlow_pred[1] = -1 * atan2(sens_virt.V[3], q_virt[0]);
304 }
305 
306 void GazeStabilization::predict_optFlow_index()
307 {
308  double v_zoom; // zoom velocity [m/s]
309  double v_hor; // horizontal velocity [m/s]
310  double v_ver; // vertical velocity [m/s]
311  double v_tilt; // tilt rotational velocity [rad/s]
312  double v_yaw; // yaw rotational velocity [rad/s]
313  double v_roll; // roll rotational velocity [rad/s]
314 
315  const double f = 529.9 * (59.7 / 640.); // focal length converted in deg (from camera calibration file)
316 
317  mbs_sensor_ArmarIII_simplified_virt(&sens_eye, &mbs_data_virt_q[0], &mbs_data_virt_qd[0], 2); //eye kin
318 
319  v_zoom = get_qdvirt(0);
320  v_tilt = get_qdvirt(1);
321  v_yaw = sens_eye.R[1][3] * sens_virt.OM[1] + sens_eye.R[2][3] * sens_virt.OM[2] + sens_eye.R[3][3] * sens_virt.OM[3]; //get_qdvirt(2);
322 
323  v_hor = sens_eye.R[1][2] * sens_eye.V[1] + sens_eye.R[2][2] * sens_eye.V[2] + sens_eye.R[3][2] * sens_eye.V[3]; // vy in eye frame
324  v_ver = sens_eye.R[1][3] * sens_eye.V[1] + sens_eye.R[2][3] * sens_eye.V[2] + sens_eye.R[3][3] * sens_eye.V[3]; // vz in eye frame;
325  v_roll = sens_eye.R[1][1] * sens_eye.OM[1] + sens_eye.R[2][1] * sens_eye.OM[2] + sens_eye.R[3][1] * sens_eye.OM[3];
326 
327  //double integral with X in [-15:15] deg and Y in [-11:11] deg for:
328  // computed with www.wolframalpha.com
329  double surf = 30.*22.;
330 
331  // 1) zoom : sqrt(X^2 + Y^2)/ surf
332  double int_zoom = 6612.53 / surf;
333 
334  // 2) tilt : sqrt((X*Y)^2 + Y^4) / (f * surf)
335  double int_tilt = 40359.9 / (f * surf);
336 
337  // 3) yaw : sqrt((X*Y)^2 + X^4) / (f * surf)
338  double int_yaw = 58943.5 / (f * surf);
339 
340  // 4) v_hor : constant f
341  double int_hor = f ;
342 
343  // 5) v_ver : constant f
344  double int_ver = f;
345 
346  // 6) roll : sqrt(X^2 + Y^2) / surf
347  double int_roll = 6612.53 / surf;
348 
349 
350  // mean distance of the optical flow [deg]
351  mean_optFl_pred = 0.;
352  mean_optFl_pred += int_zoom * fabs(v_zoom / q_virt[0]);
353  mean_optFl_pred += int_tilt * fabs(v_tilt);
354  mean_optFl_pred += int_yaw * fabs(v_yaw);
355  mean_optFl_pred += int_hor * fabs(v_hor / q_virt[0]);
356  mean_optFl_pred += int_ver * fabs(v_ver / q_virt[0]);
357  mean_optFl_pred += int_roll * fabs(v_roll);
358 
359  double f_rad = f * M_PI / 180.0; // = 0.85
360  optFlow_pred[0] = (f_rad / q_virt[0]) * v_hor + f_rad * v_yaw;
361  optFlow_pred[0] = optFlow_pred[0] / 3.;
362 
363 }
364 
365 
ARMARX_IMPORTANT_S
#define ARMARX_IMPORTANT_S
Definition: Logging.h:203
allocate_sensor
void allocate_sensor(MbsSensor *psens, int njoint)
Allocate the Jacobian matrix of the MbsSensor according to the number of joints in the multibody syst...
Definition: mbs_sensor.c:14
GazeStabOptions::weighted_inverse
int weighted_inverse
Definition: GazeStabOptions.hh:12
free_sensor
void free_sensor(MbsSensor *psens)
Free the memory of MbsSensor structure.
Definition: mbs_sensor.c:49
mbs_sensor_ArmarIV_W_Torso_virt
void mbs_sensor_ArmarIV_W_Torso_virt(MbsSensor *sens, double *q, double *qd, double *qdd, int isens)
Definition: mbs_sensor_ArmarIV-W-Torso-virt_new.c:37
GazeStabilization::get_or_err
double get_or_err()
Definition: GazeStabilization.hh:37
MbsSensor::V
double V[4]
Velocity vector of the sensor expressed in the inertial frame: .
Definition: mbs_sensor2.h:21
GazeStabOptions::lambda
double lambda
Definition: GazeStabOptions.hh:14
GazeStabOutput
Definition: GazeStabInputOutput.hh:26
GazeStabilization::get_n_gaze_joints
int get_n_gaze_joints(void)
Definition: GazeStabilization.hh:46
GazeStabilization::finish
void finish()
Definition: GazeStabilization.cc:275
GazeStabilization::output
GazeStabOutput * output
Definition: GazeStabilization.hh:17
GazeStabilization::GazeStabilization
GazeStabilization(GazeStabOptions *options)
Definition: GazeStabilization.cc:15
GazeStabOptions::pseudo_inverse
int pseudo_inverse
Definition: GazeStabOptions.hh:11
GazeStabInput::pos_target
Eigen::Vector3d pos_target
Definition: GazeStabInputOutput.hh:22
weightedPseudoInverse
Eigen::MatrixXd weightedPseudoInverse(const Eigen::MatrixXd &a, const Eigen::VectorXd w)
Definition: pinv.hh:13
MbsSensor::J
double * J[7]
Jacobian matrix of the sensor: .
Definition: mbs_sensor2.h:29
GazeStabOptions
Definition: GazeStabOptions.hh:3
MbsSensor::P
double P[4]
Position vector of the sensor expressed in the inertial frame: .
Definition: mbs_sensor2.h:19
GazeStabOutput::qd_UB_des
std::vector< double > qd_UB_des
Definition: GazeStabInputOutput.hh:33
init_sensor
void init_sensor(MbsSensor *psens, int njoint)
Initialize all fields of MbsSensor structure to 0.
Definition: mbs_sensor.c:25
GazeStabilization::input
GazeStabInput * input
Definition: GazeStabilization.hh:16
GazeStabInput::q_UB
std::vector< double > q_UB
Definition: GazeStabInputOutput.hh:15
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
GazeStabilization.hh
GazeStabInput::q_LB
std::vector< double > q_LB
Definition: GazeStabInputOutput.hh:14
GazeStabilization::get_qdvirt
double get_qdvirt(int i)
Definition: GazeStabilization.hh:24
M_PI
#define M_PI
Definition: MathTools.h:17
GazeStabOptions::model
int model
Definition: GazeStabOptions.hh:9
mbs_sensor_ArmarIII_simplified_virt
void mbs_sensor_ArmarIII_simplified_virt(MbsSensor *sens, double *q_dof, double *qd_dof, int isens)
Definition: mbs_sensor_ArmarIII_simplified_virt_new.c:39
GazeStabInput::tsim
double tsim
Definition: GazeStabInputOutput.hh:13
GazeStabInput
Definition: GazeStabInputOutput.hh:6
pinv.hh
mbs_sensor_ArmarIV_GazeStab_virt
void mbs_sensor_ArmarIV_GazeStab_virt(MbsSensor *sens, double *q, double *qd, double *qdd, int isens)
Definition: mbs_sensor_ArmarIV-GazeStab-virt_new.c:37
GazeStabilization::options
GazeStabOptions * options
Definition: GazeStabilization.hh:18
GazeStabilization::get_n_all_joints
int get_n_all_joints(void)
Definition: GazeStabilization.hh:50
GazeStabilization::~GazeStabilization
~GazeStabilization()
Definition: GazeStabilization.cc:52
GazeStabilization::init
void init()
Definition: GazeStabilization.cc:60
GazeStabInput::qd_LB_des
Eigen::VectorXd qd_LB_des
Definition: GazeStabInputOutput.hh:20
MbsSensor::OM
double OM[4]
Angular velocity vector of the sensor expressed in the inertial frame: .
Definition: mbs_sensor2.h:22
symbolic_routines.h
GazeStabilization::get_n_real_joints
int get_n_real_joints(void)
Definition: GazeStabilization.hh:42
pseudoInverse
Eigen::MatrixXd pseudoInverse(const Eigen::MatrixXd &a, double epsilon=std::numeric_limits< double >::epsilon())
Definition: pinv.hh:6
GazeStabilization::control_loop
void control_loop()
Definition: GazeStabilization.cc:110
MbsSensor::R
double R[4][4]
Rotation matrix from the inertial frame to the sensor frame: .
Definition: mbs_sensor2.h:20
Logging.h
GazeStabInput::qd_LB
std::vector< double > qd_LB
Definition: GazeStabInputOutput.hh:17
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:42
GazeStabInput::qd_UB
std::vector< double > qd_UB
Definition: GazeStabInputOutput.hh:18