sil_board.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Daniel Koch, James Jackson and Gary Ellingson, BYU MAGICC Lab.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * * Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
33 #include <fstream>
34 #include <ros/ros.h>
35 
36 #include <iostream>
37 
38 namespace rosflight_sim {
39 
41  rosflight_firmware::UDPBoard()
42 { }
43 
45 {
47 }
48 
49 void SIL_Board::gazebo_setup(gazebo::physics::LinkPtr link, gazebo::physics::WorldPtr world,
50  gazebo::physics::ModelPtr model, ros::NodeHandle* nh, std::string mav_type)
51 {
52  link_ = link;
53  world_ = world;
54  model_ = model;
55  nh_ = nh;
56  mav_type_ = mav_type;
57 
58 
59  std::string bind_host = nh->param<std::string>("gazebo_host", "localhost");
60  int bind_port = nh->param<int>("gazebo_port", 14525);
61  std::string remote_host = nh->param<std::string>("ROS_host", "localhost");
62  int remote_port = nh->param<int>("ROS_port", 14520);
63 
64  set_ports(bind_host, bind_port, remote_host, remote_port);
65 
66  // Get Sensor Parameters
67  gyro_stdev_ = nh->param<double>("gyro_stdev", 0.13);
68  gyro_bias_range_ = nh->param<double>("gyro_bias_range", 0.15);
69  gyro_bias_walk_stdev_ = nh->param<double>("gyro_bias_walk_stdev", 0.001);
70 
71  acc_stdev_ = nh->param<double>("acc_stdev", 1.15);
72  acc_bias_range_ = nh->param<double>("acc_bias_range", 0.15);
73  acc_bias_walk_stdev_ = nh->param<double>("acc_bias_walk_stdev", 0.001);
74 
75  mag_stdev_ = nh->param<double>("mag_stdev", 1.15);
76  mag_bias_range_ = nh->param<double>("mag_bias_range", 0.15);
77  mag_bias_walk_stdev_ = nh->param<double>("mag_bias_walk_stdev", 0.001);
78 
79  baro_stdev_ = nh->param<double>("baro_stdev", 1.15);
80  baro_bias_range_ = nh->param<double>("baro_bias_range", 0.15);
81  baro_bias_walk_stdev_ = nh->param<double>("baro_bias_walk_stdev", 0.001);
82 
83  airspeed_stdev_ = nh_->param<double>("airspeed_stdev", 1.15);
84  airspeed_bias_range_ = nh_->param<double>("airspeed_bias_range", 0.15);
85  airspeed_bias_walk_stdev_ = nh_->param<double>("airspeed_bias_walk_stdev", 0.001);
86 
87  sonar_stdev_ = nh_->param<double>("sonar_stdev", 1.15);
88  sonar_min_range_ = nh_->param<double>("sonar_min_range", 0.25);
89  sonar_max_range_ = nh_->param<double>("sonar_max_range", 8.0);
90 
91  imu_update_rate_ = nh_->param<double>("imu_update_rate", 1000.0);
92  imu_update_period_us_ = (uint64_t)(1e6/imu_update_rate_);
93 
94  // Calculate Magnetic Field Vector (for mag simulation)
95  double inclination = nh_->param<double>("inclination", 1.14316156541);
96  double declination = nh_->param<double>("declination", 0.198584539676);
98  GZ_COMPAT_SET_X(inertial_magnetic_field_, cos(-inclination)*cos(-declination));
99  GZ_COMPAT_SET_Y(inertial_magnetic_field_, cos(-inclination)*sin(-declination));
100 
101  // Get the desired altitude at the ground (for baro simulation)
102  ground_altitude_ = nh->param<double>("ground_altitude", 1387.0);
103 
104  // Configure Noise
105  random_generator_= std::default_random_engine(std::chrono::system_clock::now().time_since_epoch().count());
106  normal_distribution_ = std::normal_distribution<double>(0.0, 1.0);
107  uniform_distribution_ = std::uniform_real_distribution<double>(-1.0, 1.0);
108 
110 
111  // Initialize the Sensor Biases
123 
129 }
130 
131 void SIL_Board::board_reset(bool bootloader)
132 {
133 }
134 
135 // clock
136 
138 {
139  return (uint32_t)((GZ_COMPAT_GET_SIM_TIME(world_).Double() - boot_time_)*1e3);
140 }
141 
143 {
144  return (uint64_t)((GZ_COMPAT_GET_SIM_TIME(world_).Double() - boot_time_)*1e6);
145 }
146 
147 void SIL_Board::clock_delay(uint32_t milliseconds)
148 {
149 }
150 
151 // sensors
155 {
156  // Initialize the Biases
163 
164  // Gazebo coordinates is NWU and Earth's magnetic field is defined in NED, hence the negative signs
165  double inclination_ = 1.14316156541;
166  double declination_ = 0.198584539676;
168  GZ_COMPAT_SET_X(inertial_magnetic_field_, cos(-inclination_)*cos(-declination_));
169  GZ_COMPAT_SET_Y(inertial_magnetic_field_, cos(-inclination_)*sin(-declination_));
170 }
171 
173 {
174  return 0;
175 }
176 
178 {
179  uint64_t now_us = clock_micros();
180  if (now_us >= next_imu_update_time_us_)
181  {
183  return true;
184  }
185  else
186  {
187  return false;
188  }
189 }
190 
191 bool SIL_Board::imu_read(float accel[3], float* temperature, float gyro[3], uint64_t* time_us)
192 {
195  GazeboVector y_acc;
196 
197  // this is James' egregious hack to overcome wild imu while sitting on the ground
198  if (GZ_COMPAT_GET_LENGTH(current_vel) < 0.05)
199  y_acc = q_I_NWU.RotateVectorReverse(-gravity_);
200  else
201  y_acc = q_I_NWU.RotateVectorReverse(GZ_COMPAT_GET_WORLD_LINEAR_ACCEL(link_) - gravity_);
202 
203  // Apply normal noise (only if armed, because most of the noise comes from motors
204  if (motors_spinning())
205  {
209  }
210 
211  // Perform Random Walk for biases
215 
216  // Add constant Bias to measurement
220 
221  // Convert to NED for output
222  accel[0] = GZ_COMPAT_GET_X(y_acc);
223  accel[1] = -GZ_COMPAT_GET_Y(y_acc);
224  accel[2] = -GZ_COMPAT_GET_Z(y_acc);
225 
227 
228  // Normal Noise from motors
229  if (motors_spinning())
230  {
234  }
235 
236  // Random Walk for bias
240 
241  // Apply Constant Bias
245 
246  // Convert to NED for output
247  gyro[0] = GZ_COMPAT_GET_X(y_gyro);
248  gyro[1] = -GZ_COMPAT_GET_Y(y_gyro);
249  gyro[2] = -GZ_COMPAT_GET_Z(y_gyro);
250 
251  (*temperature) = 27.0;
252  (*time_us) = clock_micros();
253  return true;
254 }
255 
257 {
258  ROS_ERROR("[gazebo_rosflight_sil] imu not responding");
259 }
260 
261 void SIL_Board::mag_read(float mag[3])
262 {
264  GazeboVector noise;
268 
269  // Random Walk for bias
273 
274  // combine parts to create a measurement
275  GazeboVector y_mag = GZ_COMPAT_GET_ROT(I_to_B).RotateVectorReverse(inertial_magnetic_field_) + mag_bias_ + noise;
276 
277  // Convert measurement to NED
278  mag[0] = GZ_COMPAT_GET_X(y_mag);
279  mag[1] = -GZ_COMPAT_GET_Y(y_mag);
280  mag[2] = -GZ_COMPAT_GET_Z(y_mag);
281 }
282 
284 {
285  return true;
286 }
287 
289 {
290  return true;
291 }
292 
293 void SIL_Board::baro_read(float *pressure, float *temperature)
294 {
295  // pull z measurement out of Gazebo
296  GazeboPose current_state_NWU = GZ_COMPAT_GET_WORLD_POSE(link_);
297 
298  // Invert measurement model for pressure and temperature
299  double alt = GZ_COMPAT_GET_Z(GZ_COMPAT_GET_POS(current_state_NWU)) + ground_altitude_;
300 
301  // Convert to the true pressure reading
302  double y_baro = 101325.0f*(float)pow((1-2.25694e-5 * alt), 5.2553);
303 
304  // Add noise
306 
307  // Perform random walk
309 
310  // Add random walk
311  y_baro += baro_bias_;
312 
313  (*pressure) = (float)y_baro;
314  (*temperature) = 27.0f;
315 }
316 
318 {
319  if(mav_type_ == "fixedwing")
320  return true;
321  else
322  return false;
323 }
324 
325 void SIL_Board::diff_pressure_read(float *diff_pressure, float *temperature)
326 {
327  static double rho_ = 1.225;
328  // Calculate Airspeed
330 
331  double Va = GZ_COMPAT_GET_LENGTH(vel);
332 
333  // Invert Airpseed to get sensor measurement
334  double y_as = rho_*Va*Va/2.0; // Page 130 in the UAV Book
335 
336  // Add noise
339  y_as += airspeed_bias_;
340 
341  *diff_pressure = y_as;
342  *temperature = 27.0;
343 }
344 
346 {
347  return true;
348 }
349 
351 {
352  GazeboPose current_state_NWU = GZ_COMPAT_GET_WORLD_POSE(link_);
353  double alt = GZ_COMPAT_GET_Z(GZ_COMPAT_GET_POS(current_state_NWU));
354 
355  if (alt < sonar_min_range_)
356  {
357  return sonar_min_range_;
358  }
359  else if (alt > sonar_max_range_)
360  {
361  return sonar_max_range_;
362  }
363  else
365 }
366 
367 // PWM
368 void SIL_Board::pwm_init(uint32_t refresh_rate, uint16_t idle_pwm)
369 {
370  rc_received_ = false;
371  latestRC_.values[0] = 1500; // x
372  latestRC_.values[1] = 1500; // y
373  latestRC_.values[3] = 1500; // z
374  latestRC_.values[2] = 1000; // F
375  latestRC_.values[4] = 1000; // attitude override
376  latestRC_.values[5] = 1000; // arm
377 
378  for (size_t i = 0; i < 14; i++)
379  pwm_outputs_[i] = 1000;
380 
381  rc_sub_ = nh_->subscribe("RC", 1, &SIL_Board::RCCallback, this);
382 }
383 
384 float SIL_Board::rc_read(uint8_t channel)
385 {
386  if(rc_sub_.getNumPublishers() > 0)
387  {
388  return static_cast<float>(latestRC_.values[channel]-1000)/1000.0;
389  }
390 
391  //no publishers, set throttle low and center everything else
392  if(channel == 2)
393  return 0.0;
394 
395  return 0.5;
396 }
397 
398 void SIL_Board::pwm_write(uint8_t channel, float value)
399 {
400  pwm_outputs_[channel] = 1000+(uint16_t)(1000*value);
401 }
403 {
404  for(int i=0;i<14;i++)
405  pwm_write(i,0);
406 }
407 
409 {
410  return !rc_received_;
411 }
412 
414 
415 // non-volatile memory
417 
418 bool SIL_Board::memory_read(void * dest, size_t len)
419 {
420  std::string directory = "rosflight_memory" + nh_->getNamespace();
421  std::ifstream memory_file;
422  memory_file.open(directory + "/mem.bin", std::ios::binary);
423 
424  if(!memory_file.is_open())
425  {
426  ROS_ERROR("Unable to load rosflight memory file %s/mem.bin", directory.c_str());
427  return false;
428  }
429 
430  memory_file.read((char*) dest, len);
431  memory_file.close();
432  return true;
433 }
434 
435 bool SIL_Board::memory_write(const void * src, size_t len)
436 {
437  std::string directory = "rosflight_memory" + nh_->getNamespace();
438  std::string mkdir_command = "mkdir -p " + directory;
439  const int dir_err = system(mkdir_command.c_str());
440 
441  if (dir_err == -1)
442  {
443  ROS_ERROR("Unable to write rosflight memory file %s/mem.bin", directory.c_str());
444  return false;
445  }
446 
447  std::ofstream memory_file;
448  memory_file.open(directory + "/mem.bin", std::ios::binary);
449  memory_file.write((char*) src, len);
450  memory_file.close();
451  return true;
452 }
453 
455 {
456  if(pwm_outputs_[2] > 1100)
457  return true;
458  else
459  return false;
460 }
461 
462 // LED
463 
464 void SIL_Board::led0_on(void) { }
465 void SIL_Board::led0_off(void) { }
467 
468 void SIL_Board::led1_on(void) { }
469 void SIL_Board::led1_off(void) { }
471 
473 {
474  return false;
475 }
476 
478 {
479  rosflight_firmware::BackupData blank_data = {0};
480  return blank_data;
481 }
482 
483 void SIL_Board::RCCallback(const rosflight_msgs::RCRaw& msg)
484 {
485  rc_received_ = true;
486  latestRC_ = msg;
487 }
488 
489 } // namespace rosflight_sim
#define GZ_COMPAT_SET_X(VECTOR, VALUE)
Definition: gz_compat.h:77
#define GZ_COMPAT_GET_GRAVITY(WORLD_PTR)
Definition: gz_compat.h:94
#define GZ_COMPAT_SET_Z(VECTOR, VALUE)
Definition: gz_compat.h:79
gazebo::common::Time last_time_
Definition: sil_board.h:122
gazebo::physics::WorldPtr world_
Definition: sil_board.h:99
void baro_read(float *pressure, float *temperature) override
Definition: sil_board.cpp:293
#define GZ_COMPAT_GET_Z(VECTOR)
Definition: gz_compat.h:75
std::uniform_real_distribution< double > uniform_distribution_
Definition: sil_board.h:94
void clock_delay(uint32_t milliseconds) override
Definition: sil_board.cpp:147
bool memory_write(const void *src, size_t len) override
Definition: sil_board.cpp:435
void memory_init(void) override
Definition: sil_board.cpp:416
float cos(float x)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool diff_pressure_present(void) override
Definition: sil_board.cpp:317
gazebo::math::Vector3 GazeboVector
Definition: gz_compat.h:69
bool sonar_present(void) override
Definition: sil_board.cpp:345
GazeboVector prev_vel_3_
Definition: sil_board.h:121
void led1_off(void) override
Definition: sil_board.cpp:469
float sin(float x)
void mag_read(float mag[3]) override
Definition: sil_board.cpp:261
bool rc_lost(void) override
Definition: sil_board.cpp:408
#define GZ_COMPAT_GET_X(VECTOR)
Definition: gz_compat.h:73
void sensors_init() override
Definition: sil_board.cpp:154
float alt(float press)
int bind_port
GazeboVector gyro_bias_
Definition: sil_board.h:86
rosflight_firmware::BackupData get_backup_data(void) override
Definition: sil_board.cpp:477
#define GZ_COMPAT_GET_RELATIVE_ANGULAR_VEL(LINK_PTR)
Definition: gz_compat.h:86
uint64_t next_imu_update_time_us_
Definition: sil_board.h:113
ros::Subscriber rc_sub_
Definition: sil_board.h:104
void gazebo_setup(gazebo::physics::LinkPtr link, gazebo::physics::WorldPtr world, gazebo::physics::ModelPtr model, ros::NodeHandle *nh, std::string mav_type)
Definition: sil_board.cpp:49
float sonar_read(void) override
Definition: sil_board.cpp:350
void led1_on(void) override
Definition: sil_board.cpp:468
GazeboVector prev_vel_2_
Definition: sil_board.h:120
void diff_pressure_read(float *diff_pressure, float *temperature) override
Definition: sil_board.cpp:325
void pwm_init(uint32_t refresh_rate, uint16_t idle_pwm) override
Definition: sil_board.cpp:368
void led0_on(void) override
Definition: sil_board.cpp:464
std::normal_distribution< double > normal_distribution_
Definition: sil_board.h:93
uint32_t clock_millis() override
Definition: sil_board.cpp:137
bool imu_read(float accel[3], float *temperature, float gyro[3], uint64_t *time_us) override
Definition: sil_board.cpp:191
rosflight_msgs::RCRaw latestRC_
Definition: sil_board.h:105
#define GZ_COMPAT_GET_WORLD_POSE(LINK_PTR)
Definition: gz_compat.h:88
GazeboVector acc_bias_
Definition: sil_board.h:87
void board_reset(bool bootloader) override
Definition: sil_board.cpp:131
gazebo::math::Pose GazeboPose
Definition: gz_compat.h:70
bool param(const std::string &param_name, T &param_val, const T &default_val) const
gazebo::physics::LinkPtr link_
Definition: sil_board.h:101
void imu_not_responding_error() override
Definition: sil_board.cpp:256
bool new_imu_data() override
Definition: sil_board.cpp:177
double airspeed_bias_walk_stdev_
Definition: sil_board.h:78
uint32_t getNumPublishers() const
const std::string & getNamespace() const
#define GZ_COMPAT_GET_ROT(POSE)
Definition: gz_compat.h:82
void led1_toggle(void) override
Definition: sil_board.cpp:470
void RCCallback(const rosflight_msgs::RCRaw &msg)
Definition: sil_board.cpp:483
int i
#define GZ_COMPAT_GET_WORLD_LINEAR_ACCEL(LINK_PTR)
Definition: gz_compat.h:91
void pwm_disable(void) override
Definition: sil_board.cpp:402
uint64_t clock_micros() override
Definition: sil_board.cpp:142
GazeboVector prev_vel_1_
Definition: sil_board.h:119
GazeboVector mag_bias_
Definition: sil_board.h:88
void set_ports(std::string bind_host, uint16_t bind_port, std::string remote_host, uint16_t remote_port)
uint16_t num_sensor_errors(void) override
Definition: sil_board.cpp:172
GazeboVector gravity_
Definition: sil_board.h:96
#define GZ_COMPAT_GET_LENGTH(VECTOR)
Definition: gz_compat.h:92
bool has_backup_data(void) override
Definition: sil_board.cpp:472
bool baro_present(void) override
Definition: sil_board.cpp:288
float rc_read(uint8_t channel) override
Definition: sil_board.cpp:384
GazeboVector inertial_magnetic_field_
Definition: sil_board.h:58
#define GZ_COMPAT_GET_POS(POSE)
Definition: gz_compat.h:81
double time_since_epoch()
bool mag_present(void) override
Definition: sil_board.cpp:283
std::default_random_engine random_generator_
Definition: sil_board.h:92
void init_board(void) override
Definition: sil_board.cpp:44
gazebo::physics::ModelPtr model_
Definition: sil_board.h:100
uint64_t imu_update_period_us_
Definition: sil_board.h:114
void rc_init(rc_type_t rc_type) override
Definition: sil_board.cpp:413
ros::NodeHandle * nh_
Definition: sil_board.h:103
void led0_off(void) override
Definition: sil_board.cpp:465
void led0_toggle(void) override
Definition: sil_board.cpp:466
#define GZ_COMPAT_GET_SIM_TIME(WORLD_PTR)
Definition: gz_compat.h:84
#define ROS_ERROR(...)
void pwm_write(uint8_t channel, float value) override
Definition: sil_board.cpp:398
#define GZ_COMPAT_GET_Y(VECTOR)
Definition: gz_compat.h:74
#define GZ_COMPAT_GET_RELATIVE_LINEAR_VEL(LINK_PTR)
Definition: gz_compat.h:85
bool memory_read(void *dest, size_t len) override
Definition: sil_board.cpp:418
#define GZ_COMPAT_SET_Y(VECTOR, VALUE)
Definition: gz_compat.h:78
gazebo::math::Quaternion GazeboQuaternion
Definition: gz_compat.h:71


rosflight_sim
Author(s): James Jackson, Gary Ellingson, Daniel Koch
autogenerated on Wed Jul 3 2019 20:00:29