ardupilot如何读取传感器数据
来源:互联网 发布:会计证模拟考试软件 编辑:程序博客网 时间:2024/06/05 07:42
错误挺多,还未改正,请见谅。
1.setup();loop();
由HAL_PX4_Class.cpp可知,g_callbacks->setup();运行一次,g_callbacks->loop();在循环里
static int main_loop(int argc, char **argv){ hal.uartA->begin(115200); hal.uartB->begin(38400); hal.uartC->begin(57600); hal.uartD->begin(57600); hal.uartE->begin(57600); hal.scheduler->init(); /* run setup() at low priority to ensure CLI doesn't hang the system, and to allow initial sensor read loops to run */ hal_px4_set_priority(APM_STARTUP_PRIORITY); schedulerInstance.hal_initialized(); g_callbacks->setup(); hal.scheduler->system_initialized(); perf_counter_t perf_loop = perf_alloc(PC_ELAPSED, "APM_loop"); perf_counter_t perf_overrun = perf_alloc(PC_COUNT, "APM_overrun"); struct hrt_call loop_overtime_call; thread_running = true; /* switch to high priority for main loop */ hal_px4_set_priority(APM_MAIN_PRIORITY); while (!_px4_thread_should_exit) { perf_begin(perf_loop); /* this ensures a tight loop waiting on a lower priority driver will eventually give up some time for the driver to run. It will only ever be called if a loop() call runs for more than 0.1 second */ hrt_call_after(&loop_overtime_call, 100000, (hrt_callout)loop_overtime, nullptr); g_callbacks->loop(); if (px4_ran_overtime) { /* we ran over 1s in loop(), and our priority was lowered to let a driver run. Set it back to high priority now. */ hal_px4_set_priority(APM_MAIN_PRIORITY); perf_count(perf_overrun); px4_ran_overtime = false; } perf_end(perf_loop); /* give up 250 microseconds of time, to ensure drivers get a chance to run. This relies on the accurate semaphore wait using hrt in semaphore.cpp */ hal.scheduler->delay_microseconds(250); } thread_running = false; return 0;}
对应到ArduCoptor.cpp就是Copter::setup()运行一次(也就是初始化),Copter::loop()循环运行(程序主体)。
2.init_ardupilot()注册传感器
请注意初始化里的init_ardupilot();
void Copter::setup() { cliSerial = hal.console; // Load the default values of variables listed in var_info[]s AP_Param::setup_sketch_defaults(); // setup storage layout for copter StorageManager::set_layout_copter(); init_ardupilot(); // initialise the main loop scheduler scheduler.init(&scheduler_tasks[0], ARRAY_SIZE(scheduler_tasks)); // setup initial performance counters perf_info_reset(); fast_loopTimer = AP_HAL::micros();}
请注意BoardConfig.init();
void Copter::init_ardupilot(){ if (!hal.gpio->usb_connected()) { // USB is not connected, this means UART0 may be a Xbee, with // its darned bricking problem. We can't write to it for at // least one second after powering up. Simplest solution for // now is to delay for 1 second. Something more elegant may be // added later delay(1000); } // initialise serial port serial_manager.init_console(); // init vehicle capabilties init_capabilities(); cliSerial->printf("\n\nInit " FIRMWARE_STRING "\n\nFree RAM: %u\n", (unsigned)hal.util->available_memory()); // // Report firmware version code expect on console (check of actual EEPROM format version is done in load_parameters function) // report_version(); // load parameters from EEPROM load_parameters(); // initialise stats module g2.stats.init(); GCS_MAVLINK::set_dataflash(&DataFlash); // identify ourselves correctly with the ground station mavlink_system.sysid = g.sysid_this_mav; // initialise serial ports serial_manager.init(); // setup first port early to allow BoardConfig to report errors gcs[0].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, 0); // Register mavlink_delay_cb, which will run anytime you have // more than 5ms remaining in your call to hal.scheduler->delay hal.scheduler->register_delay_callback(mavlink_delay_cb_static, 5); BoardConfig.init(); // init cargo gripper#if GRIPPER_ENABLED == ENABLED g2.gripper.init();#endif // initialise notify system // disable external leds if epm is enabled because of pin conflict on the APM notify.init(true); // initialise battery monitor battery.init(); // Init RSSI rssi.init(); barometer.init(); // we start by assuming USB connected, as we initialed the serial // port with SERIAL0_BAUD. check_usb_mux() fixes this if need be. ap.usb_connected = true; check_usb_mux(); // setup telem slots with serial ports for (uint8_t i = 1; i < MAVLINK_COMM_NUM_BUFFERS; i++) { gcs[i].setup_uart(serial_manager, AP_SerialManager::SerialProtocol_MAVLink, i); }#if FRSKY_TELEM_ENABLED == ENABLED // setup frsky, and pass a number of parameters to the library frsky_telemetry.init(serial_manager, FIRMWARE_STRING " " FRAME_CONFIG_STRING, FRAME_MAV_TYPE, &g.fs_batt_voltage, &g.fs_batt_mah, &ap.value);#endif#if LOGGING_ENABLED == ENABLED log_init();#endif // update motor interlock state update_using_interlock();#if FRAME_CONFIG == HELI_FRAME // trad heli specific initialisation heli_init();#endif init_rc_in(); // sets up rc channels from radio init_rc_out(); // sets up motors and output to escs // initialise which outputs Servo and Relay events can use ServoRelayEvents.set_channel_mask(~motors.get_motor_mask()); relay.init(); /* * setup the 'main loop is dead' check. Note that this relies on * the RC library being initialised. */ hal.scheduler->register_timer_failsafe(failsafe_check_static, 1000); // give AHRS the rnage beacon sensor ahrs.set_beacon(&g2.beacon); // Do GPS init gps.init(&DataFlash, serial_manager); if(g.compass_enabled) init_compass();#if OPTFLOW == ENABLED // make optflow available to AHRS ahrs.set_optflow(&optflow);#endif // init Location class Location_Class::set_ahrs(&ahrs);#if AP_TERRAIN_AVAILABLE && AC_TERRAIN Location_Class::set_terrain(&terrain); wp_nav.set_terrain(&terrain);#endif wp_nav.set_avoidance(&avoid); attitude_control.parameter_sanity_check(); pos_control.set_dt(MAIN_LOOP_SECONDS); // init the optical flow sensor init_optflow();#if MOUNT == ENABLED // initialise camera mount camera_mount.init(&DataFlash, serial_manager);#endif#if PRECISION_LANDING == ENABLED // initialise precision landing init_precland();#endif#ifdef USERHOOK_INIT USERHOOK_INIT#endif#if CLI_ENABLED == ENABLED if (g.cli_enabled) { const char *msg = "\nPress ENTER 3 times to start interactive setup\n"; cliSerial->println(msg); if (gcs[1].initialised && (gcs[1].get_uart() != nullptr)) { gcs[1].get_uart()->println(msg); } if (num_gcs > 2 && gcs[2].initialised && (gcs[2].get_uart() != nullptr)) { gcs[2].get_uart()->println(msg); } }#endif // CLI_ENABLED#if HIL_MODE != HIL_MODE_DISABLED while (barometer.get_last_update() == 0) { // the barometer begins updating when we get the first // HIL_STATE message gcs_send_text(MAV_SEVERITY_WARNING, "Waiting for first HIL_STATE message"); delay(1000); } // set INS to HIL mode ins.set_hil_mode();#endif // read Baro pressure at ground //----------------------------- init_barometer(true); // initialise rangefinder init_rangefinder(); // init proximity sensor init_proximity(); // init beacons used for non-gps position estimation init_beacon(); // initialise AP_RPM library rpm_sensor.init(); // initialise mission library mission.init(); // initialise the flight mode and aux switch // --------------------------- reset_control_switch(); init_aux_switches(); startup_INS_ground(); // set landed flags set_land_complete(true); set_land_complete_maybe(true); // we don't want writes to the serial port to cause us to pause // mid-flight, so set the serial ports non-blocking once we are // ready to fly serial_manager.set_blocking_writes_all(false); // enable CPU failsafe failsafe_enable(); ins.set_raw_logging(should_log(MASK_LOG_IMU_RAW)); ins.set_dataflash(&DataFlash); cliSerial->print("\nReady to FLY "); // flag that initialisation has completed ap.initialised = true;}
请注意px4_setup();
void AP_BoardConfig::init(){#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 || CONFIG_HAL_BOARD == HAL_BOARD_VRBRAIN px4_setup();#endif#if HAL_HAVE_IMU_HEATER // let the HAL know the target temperature. We pass a pointer as // we want the user to be able to change the parameter without // rebooting hal.util->set_imu_target_temp((int8_t *)&_imu_target_temperature);#endif}
请注意px4_setup_drivers();
/* setup px4 peripherals and drivers */void AP_BoardConfig::px4_setup(){ px4_setup_peripherals(); px4_setup_pwm(); px4_setup_safety(); px4_setup_uart(); px4_setup_sbus(); px4_setup_drivers(); px4_setup_canbus();}
请注意
px4_start_driver(fmu_main, “fmu”, “sensor_reset 20”)
px4_start_common_sensors();
px4_start_fmuv2_sensors();
void AP_BoardConfig::px4_setup_drivers(void){#if defined(CONFIG_ARCH_BOARD_PX4FMU_V4) /* this works around an issue with some FMUv4 hardware (eg. copies of the Pixracer) which have incorrect components leading to sensor brownout on boot */ if (px4_start_driver(fmu_main, "fmu", "sensor_reset 20")) { printf("FMUv4 sensor reset complete\n"); }#endif // run board auto-detection px4_autodetect(); if (px4.board_type == PX4_BOARD_PH2SLIM || px4.board_type == PX4_BOARD_PIXHAWK2) { _imu_target_temperature.set_default(60); } if (px4.board_type == PX4_BOARD_PX4V1 || px4.board_type == PX4_BOARD_PHMINI || px4.board_type == PX4_BOARD_PH2SLIM || px4.board_type == PX4_BOARD_PIXRACER || px4.board_type == PX4_BOARD_PIXHAWK || px4.board_type == PX4_BOARD_PIXHAWK2) { // use in-tree drivers printf("Using in-tree drivers\n"); px4_configured_board = (enum px4_board_type)px4.board_type.get(); return; }#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 px4_start_common_sensors(); switch ((px4_board_type)px4.board_type.get()) { case PX4_BOARD_AUTO: default: px4_start_fmuv1_sensors(); px4_start_fmuv2_sensors(); break; }#elif CONFIG_HAL_BOARD == HAL_BOARD_VRBRAIN vrx_start_common_sensors(); switch ((px4_board_type)px4.board_type.get()) { case VRX_BOARD_BRAIN51: vrx_start_brain51_sensors(); break; case VRX_BOARD_BRAIN52: vrx_start_brain52_sensors(); break; case VRX_BOARD_UBRAIN51: vrx_start_ubrain51_sensors(); break; case VRX_BOARD_UBRAIN52: vrx_start_ubrain52_sensors(); break; case VRX_BOARD_CORE10: vrx_start_core10_sensors(); break; case VRX_BOARD_BRAIN54: vrx_start_brain54_sensors(); break; default: break; }#endif // HAL_BOARD_PX4 px4_configured_board = (enum px4_board_type)px4.board_type.get(); // delay for 1 second to give time for drivers to initialise hal.scheduler->delay(1000);}
请注意px4_start_driver(hmc5883_main, “hmc5883”, “-C -T -I -R 4 start”)等px4_start_driver()函数
void AP_BoardConfig::px4_start_fmuv2_sensors(void){#if defined(CONFIG_ARCH_BOARD_PX4FMU_V2) bool have_FMUV3 = false; printf("Starting FMUv2 sensors\n"); if (px4_start_driver(hmc5883_main, "hmc5883", "-C -T -I -R 4 start")) { printf("Have internal hmc5883\n"); } else { printf("No internal hmc5883\n"); } // external MPU6000 is rotated YAW_180 from standard if (px4_start_driver(mpu6000_main, "mpu6000", "-X -R 4 start")) { printf("Found MPU6000 external\n"); have_FMUV3 = true; } else { if (px4_start_driver(mpu9250_main, "mpu9250", "-X -R 4 start")) { printf("Found MPU9250 external\n"); have_FMUV3 = true; } else { printf("No MPU6000 or MPU9250 external\n"); } } if (have_FMUV3) { // external L3GD20 is rotated YAW_180 from standard if (px4_start_driver(l3gd20_main, "l3gd20", "-X -R 4 start")) { printf("l3gd20 external started OK\n"); } else { px4_sensor_error("No l3gd20"); } // external LSM303D is rotated YAW_270 from standard if (px4_start_driver(lsm303d_main, "lsm303d", "-a 16 -X -R 6 start")) { printf("lsm303d external started OK\n"); } else { px4_sensor_error("No lsm303d"); } // internal MPU6000 is rotated ROLL_180_YAW_270 from standard if (px4_start_driver(mpu6000_main, "mpu6000", "-R 14 start")) { printf("Found MPU6000 internal\n"); } else { if (px4_start_driver(mpu9250_main, "mpu9250", "-R 14 start")) { printf("Found MPU9250 internal\n"); } else { px4_sensor_error("No MPU6000 or MPU9250"); } } if (px4_start_driver(hmc5883_main, "hmc5883", "-C -T -S -R 8 start")) { printf("Found SPI hmc5883\n"); } } else { // not FMUV3 (ie. not a pixhawk2) if (px4_start_driver(mpu6000_main, "mpu6000", "start")) { printf("Found MPU6000\n"); } else { if (px4_start_driver(mpu9250_main, "mpu9250", "start")) { printf("Found MPU9250\n"); } else { printf("No MPU6000 or MPU9250\n"); } } if (px4_start_driver(l3gd20_main, "l3gd20", "start")) { printf("l3gd20 started OK\n"); } else { px4_sensor_error("no l3gd20 found"); } if (px4_start_driver(lsm303d_main, "lsm303d", "-a 16 start")) { printf("lsm303d started OK\n"); } else { px4_sensor_error("no lsm303d found"); } } if (have_FMUV3) { // on Pixhawk2 default IMU temperature to 60 _imu_target_temperature.set_default(60); } printf("FMUv2 sensors started\n");#endif // CONFIG_ARCH_BOARD_PX4FMU_V2}
px4_start_driver()函数原型
/* start one px4 driver */bool AP_BoardConfig::px4_start_driver(main_fn_t main_function, const char *name, const char *arguments){ char *s = strdup(arguments); char *args[10]; uint8_t nargs = 0; char *saveptr = nullptr; // parse into separate arguments for (char *tok=strtok_r(s, " ", &saveptr); tok; tok=strtok_r(nullptr, " ", &saveptr)) { args[nargs++] = tok; if (nargs == ARRAY_SIZE(args)-1) { break; } } args[nargs++] = nullptr; printf("Starting driver %s %s\n", name, arguments); pid_t pid; if (task_spawn(&pid, name, main_function, nullptr, nullptr, args, nullptr) != 0) { free(s); printf("Failed to spawn %s\n", name); return false; } // wait for task to exit and gather status int status = -1; if (waitpid(pid, &status, 0) != pid) { printf("waitpid failed for %s\n", name); free(s); return false; } free(s); return (status >> 8) == 0;}
其中task_spawn(&pid, name, main_function, nullptr, nullptr, args, nullptr) != 0)创建了新的线程
比如px4_start_driver(hmc5883_main, “hmc5883”, “-C -T -I -R 4 start”)就映射到了px4的hmc5883驱动
inthmc5883_main(int argc, char *argv[]){ int ch; enum HMC5883_BUS busid = HMC5883_BUS_ALL; enum Rotation rotation = ROTATION_NONE; bool calibrate = false; bool temp_compensation = false; while ((ch = getopt(argc, argv, "XISR:CT")) != EOF) { switch (ch) { case 'R': rotation = (enum Rotation)atoi(optarg); break;#if (PX4_I2C_BUS_ONBOARD || PX4_SPIDEV_HMC) case 'I': busid = HMC5883_BUS_I2C_INTERNAL; break;#endif case 'X': busid = HMC5883_BUS_I2C_EXTERNAL; break; case 'S': busid = HMC5883_BUS_SPI; break; case 'C': calibrate = true; break; case 'T': temp_compensation = true; break; default: hmc5883::usage(); exit(0); } } const char *verb = argv[optind]; /* * Start/load the driver. */ if (!strcmp(verb, "start")) { hmc5883::start(busid, rotation); if (calibrate && hmc5883::calibrate(busid) != 0) { errx(1, "calibration failed"); } if (temp_compensation) { // we consider failing to setup temperature // compensation as non-fatal hmc5883::temp_enable(busid, true); } exit(0); } /* * Test the driver/device. */ if (!strcmp(verb, "test")) { hmc5883::test(busid); } /* * Reset the driver. */ if (!strcmp(verb, "reset")) { hmc5883::reset(busid); } /* * enable/disable temperature compensation */ if (!strcmp(verb, "tempoff")) { hmc5883::temp_enable(busid, false); } if (!strcmp(verb, "tempon")) { hmc5883::temp_enable(busid, true); } /* * Print driver information. */ if (!strcmp(verb, "info") || !strcmp(verb, "status")) { hmc5883::info(busid); } /* * Autocalibrate the scaling */ if (!strcmp(verb, "calibrate")) { if (hmc5883::calibrate(busid) == 0) { errx(0, "calibration successful"); } else { errx(1, "calibration failed"); } } errx(1, "unrecognized command, try 'start', 'test', 'reset' 'calibrate', 'tempoff', 'tempon' or 'info'");}
请注意hmc5883::start(busid, rotation);
/** * Start the driver. * * This function call only returns once the driver * is either successfully up and running or failed to start. */voidstart(enum HMC5883_BUS busid, enum Rotation rotation){ bool started = false; for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) { if (busid == HMC5883_BUS_ALL && bus_options[i].dev != NULL) { // this device is already started continue; } if (busid != HMC5883_BUS_ALL && bus_options[i].busid != busid) { // not the one that is asked for continue; } started |= start_bus(bus_options[i], rotation); } if (!started) { exit(1); }}
请注意started |= start_bus(bus_options[i], rotation);
/** * start driver for a specific bus option */boolstart_bus(struct hmc5883_bus_option &bus, enum Rotation rotation){ if (bus.dev != nullptr) { errx(1, "bus option already started"); } device::Device *interface = bus.interface_constructor(bus.busnum); if (interface->init() != OK) { delete interface; warnx("no device on bus %u", (unsigned)bus.busid); return false; } bus.dev = new HMC5883(interface, bus.devpath, rotation); if (bus.dev != nullptr && OK != bus.dev->init()) { delete bus.dev; bus.dev = NULL; return false; } int fd = open(bus.devpath, O_RDONLY); if (fd < 0) { return false; } if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) { close(fd); errx(1, "Failed to setup poll rate"); } close(fd); return true;}
请注意bus.dev->init()
intHMC5883::init(){ int ret = ERROR; ret = CDev::init(); if (ret != OK) { DEVICE_DEBUG("CDev init failed"); goto out; } /* allocate basic report buffers */ _reports = new ringbuffer::RingBuffer(2, sizeof(mag_report)); if (_reports == nullptr) { goto out; } /* reset the device configuration */ reset(); _class_instance = register_class_devname(MAG_BASE_DEVICE_PATH); ret = OK; /* sensor is ok, but not calibrated */ _sensor_ok = true;out: return ret;}
请注意_class_instance = register_class_devname(MAG_BASE_DEVICE_PATH);注册了设备路径。
返回bool start_bus(struct hmc5883_bus_option &bus, enum Rotation rotation)
int fd = open(bus.devpath, O_RDONLY);
打开设备。此时就可以直接用read、ioctl等操作了。
此处有疑问了,是ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)读取的数据,还是ardupilot里面::read()读取数据
3.读取传感器数据
请注意fast_loop();
void Copter::loop(){ // wait for an INS sample ins.wait_for_sample(); uint32_t timer = micros(); // check loop time perf_info_check_loop_time(timer - fast_loopTimer); // used by PI Loops G_Dt = (float)(timer - fast_loopTimer) / 1000000.0f; fast_loopTimer = timer; // for mainloop failure monitoring mainLoop_count++; // Execute the fast loop // --------------------- fast_loop(); // tell the scheduler one tick has passed scheduler.tick(); // run all the tasks that are due to run. Note that we only // have to call this once per loop, as the tasks are scheduled // in multiples of the main loop tick. So if they don't run on // the first call to the scheduler they won't run on a later // call until scheduler.tick() is called again uint32_t time_available = (timer + MAIN_LOOP_MICROS) - micros(); scheduler.run(time_available > MAIN_LOOP_MICROS ? 0u : time_available);}
请注意read_AHRS();
// Main loop - 400hzvoid Copter::fast_loop(){ // IMU DCM Algorithm // -------------------- read_AHRS(); // run low level rate controllers that only require IMU data attitude_control.rate_controller_run();#if FRAME_CONFIG == HELI_FRAME update_heli_control_dynamics();#endif //HELI_FRAME // send outputs to the motors library motors_output(); // Inertial Nav // -------------------- read_inertia(); // check if ekf has reset target heading or position check_ekf_reset(); // run the attitude controllers update_flight_mode(); // update home from EKF if necessary update_home_from_EKF(); // check if we've landed or crashed update_land_and_crash_detectors();#if MOUNT == ENABLED // camera mount's fast update camera_mount.update_fast();#endif // log sensor health if (should_log(MASK_LOG_ANY)) { Log_Sensor_Health(); }}
请注意ahrs.update();
void Copter::read_AHRS(void){ // Perform IMU calculations and get attitude info //-----------------------------------------------#if HIL_MODE != HIL_MODE_DISABLED // update hil before ahrs update gcs_check_input();#endif ahrs.update();}
这个地方调用了AP_AHRS_NavEKF 中的update,而不是AP_AHRS_DCM 的updata
void AP_AHRS_NavEKF::update(void){#if !AP_AHRS_WITH_EKF1 if (_ekf_type == 1) { _ekf_type.set(2); }#endif update_DCM();#if AP_AHRS_WITH_EKF1 update_EKF1();#endif update_EKF2();#if CONFIG_HAL_BOARD == HAL_BOARD_SITL update_SITL();#endif // call AHRS_update hook if any AP_Module::call_hook_AHRS_update(*this);}
这里update_DCM();直接调用了AP_AHRS_DCM 的updata
void AP_AHRS_NavEKF::update_DCM(void){ // we need to restore the old DCM attitude values as these are // used internally in DCM to calculate error values for gyro drift // correction roll = _dcm_attitude.x; pitch = _dcm_attitude.y; yaw = _dcm_attitude.z; update_cd_values(); AP_AHRS_DCM::update(); // keep DCM attitude available for get_secondary_attitude() _dcm_attitude(roll, pitch, yaw);}
接着AP_AHRS_DCM::update();
// run a full DCM update roundvoidAP_AHRS_DCM::update(void){ float delta_t; if (_last_startup_ms == 0) { _last_startup_ms = AP_HAL::millis(); } // tell the IMU to grab some data _ins.update(); // ask the IMU how much time this sensor reading represents delta_t = _ins.get_delta_time(); // if the update call took more than 0.2 seconds then discard it, // otherwise we may move too far. This happens when arming motors // in ArduCopter if (delta_t > 0.2f) { memset(&_ra_sum[0], 0, sizeof(_ra_sum)); _ra_deltat = 0; return; } // Integrate the DCM matrix using gyro inputs matrix_update(delta_t); // Normalize the DCM matrix normalize(); // Perform drift correction drift_correction(delta_t); // paranoid check for bad values in the DCM matrix check_matrix(); // Calculate pitch, roll, yaw for stabilization and navigation euler_angles(); // update trig values including _cos_roll, cos_pitch update_trig();}
请注意
// tell the IMU to grab some data _ins.update();
/* update gyro and accel values from backends */void AP_InertialSensor::update(void){ // during initialisation update() may be called without // wait_for_sample(), and a wait is implied wait_for_sample(); if (!_hil_mode) { for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { // mark sensors unhealthy and let update() in each backend // mark them healthy via _publish_gyro() and // _publish_accel() _gyro_healthy[i] = false; _accel_healthy[i] = false; _delta_velocity_valid[i] = false; _delta_angle_valid[i] = false; } for (uint8_t i=0; i<_backend_count; i++) { _backends[i]->update(); } // clear accumulators for (uint8_t i = 0; i < INS_MAX_INSTANCES; i++) { _delta_velocity_acc[i].zero(); _delta_velocity_acc_dt[i] = 0; _delta_angle_acc[i].zero(); _delta_angle_acc_dt[i] = 0; } if (!_startup_error_counts_set) { for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { _accel_startup_error_count[i] = _accel_error_count[i]; _gyro_startup_error_count[i] = _gyro_error_count[i]; } if (_startup_ms == 0) { _startup_ms = AP_HAL::millis(); } else if (AP_HAL::millis()-_startup_ms > 2000) { _startup_error_counts_set = true; } } for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { if (_accel_error_count[i] < _accel_startup_error_count[i]) { _accel_startup_error_count[i] = _accel_error_count[i]; } if (_gyro_error_count[i] < _gyro_startup_error_count[i]) { _gyro_startup_error_count[i] = _gyro_error_count[i]; } } // adjust health status if a sensor has a non-zero error count // but another sensor doesn't. bool have_zero_accel_error_count = false; bool have_zero_gyro_error_count = false; for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { if (_accel_healthy[i] && _accel_error_count[i] <= _accel_startup_error_count[i]) { have_zero_accel_error_count = true; } if (_gyro_healthy[i] && _gyro_error_count[i] <= _gyro_startup_error_count[i]) { have_zero_gyro_error_count = true; } } for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { if (_gyro_healthy[i] && _gyro_error_count[i] > _gyro_startup_error_count[i] && have_zero_gyro_error_count) { // we prefer not to use a gyro that has had errors _gyro_healthy[i] = false; } if (_accel_healthy[i] && _accel_error_count[i] > _accel_startup_error_count[i] && have_zero_accel_error_count) { // we prefer not to use a accel that has had errors _accel_healthy[i] = false; } } // set primary to first healthy accel and gyro for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { if (_gyro_healthy[i] && _use[i]) { _primary_gyro = i; break; } } for (uint8_t i=0; i<INS_MAX_INSTANCES; i++) { if (_accel_healthy[i] && _use[i]) { _primary_accel = i; break; } } } _have_sample = false;}
请注意_backends[i]->update();
update()是虚函数
那么需要找update()所在类的继承类,搜索public AP_InertialSensor_Backend
有很多继承类,比如MPU6000
/* publish any pending data */bool AP_InertialSensor_MPU6000::update(){ update_accel(_accel_instance); update_gyro(_gyro_instance); _publish_temperature(_accel_instance, _temp_filtered); return true;}
px4
bool AP_InertialSensor_PX4::update(void) { // get the latest sample from the sensor drivers _get_sample(); for (uint8_t k=0; k<_num_accel_instances; k++) { update_accel(_accel_instance[k]); } for (uint8_t k=0; k<_num_gyro_instances; k++) { update_gyro(_gyro_instance[k]); } return true;}
那么需要找谁给_backends[i]赋了值
搜索_backends可找到_add_backend()
bool AP_InertialSensor::_add_backend(AP_InertialSensor_Backend *backend){ if (!backend) return false; if (_backend_count == INS_MAX_BACKENDS) AP_HAL::panic("Too many INS backends"); _backends[_backend_count++] = backend; return true;}
那么看哪里调用了_add_backend()
/* detect available backends for this board */voidAP_InertialSensor::detect_backends(void){ if (_backends_detected) return; _backends_detected = true; if (_hil_mode) { _add_backend(AP_InertialSensor_HIL::detect(*this)); return; } #if CONFIG_HAL_BOARD == HAL_BOARD_SITL _add_backend(AP_InertialSensor_SITL::detect(*this)); #elif HAL_INS_DEFAULT == HAL_INS_HIL _add_backend(AP_InertialSensor_HIL::detect(*this)); #elif HAL_INS_DEFAULT == HAL_INS_MPU60XX_SPI && defined(HAL_INS_DEFAULT_ROTATION) _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), HAL_INS_DEFAULT_ROTATION)); #elif HAL_INS_DEFAULT == HAL_INS_MPU60XX_SPI _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME))); #elif HAL_INS_DEFAULT == HAL_INS_MPU60XX_I2C && defined(HAL_INS_DEFAULT_ROTATION) _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.i2c_mgr->get_device(HAL_INS_MPU60x0_I2C_BUS, HAL_INS_MPU60x0_I2C_ADDR), HAL_INS_DEFAULT_ROTATION)); #elif HAL_INS_DEFAULT == HAL_INS_MPU60XX_I2C _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.i2c_mgr->get_device(HAL_INS_MPU60x0_I2C_BUS, HAL_INS_MPU60x0_I2C_ADDR))); #elif HAL_INS_DEFAULT == HAL_INS_BH _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.i2c_mgr->get_device(HAL_INS_MPU60x0_I2C_BUS, HAL_INS_MPU60x0_I2C_ADDR))); _add_backend(AP_InertialSensor_MPU9250::probe(*this, hal.spi->get_device(HAL_INS_MPU9250_NAME))); #elif HAL_INS_DEFAULT == HAL_INS_PX4 || HAL_INS_DEFAULT == HAL_INS_VRBRAIN if (AP_BoardConfig::get_board_type() == AP_BoardConfig::PX4_BOARD_PX4V1) { _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME))); } else if (AP_BoardConfig::get_board_type() == AP_BoardConfig::PX4_BOARD_PIXHAWK) { if (!_add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), ROTATION_ROLL_180))) { // handle pixfalcon with mpu9250 instead of mpu6000 _fast_sampling_mask.set_default(1); _add_backend(AP_InertialSensor_MPU9250::probe(*this, hal.spi->get_device(HAL_INS_MPU9250_NAME), ROTATION_ROLL_180)); } _add_backend(AP_InertialSensor_LSM9DS0::probe(*this, hal.spi->get_device(HAL_INS_LSM9DS0_G_NAME), hal.spi->get_device(HAL_INS_LSM9DS0_A_NAME), ROTATION_ROLL_180, ROTATION_ROLL_180_YAW_270)); } else if (AP_BoardConfig::get_board_type() == AP_BoardConfig::PX4_BOARD_PIXHAWK2) { // older Pixhawk2 boards have the MPU6000 instead of MPU9250 _fast_sampling_mask.set_default(1); if (!_add_backend(AP_InertialSensor_MPU9250::probe(*this, hal.spi->get_device(HAL_INS_MPU9250_EXT_NAME), ROTATION_PITCH_180))) { _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_EXT_NAME), ROTATION_PITCH_180)); } _add_backend(AP_InertialSensor_LSM9DS0::probe(*this, hal.spi->get_device(HAL_INS_LSM9DS0_EXT_G_NAME), hal.spi->get_device(HAL_INS_LSM9DS0_EXT_A_NAME), ROTATION_ROLL_180_YAW_270, ROTATION_ROLL_180_YAW_90)); if (!_add_backend(AP_InertialSensor_MPU9250::probe(*this, hal.spi->get_device(HAL_INS_MPU9250_NAME), ROTATION_YAW_270))) { _add_backend(AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), ROTATION_YAW_270)); } } ......
可以找到else if (AP_BoardConfig::get_board_type() == AP_BoardConfig::PX4_BOARD_PIXHAWK2)判断
AP_InertialSensor_MPU6000::probe(*this, hal.spi->get_device(HAL_INS_MPU60x0_NAME), ROTATION_YAW_270)返回AP_InertialSensor_Backend类的对象,也就是操作传感器的后端对象
我们使用的是px4,所以可以找到update()的实例化
(先岔开一会,想看看哪里调用了void AP_InertialSensor::detect_backends(void),请看最下面第4点)
AP_InertialSensor_PX4::update(void) 是update()的实现
bool AP_InertialSensor_PX4::update(void) { // get the latest sample from the sensor drivers _get_sample(); for (uint8_t k=0; k<_num_accel_instances; k++) { update_accel(_accel_instance[k]); } for (uint8_t k=0; k<_num_gyro_instances; k++) { update_gyro(_gyro_instance[k]); } return true;}
请注意_get_sample();
void AP_InertialSensor_PX4::_get_sample(){ for (uint8_t i=0; i<MAX(_num_accel_instances,_num_gyro_instances);i++) { struct accel_report accel_report; struct gyro_report gyro_report; bool gyro_valid = _get_gyro_sample(i,gyro_report); bool accel_valid = _get_accel_sample(i,accel_report); while(gyro_valid || accel_valid) { // interleave accel and gyro samples by time - this will allow sculling corrections later // check the next gyro measurement to see if it needs to be integrated first if(gyro_valid && accel_valid && gyro_report.timestamp <= accel_report.timestamp) { _new_gyro_sample(i,gyro_report); gyro_valid = _get_gyro_sample(i,gyro_report); continue; } // if not, try to integrate an accelerometer sample if(accel_valid) { _new_accel_sample(i,accel_report); accel_valid = _get_accel_sample(i,accel_report); continue; } // if not, we've only got gyro samples left in the buffer if(gyro_valid) { _new_gyro_sample(i,gyro_report); gyro_valid = _get_gyro_sample(i,gyro_report); } } }}
请注意
bool gyro_valid = _get_gyro_sample(i,gyro_report);
bool accel_valid = _get_accel_sample(i,accel_report);
bool AP_InertialSensor_PX4::_get_gyro_sample(uint8_t i, struct gyro_report &gyro_report) { if (i<_num_gyro_instances && _gyro_fd[i] != -1 && ::read(_gyro_fd[i], &gyro_report, sizeof(gyro_report)) == sizeof(gyro_report) && gyro_report.timestamp != _last_gyro_timestamp[i]) { return true; } return false;}
请注意 ::read(_gyro_fd[i], &gyro_report, sizeof(gyro_report))
根据2中_class_instance = register_class_devname(PATH);注册设备路径,可以根据_gyro_fd描述符直接调用
ssize_tMPU6000::read(struct file *filp, char *buffer, size_t buflen){ unsigned count = buflen / sizeof(accel_report); /* buffer must be large enough */ if (count < 1) { return -ENOSPC; } /* if automatic measurement is not enabled, get a fresh measurement into the buffer */ if (_call_interval == 0) { _accel_reports->flush(); measure(); } /* if no data, error (we could block here) */ if (_accel_reports->empty()) { return -EAGAIN; } perf_count(_accel_reads); /* copy reports out of our buffer to the caller */ accel_report *arp = reinterpret_cast<accel_report *>(buffer); int transferred = 0; while (count--) { if (!_accel_reports->get(arp)) { break; } transferred++; arp++; } /* return the number of bytes transferred */ return (transferred * sizeof(accel_report));}
于是读出数据。
疑问:是ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)读取的数据,还是ardupilot里面::read()读取数据?还是他们都可以读取数据?
4.startup_INS_ground()
void Copter::setup() | |init_ardupilot(); \ \__void Copter::init_ardupilot() | | startup_INS_ground(); | | void Copter::startup_INS_ground() | \ \_____ins.init(scheduler.get_loop_rate_hz()); | | void AP_InertialSensor::init(uint16_t sample_rate) | | void AP_InertialSensor::_start_backends() | | void AP_InertialSensor::detect_backends(void) | | _add_backend(AP_InertialSensor_PX4::detect(*this)); | | \ \_____AP_InertialSensor_Backend *AP_InertialSensor_PX4::detect(AP_InertialSensor &_imu) | | bool AP_InertialSensor_PX4::_init_sensor(void)
您的鼓励将是笔者书写高质量文章的最大动力^_^!!
- ardupilot如何读取传感器数据
- pixhawk串口读取传感器数据
- Htc 手机读取LightSensor(环境传感器)数据
- 使用Arduino读取水位传感器数据
- arduino读取BEC光照传感器数据
- 高通DSP读取传感器数据流程
- STM32读取MQ4传感器、DHT11温湿度传感器、GP2Y1014AU0F夏普光学灰尘传感器数据
- ARDupilot
- Ardupilot -- APM源码笔记三(重制)~ 传感器驱动程序
- Python脚本实现树莓派读取mpu9250传感器数据
- 如何读取配置文件数据
- Ubuntu16.04下如何编译 ardupilot
- pixhawk/px4如何获取及使用传感器数据
- pixhawk/px4如何获取及使用传感器数据
- 数据库ADO如何读取数据
- 如何读取Lucene索引数据
- 如何读取数据效率高?
- C#如何读取excel数据
- epublib 按指定层级拆分电子书
- Tensorflow学习: 自编码器Tensorflow代码
- 在Apache2环境下安装SSL证书,利用301将http定向到https
- http
- linux的高级网络配置
- ardupilot如何读取传感器数据
- 深度学习Flappy Bird
- 用 CSS 实现元素垂直居中,有哪些好的方案?
- 矩阵变换中等距、相似、仿射和投影变换的小结
- ZigBee TI ZStack CC2530 2.6 选择开发板和下载器
- dedecms 的这个dede:arclist里怎么调用添加的自定义新变量?
- 炒股养家
- nodejs操作mongodb数据库(转载)
- hdu2299Largest Triangle