bool SpecificWorker::setParams(RoboCompCommonBehavior::ParameterList params)
{
	QMutexLocker locker(mutex);

	// YEP: OMNI-DIRECTIONAL ROBOTS: Abstract: All the robots introduced in chapter 7, with the exception of syncro-drive vehicles...
	// NOPE: http://cdn.intechopen.com/pdfs-wm/465.pdf
	R  = QString::fromStdString(params["DelfosBase.WheelRadius"].value).toFloat(); 
	l1 = QString::fromStdString(params["DelfosBase.DistAxes"].value   ).toFloat();
	l2 = QString::fromStdString(params["DelfosBase.AxesLength"].value ).toFloat();
	printf("l1: %f\n", l1);
	printf("l2: %f\n", l2);
	printf("r:  %f\n", R);

	// inverse kinematics matrix
	const float ill = 1. / (2.*(l1 + l2));
	M_wheels_2_vels = QMat(3, 4);
	M_wheels_2_vels(0,0) = +1./4.;
	M_wheels_2_vels(0,1) = +1./4.;
	M_wheels_2_vels(0,2) = +1./4.;
	M_wheels_2_vels(0,3) = +1./4.;
	M_wheels_2_vels(1,0) = +1./4.;
	M_wheels_2_vels(1,1) = -1./4.;
	M_wheels_2_vels(1,2) = -1./4.;
	M_wheels_2_vels(1,3) = +1./4.;
	M_wheels_2_vels(2,0) = +ill;
	M_wheels_2_vels(2,1) = -ill;
	M_wheels_2_vels(2,2) = +ill;
	M_wheels_2_vels(2,3) = -ill;
	M_wheels_2_vels = M_wheels_2_vels.operator*(R); // R instead of 2*pi*R because we use rads/s instead of rev/s
	M_wheels_2_vels.print("M_wheels_2_vels");

	// forward kinematics matrix
	const float ll = (l1 + l2)/2.;
	M_vels_2_wheels = QMat(4,3);
	M_vels_2_wheels(0,0) = +1.;
	M_vels_2_wheels(1,0) = +1.;
	M_vels_2_wheels(2,0) = +1.;
	M_vels_2_wheels(3,0) = +1.;
	M_vels_2_wheels(0,1) = +1.;
	M_vels_2_wheels(1,1) = -1.;
	M_vels_2_wheels(2,1) = -1.;
	M_vels_2_wheels(3,1) = +1.;
	M_vels_2_wheels(0,2) = +ll; // In contrast with the paper this code is based on, the
	M_vels_2_wheels(1,2) = -ll; // third column of the matrix is inverted because we use
	M_vels_2_wheels(2,2) = +ll; // the left-hand rule for angles.
	M_vels_2_wheels(3,2) = -ll;
	M_vels_2_wheels = M_vels_2_wheels.operator*(1./(R)); // 1/R instead of 1/(2*pi*R) because we use rads/s instead of rev/s
	M_vels_2_wheels.print("M_vels_2_wheels");
	
	timer.start(Period);
	return true;
}
  // Initialization process
void EkfNode::init() {
  /**************************************************************************
   * Initialize firstRun, time, and frame names
   **************************************************************************/
  // Set first run to true for encoders. Once a message is received, this will
  // be set to false.
  firstRunEnc_ = true;
  firstRunSys_ = true;
  // Set Times
  ros::Time currTime = ros::Time::now();
  lastEncTime_ = currTime;
  lastSysTime_ = currTime;
  // Use the ROS parameter server to initilize parameters
  if(!private_nh_.getParam("base_frame", base_frame_))
    base_frame_ = "base_link";
  if(!private_nh_.getParam("odom_frame", base_frame_))
    odom_frame_ = "odom";
  if(!private_nh_.getParam("map_frame", map_frame_))
    map_frame_ = "map";

  /**************************************************************************
   * Initialize state for ekf_odom_ and ekf_map_
   **************************************************************************/
  // Create temp array to initialize state
  double state_temp[] = {0, 0, 0, 0, 0, 0};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> state (state_temp, state_temp + sizeof(state_temp) / sizeof(double));
  // Check the parameter server and initialize state
  if(!private_nh_.getParam("state", state)) {
    ROS_WARN_STREAM("No state found. Using default.");
  }
  // Check to see if the size is not equal to 6
  if (state.size() != 6) {
    ROS_WARN_STREAM("state isn't 6 elements long!");
  }
  // And initialize the Matrix
  typedef Matrix<double, 6, 1> Vector6d;
  Vector6d stateMat(state.data());
  std::cout << "state_map = " << std::endl;
  std::cout << stateMat << std::endl;
  ekf_map_.initState(stateMat);

  // Odom is always initialized at all zeros.
  stateMat << 0, 0, 0, 0, 0, 0;
  ekf_odom_.initState(stateMat);
  std::cout << "state_odom = " << std::endl;
  std::cout << stateMat << std::endl;

  /**************************************************************************
   * Initialize covariance for ekf_odom_ and ekf_map_
   **************************************************************************/
  // Create temp array to initialize covariance
  double cov_temp[] = {0.01, 0, 0, 0, 0, 0,
		       0, 0.01, 0, 0, 0, 0,
		       0, 0, 0.01, 0, 0, 0,
		       0, 0, 0, 0.01, 0, 0,
		       0, 0, 0, 0, 0.01, 0,
		       0, 0, 0, 0, 0, 0.01};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> cov (cov_temp, cov_temp + sizeof(cov_temp) / sizeof(double));
  // Check the parameter server and initialize cov
  if(!private_nh_.getParam("covariance", cov)) {
    ROS_WARN_STREAM("No covariance found. Using default.");
  }
  // Check to see if the size is not equal to 36
  if (cov.size() != 36) {
    ROS_WARN_STREAM("cov isn't 36 elements long!");
  }
  // And initialize the Matrix
  typedef Matrix<double, 6, 6, RowMajor> Matrix66;
  Matrix66 covMat(cov.data());
  std::cout << "covariance = " << std::endl;
  std::cout << covMat << std::endl;
  ekf_map_.initCov(covMat);

  // Initialize odom covariance the same as the map covariance (this isn't
  // correct. But, since it is all an estimate anyway, it should be fine.
  ekf_odom_.initCov(covMat);

  /**************************************************************************
   * Initialize Q for ekf_odom_ and ekf_map_
   **************************************************************************/
  // Create temp array to initialize Q
  double Q_temp[] = {0.01, 0, 0, 0, 0, 0,
		     0, 0.01, 0, 0, 0, 0,
		     0, 0, 0.01, 0, 0, 0,
		     0, 0, 0, 0.01, 0, 0,
		     0, 0, 0, 0, 0.01, 0,
		     0, 0, 0, 0, 0, 0.01};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> Q (Q_temp, Q_temp + sizeof(Q_temp) / sizeof(double));
  // Check the parameter server and initialize Q
  if(!private_nh_.getParam("Q", Q)) {
    ROS_WARN_STREAM("No Q found. Using default.");
  }
  // Check to see if the size is not equal to 36
  if (Q.size() != 36) {
    ROS_WARN_STREAM("Q isn't 36 elements long!");
  }
  // And initialize the Matrix
  Matrix66 QMat(Q.data());
  std::cout << "Q = " << std::endl;
  std::cout << QMat << std::endl;
  ekf_map_.initSystem(QMat);
  ekf_odom_.initSystem(QMat);

  /**************************************************************************
   * Initialize Decawave for ekf_map_ (not used in ekf_odom_)
   **************************************************************************/
  // Create temp array to initialize R for DecaWave
  double RDW_temp[] = {0.01, 0, 0, 0,
		       0, 0.01, 0, 0,
		       0, 0, 0.01, 0,
		       0, 0, 0, 0.01};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> RDW (RDW_temp, RDW_temp + sizeof(RDW_temp) / sizeof(double));
  // Check the parameter server and initialize RDW
  if(!private_nh_.getParam("DW_R", RDW)) {
    ROS_WARN_STREAM("No DW_R found. Using default.");
  }
  // Check to see if the size is not equal to 16
  if (RDW.size() != 16) {
    ROS_WARN_STREAM("DW_R isn't 16 elements long!");
  }
  // And initialize the Matrix
  typedef Matrix<double, 4, 4, RowMajor> Matrix44;
  Matrix44 RDWMat(RDW.data());
  std::cout << "RDecaWave = " << std::endl;
  std::cout << RDWMat << std::endl;

  // Create temp array to initialize beacon locations for DecaWave
  double DWBL_temp[] = {0, 0,
		       5, 0,
		       5, 15,
		       0, 15};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> DWBL (DWBL_temp, DWBL_temp + sizeof(DWBL_temp) / sizeof(double));
  // Check the parameter server and initialize DWBL
  if(!private_nh_.getParam("DW_Beacon_Loc", DWBL)) {
    ROS_WARN_STREAM("No DW_Beacon_Loc found. Using default.");
  }
  // Check to see if the size is not equal to 8
  if (DWBL.size() != 8) {
    ROS_WARN_STREAM("DW_Beacon_Loc isn't 8 elements long!");
  }
  // And initialize the Matrix
  typedef Matrix<double, 4, 2, RowMajor> Matrix42;
  Matrix42 DWBLMat(DWBL.data());
  std::cout << "DW_Beacon_Loc = " << std::endl;
  std::cout << DWBLMat << std::endl;

  MatrixXd DecaWaveBeaconLoc(4,2);
  MatrixXd DecaWaveOffset(2,1);
  double DW_offset_x;
  double DW_offset_y;
  if(!private_nh_.getParam("DW_offset_x", DW_offset_x))
    DW_offset_x = 0.0;
  if(!private_nh_.getParam("DW_offset_y", DW_offset_y))
    DW_offset_y = 0.0;
  DecaWaveOffset << DW_offset_x, DW_offset_y;
  std::cout << "DecaWaveOffset = " << std::endl;
  std::cout << DecaWaveOffset << std::endl;

  ekf_map_.initDecaWave(RDWMat, DWBLMat, DecaWaveOffset);
  // Decawave is not used in odom, so no need to initialize

  /**************************************************************************
   * Initialize Encoders for ekf_odom_ and ekf_map_
   **************************************************************************/
  // Create temp array to initialize R for DecaWave
  double REnc_temp[] = {0.01, 0,
			0, 0.01};
  // And a std::vector, which will be used to initialize an Eigen Matrix
  std::vector<double> REnc (REnc_temp, REnc_temp + sizeof(REnc_temp) / sizeof(double));
  // Check the parameter server and initialize RDW
  if(!private_nh_.getParam("Enc_R", REnc)) {
    ROS_WARN_STREAM("No Enc_R found. Using default.");
  }
  // Check to see if the size is not equal to 4
  if (REnc.size() != 4) {
    ROS_WARN_STREAM("Enc_R isn't 4 elements long!");
  }
  // And initialize the Matrix
  typedef Matrix<double, 2, 2, RowMajor> Matrix22;
  Matrix22 REncMat(REnc.data());
  std::cout << "R_Enc = " << std::endl;
  std::cout << REncMat << std::endl;

  double b, tpmRight, tpmLeft;
  if(!private_nh_.getParam("track_width", b))
    b = 1;
  if(!private_nh_.getParam("tpm_right", tpmRight))
    tpmRight = 1;
  if(!private_nh_.getParam("tpm_left", tpmLeft))
    tpmLeft = 1;
  ekf_map_.initEnc(REncMat, b, tpmRight, tpmLeft);
  ekf_odom_.initEnc(REncMat, b, tpmRight, tpmLeft);
  std::cout << "track_width = " << b << std::endl;
  std::cout << "tpm_right   = " << tpmRight << std::endl;
  std::cout << "tpm_left    = " << tpmLeft << std::endl;

  /**************************************************************************
   * Initialize IMU for ekf_odom_ and ekf_map_
   **************************************************************************/
  double RIMU;
  if(!private_nh_.getParam("R_IMU", RIMU))
    RIMU = 0.01;
  ekf_map_.initIMU(RIMU);
  ekf_odom_.initIMU(RIMU);
  std::cout << "R_IMU = " << RIMU << std::endl;

  // Publish the initialized state and exit initialization.
  publishState(currTime);
  ROS_INFO_STREAM("Finished with initialization.");
}