diff --git a/makefiles/qurt.mk b/makefiles/qurt.mk index f34392a210..612dd0bd16 100644 --- a/makefiles/qurt.mk +++ b/makefiles/qurt.mk @@ -35,6 +35,5 @@ # MODULES += \ - platforms/common \ - platforms/qurt/px4_layer + platforms/common diff --git a/makefiles/qurt/config_qurt_default.mk b/makefiles/qurt/config_qurt_default.mk index c076cd5841..ba7ca3e143 100644 --- a/makefiles/qurt/config_qurt_default.mk +++ b/makefiles/qurt/config_qurt_default.mk @@ -10,17 +10,17 @@ # # Board support modules # -#MODULES += drivers/device -#MODULES += drivers/blinkm -#MODULES += drivers/hil -#MODULES += drivers/rgbled -#MODULES += modules/sensors +MODULES += drivers/device +MODULES += drivers/blinkm +MODULES += drivers/hil +MODULES += drivers/rgbled +MODULES += modules/sensors #MODULES += drivers/ms5611 # # System commands # -#MODULES += systemcmds/param +MODULES += systemcmds/param # # General system control @@ -30,8 +30,8 @@ # # Estimation modules (EKF/ SO3 / other filters) # -#MODULES += modules/attitude_estimator_ekf -#MODULES += modules/ekf_att_pos_estimator +MODULES += modules/attitude_estimator_ekf +MODULES += modules/ekf_att_pos_estimator # # Vehicle Control @@ -41,37 +41,37 @@ # # Library modules # -#MODULES += modules/systemlib -#MODULES += modules/systemlib/mixer -#MODULES += modules/uORB +MODULES += modules/systemlib +MODULES += modules/systemlib/mixer +MODULES += modules/uORB #MODULES += modules/dataman #MODULES += modules/sdlog2 -#MODULES += modules/simulator -#MODULES += modules/commander +MODULES += modules/simulator +MODULES += modules/commander # # Libraries # -#MODULES += lib/mathlib -#MODULES += lib/mathlib/math/filter -#MODULES += lib/geo -#MODULES += lib/geo_lookup -#MODULES += lib/conversion +MODULES += lib/mathlib +MODULES += lib/mathlib/math/filter +MODULES += lib/geo +MODULES += lib/geo_lookup +MODULES += lib/conversion # # QuRT port # MODULES += platforms/qurt/px4_layer -#MODULES += platforms/linux/drivers/accelsim -#MODULES += platforms/linux/drivers/gyrosim -#MODULES += platforms/linux/drivers/adcsim -#MODULES += platforms/linux/drivers/barosim +MODULES += platforms/posix/drivers/accelsim +MODULES += platforms/posix/drivers/gyrosim +MODULES += platforms/posix/drivers/adcsim +MODULES += platforms/posix/drivers/barosim # # Unit tests # MODULES += platforms/qurt/tests/hello -#MODULES += platforms/linux/tests/vcdev_test -#MODULES += platforms/linux/tests/hrt_test -#MODULES += platforms/linux/tests/wqueue +#MODULES += platforms/posix/tests/vcdev_test +#MODULES += platforms/posix/tests/hrt_test +#MODULES += platforms/posix/tests/wqueue diff --git a/makefiles/toolchain_hexagon.mk b/makefiles/toolchain_hexagon.mk index c409136c5b..75bcec41ba 100644 --- a/makefiles/toolchain_hexagon.mk +++ b/makefiles/toolchain_hexagon.mk @@ -68,7 +68,7 @@ endif # XXX this is pulled pretty directly from the fmu Make.defs - needs cleanup -MAXOPTIMIZATION ?= -O2 +MAXOPTIMIZATION ?= -Os # Base CPU flags for each of the supported architectures. # @@ -81,10 +81,11 @@ ifeq ($(CONFIG_BOARD),) $(error Board config does not define CONFIG_BOARD) endif ARCHDEFINES += -DCONFIG_ARCH_BOARD_$(CONFIG_BOARD) \ - -D__PX4_QURT \ + -D__PX4_QURT -D__PX4_POSIX \ -D__EXPORT= \ -Dnoreturn_function= \ -Drestrict= \ + -I/opt/6.4.05/gnu/hexagon/include \ -I$(PX4_BASE)/src/lib/eigen \ -I$(PX4_BASE)/src/platforms/qurt/include \ -I$(PX4_BASE)/../dspal/include \ @@ -116,7 +117,9 @@ ARCHWARNINGS = -Wall \ -Wextra \ -Werror \ -Wno-unused-parameter \ + -Wno-unused-function \ -Wno-unused-variable \ + -Wno-gnu-array-member-paren-init \ -Wno-cast-align \ -Wno-missing-braces \ -Wno-strict-aliasing @@ -206,6 +209,7 @@ DEP_INCLUDES = $(subst .o,.d,$(OBJS)) define COMPILE @$(ECHO) "CC: $1" @$(MKDIR) -p $(dir $2) + @echo $(Q) $(CCACHE) $(CC) -MD -c $(CFLAGS) $(abspath $1) -o $2 $(Q) $(CCACHE) $(CC) -MD -c $(CFLAGS) $(abspath $1) -o $2 endef diff --git a/src/drivers/device/vdev_posix.cpp b/src/drivers/device/vdev_posix.cpp index 31f141267f..58b445d607 100644 --- a/src/drivers/device/vdev_posix.cpp +++ b/src/drivers/device/vdev_posix.cpp @@ -37,7 +37,8 @@ * POSIX-like API for virtual character device */ -#include "px4_posix.h" +#include +#include #include "device.h" #include diff --git a/src/drivers/hil/hil_posix.cpp b/src/drivers/hil/hil_posix.cpp index eca2ec8ba5..eb86a49742 100644 --- a/src/drivers/hil/hil_posix.cpp +++ b/src/drivers/hil/hil_posix.cpp @@ -50,6 +50,8 @@ #include #include +#include +#include #include #include @@ -61,7 +63,8 @@ #include #include #include -#include +#include +#include #include #include @@ -409,7 +412,7 @@ HIL::task_main() /* last resort: catch NaN, INF and out-of-band errors */ if (i < outputs.noutputs && - isfinite(outputs.output[i]) && + PX4_ISFINITE(outputs.output[i]) && outputs.output[i] >= -1.0f && outputs.output[i] <= 1.0f) { /* scale for PWM output 900 - 2100us */ diff --git a/src/modules/sensors/sensors_posix.cpp b/src/modules/sensors/sensors.cpp similarity index 97% rename from src/modules/sensors/sensors_posix.cpp rename to src/modules/sensors/sensors.cpp index 755d4f1678..adf231840c 100644 --- a/src/modules/sensors/sensors_posix.cpp +++ b/src/modules/sensors/sensors.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ #include #include +//#include #include #include @@ -113,7 +115,7 @@ #ifdef CONFIG_ARCH_BOARD_PX4FMU_V1 #define ADC_BATTERY_VOLTAGE_CHANNEL 10 -#define ADC_BATTERY_CURRENT_CHANNEL -1 +#define ADC_BATTERY_CURRENT_CHANNEL ((uint8_t)(-1)) #define ADC_AIRSPEED_VOLTAGE_CHANNEL 11 #endif @@ -126,8 +128,8 @@ #ifdef CONFIG_ARCH_BOARD_AEROCORE #define ADC_BATTERY_VOLTAGE_CHANNEL 10 -#define ADC_BATTERY_CURRENT_CHANNEL -1 -#define ADC_AIRSPEED_VOLTAGE_CHANNEL -1 +#define ADC_BATTERY_CURRENT_CHANNEL ((uint8_t)(-1)) +#define ADC_AIRSPEED_VOLTAGE_CHANNEL ((uint8_t)(-1)) #endif #define BATT_V_LOWPASS 0.001f @@ -147,7 +149,7 @@ #endif static const int ERROR = -1; -#define CAL_FAILED_APPLY_CAL_MSG "FAILED APPLYING SENSOR CAL" +#define CAL_FAILED_APPLY_CAL_MSG "FAILED APPLYING %s CAL #%u" /** * Sensor app start / stop handling function @@ -225,7 +227,7 @@ private: int _rc_sub; /**< raw rc channels data subscription */ int _baro_sub; /**< raw baro data subscription */ int _baro1_sub; /**< raw baro data subscription */ - int _airspeed_sub; /**< airspeed subscription */ + //int _airspeed_sub; /**< airspeed subscription */ int _diff_pres_sub; /**< raw differential pressure subscription */ int _vcontrol_mode_sub; /**< vehicle control mode subscription */ int _params_sub; /**< notification of parameter updates */ @@ -671,11 +673,7 @@ Sensors::parameters_update() tmpRevFactor = tmpScaleFactor * _parameters.rev[i]; /* handle blowup in the scaling factor calculation */ -#ifdef __PX4_NUTTX - if (!isfinite(tmpScaleFactor) || -#else - if (!std::isfinite(tmpScaleFactor) || -#endif + if (!PX4_ISFINITE(tmpScaleFactor) || (tmpRevFactor < 0.000001f) || (tmpRevFactor > 0.2f)) { warnx("RC chan %u not sane, scaling: %8.6f, rev: %d", i, (double)tmpScaleFactor, (int)(_parameters.rev[i])); @@ -855,7 +853,7 @@ Sensors::parameters_update() barofd = px4_open(BARO0_DEVICE_PATH, 0); if (barofd < 0) { - warnx("ERROR: no barometer found on %s", BARO0_DEVICE_PATH); + warnx("ERROR: no barometer foundon %s", BARO0_DEVICE_PATH); return ERROR; } else { @@ -1021,6 +1019,7 @@ Sensors::accel_poll(struct sensor_combined_s &raw) raw.accelerometer_timestamp = accel_report.timestamp; raw.accelerometer_errcount = accel_report.error_count; + raw.accelerometer_temp = accel_report.temperature; } orb_check(_accel1_sub, &accel_updated); @@ -1043,6 +1042,7 @@ Sensors::accel_poll(struct sensor_combined_s &raw) raw.accelerometer1_timestamp = accel_report.timestamp; raw.accelerometer1_errcount = accel_report.error_count; + raw.accelerometer1_temp = accel_report.temperature; } orb_check(_accel2_sub, &accel_updated); @@ -1065,6 +1065,7 @@ Sensors::accel_poll(struct sensor_combined_s &raw) raw.accelerometer2_timestamp = accel_report.timestamp; raw.accelerometer2_errcount = accel_report.error_count; + raw.accelerometer2_temp = accel_report.temperature; } } @@ -1092,6 +1093,7 @@ Sensors::gyro_poll(struct sensor_combined_s &raw) raw.timestamp = gyro_report.timestamp; raw.gyro_errcount = gyro_report.error_count; + raw.gyro_temp = gyro_report.temperature; } orb_check(_gyro1_sub, &gyro_updated); @@ -1114,6 +1116,7 @@ Sensors::gyro_poll(struct sensor_combined_s &raw) raw.gyro1_timestamp = gyro_report.timestamp; raw.gyro1_errcount = gyro_report.error_count; + raw.gyro1_temp = gyro_report.temperature; } orb_check(_gyro2_sub, &gyro_updated); @@ -1136,6 +1139,7 @@ Sensors::gyro_poll(struct sensor_combined_s &raw) raw.gyro2_timestamp = gyro_report.timestamp; raw.gyro2_errcount = gyro_report.error_count; + raw.gyro2_temp = gyro_report.temperature; } } @@ -1164,6 +1168,7 @@ Sensors::mag_poll(struct sensor_combined_s &raw) raw.magnetometer_timestamp = mag_report.timestamp; raw.magnetometer_errcount = mag_report.error_count; + raw.magnetometer_temp = mag_report.temperature; } orb_check(_mag1_sub, &mag_updated); @@ -1187,6 +1192,7 @@ Sensors::mag_poll(struct sensor_combined_s &raw) raw.magnetometer1_timestamp = mag_report.timestamp; raw.magnetometer1_errcount = mag_report.error_count; + raw.magnetometer1_temp = mag_report.temperature; } orb_check(_mag2_sub, &mag_updated); @@ -1210,6 +1216,7 @@ Sensors::mag_poll(struct sensor_combined_s &raw) raw.magnetometer2_timestamp = mag_report.timestamp; raw.magnetometer2_errcount = mag_report.error_count; + raw.magnetometer2_temp = mag_report.temperature; } } @@ -1379,14 +1386,13 @@ Sensors::parameter_update_poll(bool forced) failed = failed || (OK != param_get(param_find(str), &gscale.z_scale)); if (failed) { - warnx("%s: gyro #%u", CAL_FAILED_APPLY_CAL_MSG, gyro_count); + warnx(CAL_FAILED_APPLY_CAL_MSG, "gyro", i); } else { /* apply new scaling and offsets */ res = px4_ioctl(fd, GYROIOCSSCALE, (long unsigned int)&gscale); if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG); + warnx(CAL_FAILED_APPLY_CAL_MSG, "gyro", i); } else { - gyro_count++; config_ok = true; } } @@ -1394,11 +1400,11 @@ Sensors::parameter_update_poll(bool forced) } } - px4_close(fd); - - if (!config_ok) { - warnx("NO CONFIG FOR GYRO #%u", s); + if (config_ok) { + gyro_count++; } + + px4_close(fd); } /* run through all accel sensors */ @@ -1446,14 +1452,13 @@ Sensors::parameter_update_poll(bool forced) failed = failed || (OK != param_get(param_find(str), &gscale.z_scale)); if (failed) { - warnx("%s: acc #%u", CAL_FAILED_APPLY_CAL_MSG, accel_count); + warnx(CAL_FAILED_APPLY_CAL_MSG, "accel", i); } else { /* apply new scaling and offsets */ res = px4_ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&gscale); if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG); + warnx(CAL_FAILED_APPLY_CAL_MSG, "accel", i); } else { - accel_count++; config_ok = true; } } @@ -1461,11 +1466,11 @@ Sensors::parameter_update_poll(bool forced) } } - px4_close(fd); - - if (!config_ok) { - warnx("NO CONFIG FOR ACCEL #%u", s); + if (config_ok) { + accel_count++; } + + px4_close(fd); } /* run through all mag sensors */ @@ -1477,9 +1482,16 @@ Sensors::parameter_update_poll(bool forced) int fd = px4_open(str, 0); if (fd < 0) { + /* the driver is not running, abort */ continue; } + /* set a valid default rotation (same as board). + * if the mag is configured, this might be replaced + * in the section below. + */ + _mag_rotation[s] = _board_rotation; + bool config_ok = false; /* run through all stored calibrations */ @@ -1563,14 +1575,13 @@ Sensors::parameter_update_poll(bool forced) } if (failed) { - warnx("%s: mag #%u", CAL_FAILED_APPLY_CAL_MSG, mag_count); + warnx(CAL_FAILED_APPLY_CAL_MSG, "mag", i); } else { /* apply new scaling and offsets */ res = px4_ioctl(fd, MAGIOCSSCALE, (long unsigned int)&gscale); if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG); + warnx(CAL_FAILED_APPLY_CAL_MSG, "mag", i); } else { - mag_count++; config_ok = true; } } @@ -1578,11 +1589,11 @@ Sensors::parameter_update_poll(bool forced) } } - px4_close(fd); - - if (!config_ok) { - warnx("NO CONFIG FOR MAG #%u", s); + if (config_ok) { + mag_count++; } + + px4_close(fd); } int fd = px4_open(AIRSPEED0_DEVICE_PATH, 0); @@ -1602,7 +1613,7 @@ Sensors::parameter_update_poll(bool forced) px4_close(fd); } - warnx("config: %u gyros, %u mags, %u accels", gyro_count, mag_count, accel_count); + warnx("valid configs: %u gyros, %u mags, %u accels", gyro_count, mag_count, accel_count); } } @@ -1947,11 +1958,7 @@ Sensors::rc_poll() _rc.channels[i] *= _parameters.rev[i]; /* handle any parameter-induced blowups */ -#ifdef __PX4_NUTTX - if (!isfinite(_rc.channels[i])) { -#else - if (!std::isfinite(_rc.channels[i])) { -#endif + if (!PX4_ISFINITE(_rc.channels[i])) { _rc.channels[i] = 0.0f; } } @@ -2152,12 +2159,8 @@ Sensors::task_main() /* advertise the sensor_combined topic and make the initial publication */ _sensor_pub = orb_advertise(ORB_ID(sensor_combined), &raw); - if (_sensor_pub < 0) { - warnx("Sensors::task_main ERROR - uORB not started"); - } - /* wakeup source(s) */ - struct pollfd fds[1]; + px4_pollfd_struct_t fds[1]; /* use the gyro to pace output - XXX BROKEN if we are using the L3GD20 */ fds[0].fd = _gyro_sub; @@ -2168,7 +2171,7 @@ Sensors::task_main() while (!_task_should_exit) { /* wait for up to 50ms for data */ - int pret = poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 50); + int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 50); /* if pret == 0 it timed out - periodic check for _task_should_exit, etc. */ diff --git a/src/modules/sensors/sensors_nuttx.cpp b/src/modules/sensors/sensors_nuttx.cpp deleted file mode 100644 index 3fc8627c15..0000000000 --- a/src/modules/sensors/sensors_nuttx.cpp +++ /dev/null @@ -1,2305 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name PX4 nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/** - * @file sensors.cpp - * - * PX4 Flight Core transitional mapping layer. - * - * This app / class mapps the PX4 middleware layer / drivers to the application - * layer of the PX4 Flight Core. Individual sensors can be accessed directly as - * well instead of relying on the sensor_combined topic. - * - * @author Lorenz Meier - * @author Julian Oes - * @author Thomas Gubler - * @author Anton Babushkin - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * Analog layout: - * FMU: - * IN2 - battery voltage - * IN3 - battery current - * IN4 - 5V sense - * IN10 - spare (we could actually trim these from the set) - * IN11 - spare (we could actually trim these from the set) - * IN12 - spare (we could actually trim these from the set) - * IN13 - aux1 - * IN14 - aux2 - * IN15 - pressure sensor - * - * IO: - * IN4 - servo supply rail - * IN5 - analog RSSI - */ - -#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1 -#define ADC_BATTERY_VOLTAGE_CHANNEL 10 -#define ADC_BATTERY_CURRENT_CHANNEL -1 -#define ADC_AIRSPEED_VOLTAGE_CHANNEL 11 -#endif - -#ifdef CONFIG_ARCH_BOARD_PX4FMU_V2 -#define ADC_BATTERY_VOLTAGE_CHANNEL 2 -#define ADC_BATTERY_CURRENT_CHANNEL 3 -#define ADC_5V_RAIL_SENSE 4 -#define ADC_AIRSPEED_VOLTAGE_CHANNEL 15 -#endif - -#ifdef CONFIG_ARCH_BOARD_AEROCORE -#define ADC_BATTERY_VOLTAGE_CHANNEL 10 -#define ADC_BATTERY_CURRENT_CHANNEL -1 -#define ADC_AIRSPEED_VOLTAGE_CHANNEL -1 -#endif - -#define BATT_V_LOWPASS 0.001f -#define BATT_V_IGNORE_THRESHOLD 4.8f - -/** - * HACK - true temperature is much less than indicated temperature in baro, - * subtract 5 degrees in an attempt to account for the electrical upheating of the PCB - */ -#define PCB_TEMP_ESTIMATE_DEG 5.0f -#define STICK_ON_OFF_LIMIT 0.75f -#define MAG_ROT_VAL_INTERNAL -1 - -/* oddly, ERROR is not defined for c++ */ -#ifdef ERROR -# undef ERROR -#endif -static const int ERROR = -1; - -#define CAL_FAILED_APPLY_CAL_MSG "FAILED APPLYING %s CAL #%u" - -/** - * Sensor app start / stop handling function - * - * @ingroup apps - */ -extern "C" __EXPORT int sensors_main(int argc, char *argv[]); - -class Sensors -{ -public: - /** - * Constructor - */ - Sensors(); - - /** - * Destructor, also kills the sensors task. - */ - ~Sensors(); - - /** - * Start the sensors task. - * - * @return OK on success. - */ - int start(); - -private: - static const unsigned _rc_max_chan_count = RC_INPUT_MAX_CHANNELS; /**< maximum number of r/c channels we handle */ - - /** - * Get and limit value for specified RC function. Returns NAN if not mapped. - */ - float get_rc_value(uint8_t func, float min_value, float max_value); - - /** - * Get switch position for specified function. - */ - switch_pos_t get_rc_sw3pos_position(uint8_t func, float on_th, bool on_inv, float mid_th, bool mid_inv); - switch_pos_t get_rc_sw2pos_position(uint8_t func, float on_th, bool on_inv); - - /** - * Update paramters from RC channels if the functionality is activated and the - * input has changed since the last update - * - * @param - */ - void set_params_from_rc(); - - /** - * Gather and publish RC input data. - */ - void rc_poll(); - - /* XXX should not be here - should be own driver */ - int _fd_adc; /**< ADC driver handle */ - hrt_abstime _last_adc; /**< last time we took input from the ADC */ - - bool _task_should_exit; /**< if true, sensor task should exit */ - int _sensors_task; /**< task handle for sensor task */ - - bool _hil_enabled; /**< if true, HIL is active */ - bool _publishing; /**< if true, we are publishing sensor data */ - - int _gyro_sub; /**< raw gyro0 data subscription */ - int _accel_sub; /**< raw accel0 data subscription */ - int _mag_sub; /**< raw mag0 data subscription */ - int _gyro1_sub; /**< raw gyro1 data subscription */ - int _accel1_sub; /**< raw accel1 data subscription */ - int _mag1_sub; /**< raw mag1 data subscription */ - int _gyro2_sub; /**< raw gyro2 data subscription */ - int _accel2_sub; /**< raw accel2 data subscription */ - int _mag2_sub; /**< raw mag2 data subscription */ - int _rc_sub; /**< raw rc channels data subscription */ - int _baro_sub; /**< raw baro data subscription */ - int _baro1_sub; /**< raw baro data subscription */ - int _airspeed_sub; /**< airspeed subscription */ - int _diff_pres_sub; /**< raw differential pressure subscription */ - int _vcontrol_mode_sub; /**< vehicle control mode subscription */ - int _params_sub; /**< notification of parameter updates */ - int _rc_parameter_map_sub; /**< rc parameter map subscription */ - int _manual_control_sub; /**< notification of manual control updates */ - - orb_advert_t _sensor_pub; /**< combined sensor data topic */ - orb_advert_t _manual_control_pub; /**< manual control signal topic */ - orb_advert_t _actuator_group_3_pub; /**< manual control as actuator topic */ - orb_advert_t _rc_pub; /**< raw r/c control topic */ - orb_advert_t _battery_pub; /**< battery status */ - orb_advert_t _airspeed_pub; /**< airspeed */ - orb_advert_t _diff_pres_pub; /**< differential_pressure */ - - perf_counter_t _loop_perf; /**< loop performance counter */ - - struct rc_channels_s _rc; /**< r/c channel data */ - struct battery_status_s _battery_status; /**< battery status */ - struct baro_report _barometer; /**< barometer data */ - struct differential_pressure_s _diff_pres; - struct airspeed_s _airspeed; - struct rc_parameter_map_s _rc_parameter_map; - - math::Matrix<3, 3> _board_rotation; /**< rotation matrix for the orientation that the board is mounted */ - math::Matrix<3, 3> _mag_rotation[3]; /**< rotation matrix for the orientation that the external mag0 is mounted */ - - uint64_t _battery_discharged; /**< battery discharged current in mA*ms */ - hrt_abstime _battery_current_timestamp; /**< timestamp of last battery current reading */ - - struct { - float min[_rc_max_chan_count]; - float trim[_rc_max_chan_count]; - float max[_rc_max_chan_count]; - float rev[_rc_max_chan_count]; - float dz[_rc_max_chan_count]; - float scaling_factor[_rc_max_chan_count]; - - float diff_pres_offset_pa; - float diff_pres_analog_scale; - - int board_rotation; - int flow_rotation; - - float board_offset[3]; - - int rc_map_roll; - int rc_map_pitch; - int rc_map_yaw; - int rc_map_throttle; - int rc_map_failsafe; - - int rc_map_mode_sw; - int rc_map_return_sw; - int rc_map_posctl_sw; - int rc_map_loiter_sw; - int rc_map_acro_sw; - int rc_map_offboard_sw; - - int rc_map_flaps; - - int rc_map_aux1; - int rc_map_aux2; - int rc_map_aux3; - int rc_map_aux4; - int rc_map_aux5; - - int rc_map_param[RC_PARAM_MAP_NCHAN]; - - int32_t rc_fails_thr; - float rc_assist_th; - float rc_auto_th; - float rc_posctl_th; - float rc_return_th; - float rc_loiter_th; - float rc_acro_th; - float rc_offboard_th; - bool rc_assist_inv; - bool rc_auto_inv; - bool rc_posctl_inv; - bool rc_return_inv; - bool rc_loiter_inv; - bool rc_acro_inv; - bool rc_offboard_inv; - - float battery_voltage_scaling; - float battery_current_scaling; - - float baro_qnh; - - } _parameters; /**< local copies of interesting parameters */ - - struct { - param_t min[_rc_max_chan_count]; - param_t trim[_rc_max_chan_count]; - param_t max[_rc_max_chan_count]; - param_t rev[_rc_max_chan_count]; - param_t dz[_rc_max_chan_count]; - - param_t diff_pres_offset_pa; - param_t diff_pres_analog_scale; - - param_t rc_map_roll; - param_t rc_map_pitch; - param_t rc_map_yaw; - param_t rc_map_throttle; - param_t rc_map_failsafe; - - param_t rc_map_mode_sw; - param_t rc_map_return_sw; - param_t rc_map_posctl_sw; - param_t rc_map_loiter_sw; - param_t rc_map_acro_sw; - param_t rc_map_offboard_sw; - - param_t rc_map_flaps; - - param_t rc_map_aux1; - param_t rc_map_aux2; - param_t rc_map_aux3; - param_t rc_map_aux4; - param_t rc_map_aux5; - - param_t rc_map_param[RC_PARAM_MAP_NCHAN]; - param_t rc_param[RC_PARAM_MAP_NCHAN]; /**< param handles for the paramters which are bound - to a RC channel, equivalent float values in the - _parameters struct are not existing - because these parameters are never read. */ - - param_t rc_fails_thr; - param_t rc_assist_th; - param_t rc_auto_th; - param_t rc_posctl_th; - param_t rc_return_th; - param_t rc_loiter_th; - param_t rc_acro_th; - param_t rc_offboard_th; - - param_t battery_voltage_scaling; - param_t battery_current_scaling; - - param_t board_rotation; - param_t flow_rotation; - - param_t board_offset[3]; - - param_t baro_qnh; - - } _parameter_handles; /**< handles for interesting parameters */ - - - /** - * Update our local parameter cache. - */ - int parameters_update(); - - /** - * Do accel-related initialisation. - */ - int accel_init(); - - /** - * Do gyro-related initialisation. - */ - int gyro_init(); - - /** - * Do mag-related initialisation. - */ - int mag_init(); - - /** - * Do baro-related initialisation. - */ - int baro_init(); - - /** - * Do adc-related initialisation. - */ - int adc_init(); - - /** - * Poll the accelerometer for updated data. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void accel_poll(struct sensor_combined_s &raw); - - /** - * Poll the gyro for updated data. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void gyro_poll(struct sensor_combined_s &raw); - - /** - * Poll the magnetometer for updated data. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void mag_poll(struct sensor_combined_s &raw); - - /** - * Poll the barometer for updated data. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void baro_poll(struct sensor_combined_s &raw); - - /** - * Poll the differential pressure sensor for updated data. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void diff_pres_poll(struct sensor_combined_s &raw); - - /** - * Check for changes in vehicle control mode. - */ - void vehicle_control_mode_poll(); - - /** - * Check for changes in parameters. - */ - void parameter_update_poll(bool forced = false); - - /** - * Check for changes in rc_parameter_map - */ - void rc_parameter_map_poll(bool forced = false); - - /** - * Poll the ADC and update readings to suit. - * - * @param raw Combined sensor data structure into which - * data should be returned. - */ - void adc_poll(struct sensor_combined_s &raw); - - /** - * Shim for calling task_main from task_create. - */ - static void task_main_trampoline(int argc, char *argv[]); - - /** - * Main sensor collection task. - */ - void task_main(); -}; - -namespace sensors -{ - -Sensors *g_sensors = nullptr; -} - -Sensors::Sensors() : - _fd_adc(-1), - _last_adc(0), - - _task_should_exit(true), - _sensors_task(-1), - _hil_enabled(false), - _publishing(true), - - /* subscriptions */ - _gyro_sub(-1), - _accel_sub(-1), - _mag_sub(-1), - _gyro1_sub(-1), - _accel1_sub(-1), - _mag1_sub(-1), - _gyro2_sub(-1), - _accel2_sub(-1), - _mag2_sub(-1), - _rc_sub(-1), - _baro_sub(-1), - _baro1_sub(-1), - _vcontrol_mode_sub(-1), - _params_sub(-1), - _rc_parameter_map_sub(-1), - _manual_control_sub(-1), - - /* publications */ - _sensor_pub(-1), - _manual_control_pub(-1), - _actuator_group_3_pub(-1), - _rc_pub(-1), - _battery_pub(-1), - _airspeed_pub(-1), - _diff_pres_pub(-1), - - /* performance counters */ - _loop_perf(perf_alloc(PC_ELAPSED, "sensor task update")), - - _board_rotation{}, - _mag_rotation{}, - - _battery_discharged(0), - _battery_current_timestamp(0) -{ - memset(&_rc, 0, sizeof(_rc)); - memset(&_diff_pres, 0, sizeof(_diff_pres)); - memset(&_rc_parameter_map, 0, sizeof(_rc_parameter_map)); - - /* basic r/c parameters */ - for (unsigned i = 0; i < _rc_max_chan_count; i++) { - char nbuf[16]; - - /* min values */ - sprintf(nbuf, "RC%d_MIN", i + 1); - _parameter_handles.min[i] = param_find(nbuf); - - /* trim values */ - sprintf(nbuf, "RC%d_TRIM", i + 1); - _parameter_handles.trim[i] = param_find(nbuf); - - /* max values */ - sprintf(nbuf, "RC%d_MAX", i + 1); - _parameter_handles.max[i] = param_find(nbuf); - - /* channel reverse */ - sprintf(nbuf, "RC%d_REV", i + 1); - _parameter_handles.rev[i] = param_find(nbuf); - - /* channel deadzone */ - sprintf(nbuf, "RC%d_DZ", i + 1); - _parameter_handles.dz[i] = param_find(nbuf); - - } - - /* mandatory input switched, mapped to channels 1-4 per default */ - _parameter_handles.rc_map_roll = param_find("RC_MAP_ROLL"); - _parameter_handles.rc_map_pitch = param_find("RC_MAP_PITCH"); - _parameter_handles.rc_map_yaw = param_find("RC_MAP_YAW"); - _parameter_handles.rc_map_throttle = param_find("RC_MAP_THROTTLE"); - _parameter_handles.rc_map_failsafe = param_find("RC_MAP_FAILSAFE"); - - /* mandatory mode switches, mapped to channel 5 and 6 per default */ - _parameter_handles.rc_map_mode_sw = param_find("RC_MAP_MODE_SW"); - _parameter_handles.rc_map_return_sw = param_find("RC_MAP_RETURN_SW"); - - _parameter_handles.rc_map_flaps = param_find("RC_MAP_FLAPS"); - - /* optional mode switches, not mapped per default */ - _parameter_handles.rc_map_posctl_sw = param_find("RC_MAP_POSCTL_SW"); - _parameter_handles.rc_map_loiter_sw = param_find("RC_MAP_LOITER_SW"); - _parameter_handles.rc_map_acro_sw = param_find("RC_MAP_ACRO_SW"); - _parameter_handles.rc_map_offboard_sw = param_find("RC_MAP_OFFB_SW"); - - _parameter_handles.rc_map_aux1 = param_find("RC_MAP_AUX1"); - _parameter_handles.rc_map_aux2 = param_find("RC_MAP_AUX2"); - _parameter_handles.rc_map_aux3 = param_find("RC_MAP_AUX3"); - _parameter_handles.rc_map_aux4 = param_find("RC_MAP_AUX4"); - _parameter_handles.rc_map_aux5 = param_find("RC_MAP_AUX5"); - - /* RC to parameter mapping for changing parameters with RC */ - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - char name[PARAM_ID_LEN]; - snprintf(name, PARAM_ID_LEN, "RC_MAP_PARAM%d", i + 1); // shifted by 1 because param name starts at 1 - _parameter_handles.rc_map_param[i] = param_find(name); - } - - /* RC thresholds */ - _parameter_handles.rc_fails_thr = param_find("RC_FAILS_THR"); - _parameter_handles.rc_assist_th = param_find("RC_ASSIST_TH"); - _parameter_handles.rc_auto_th = param_find("RC_AUTO_TH"); - _parameter_handles.rc_posctl_th = param_find("RC_POSCTL_TH"); - _parameter_handles.rc_return_th = param_find("RC_RETURN_TH"); - _parameter_handles.rc_loiter_th = param_find("RC_LOITER_TH"); - _parameter_handles.rc_acro_th = param_find("RC_ACRO_TH"); - _parameter_handles.rc_offboard_th = param_find("RC_OFFB_TH"); - - /* Differential pressure offset */ - _parameter_handles.diff_pres_offset_pa = param_find("SENS_DPRES_OFF"); - _parameter_handles.diff_pres_analog_scale = param_find("SENS_DPRES_ANSC"); - - _parameter_handles.battery_voltage_scaling = param_find("BAT_V_SCALING"); - _parameter_handles.battery_current_scaling = param_find("BAT_C_SCALING"); - - /* rotations */ - _parameter_handles.board_rotation = param_find("SENS_BOARD_ROT"); - _parameter_handles.flow_rotation = param_find("SENS_FLOW_ROT"); - - /* rotation offsets */ - _parameter_handles.board_offset[0] = param_find("SENS_BOARD_X_OFF"); - _parameter_handles.board_offset[1] = param_find("SENS_BOARD_Y_OFF"); - _parameter_handles.board_offset[2] = param_find("SENS_BOARD_Z_OFF"); - - /* Barometer QNH */ - _parameter_handles.baro_qnh = param_find("SENS_BARO_QNH"); - - /* fetch initial parameter values */ - parameters_update(); -} - -Sensors::~Sensors() -{ - if (_sensors_task != -1) { - - /* task wakes up every 100ms or so at the longest */ - _task_should_exit = true; - - /* wait for a second for the task to quit at our request */ - unsigned i = 0; - - do { - /* wait 20ms */ - usleep(20000); - - /* if we have given up, kill it */ - if (++i > 50) { - task_delete(_sensors_task); - break; - } - } while (_sensors_task != -1); - } - - sensors::g_sensors = nullptr; -} - -int -Sensors::parameters_update() -{ - bool rc_valid = true; - float tmpScaleFactor = 0.0f; - float tmpRevFactor = 0.0f; - - /* rc values */ - for (unsigned int i = 0; i < _rc_max_chan_count; i++) { - - param_get(_parameter_handles.min[i], &(_parameters.min[i])); - param_get(_parameter_handles.trim[i], &(_parameters.trim[i])); - param_get(_parameter_handles.max[i], &(_parameters.max[i])); - param_get(_parameter_handles.rev[i], &(_parameters.rev[i])); - param_get(_parameter_handles.dz[i], &(_parameters.dz[i])); - - tmpScaleFactor = (1.0f / ((_parameters.max[i] - _parameters.min[i]) / 2.0f) * _parameters.rev[i]); - tmpRevFactor = tmpScaleFactor * _parameters.rev[i]; - - /* handle blowup in the scaling factor calculation */ - if (!isfinite(tmpScaleFactor) || - (tmpRevFactor < 0.000001f) || - (tmpRevFactor > 0.2f)) { - warnx("RC chan %u not sane, scaling: %8.6f, rev: %d", i, (double)tmpScaleFactor, (int)(_parameters.rev[i])); - /* scaling factors do not make sense, lock them down */ - _parameters.scaling_factor[i] = 0.0f; - rc_valid = false; - - } else { - _parameters.scaling_factor[i] = tmpScaleFactor; - } - } - - /* handle wrong values */ - if (!rc_valid) { - warnx("WARNING WARNING WARNING\n\nRC CALIBRATION NOT SANE!\n\n"); - } - - const char *paramerr = "FAIL PARM LOAD"; - - /* channel mapping */ - if (param_get(_parameter_handles.rc_map_roll, &(_parameters.rc_map_roll)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_pitch, &(_parameters.rc_map_pitch)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_yaw, &(_parameters.rc_map_yaw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_throttle, &(_parameters.rc_map_throttle)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_failsafe, &(_parameters.rc_map_failsafe)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_mode_sw, &(_parameters.rc_map_mode_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_return_sw, &(_parameters.rc_map_return_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_posctl_sw, &(_parameters.rc_map_posctl_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_loiter_sw, &(_parameters.rc_map_loiter_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_acro_sw, &(_parameters.rc_map_acro_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_offboard_sw, &(_parameters.rc_map_offboard_sw)) != OK) { - warnx("%s", paramerr); - } - - if (param_get(_parameter_handles.rc_map_flaps, &(_parameters.rc_map_flaps)) != OK) { - warnx("%s", paramerr); - } - - param_get(_parameter_handles.rc_map_aux1, &(_parameters.rc_map_aux1)); - param_get(_parameter_handles.rc_map_aux2, &(_parameters.rc_map_aux2)); - param_get(_parameter_handles.rc_map_aux3, &(_parameters.rc_map_aux3)); - param_get(_parameter_handles.rc_map_aux4, &(_parameters.rc_map_aux4)); - param_get(_parameter_handles.rc_map_aux5, &(_parameters.rc_map_aux5)); - - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - param_get(_parameter_handles.rc_map_param[i], &(_parameters.rc_map_param[i])); - } - - param_get(_parameter_handles.rc_fails_thr, &(_parameters.rc_fails_thr)); - param_get(_parameter_handles.rc_assist_th, &(_parameters.rc_assist_th)); - _parameters.rc_assist_inv = (_parameters.rc_assist_th < 0); - _parameters.rc_assist_th = fabs(_parameters.rc_assist_th); - param_get(_parameter_handles.rc_auto_th, &(_parameters.rc_auto_th)); - _parameters.rc_auto_inv = (_parameters.rc_auto_th < 0); - _parameters.rc_auto_th = fabs(_parameters.rc_auto_th); - param_get(_parameter_handles.rc_posctl_th, &(_parameters.rc_posctl_th)); - _parameters.rc_posctl_inv = (_parameters.rc_posctl_th < 0); - _parameters.rc_posctl_th = fabs(_parameters.rc_posctl_th); - param_get(_parameter_handles.rc_return_th, &(_parameters.rc_return_th)); - _parameters.rc_return_inv = (_parameters.rc_return_th < 0); - _parameters.rc_return_th = fabs(_parameters.rc_return_th); - param_get(_parameter_handles.rc_loiter_th, &(_parameters.rc_loiter_th)); - _parameters.rc_loiter_inv = (_parameters.rc_loiter_th < 0); - _parameters.rc_loiter_th = fabs(_parameters.rc_loiter_th); - param_get(_parameter_handles.rc_acro_th, &(_parameters.rc_acro_th)); - _parameters.rc_acro_inv = (_parameters.rc_acro_th < 0); - _parameters.rc_acro_th = fabs(_parameters.rc_acro_th); - param_get(_parameter_handles.rc_offboard_th, &(_parameters.rc_offboard_th)); - _parameters.rc_offboard_inv = (_parameters.rc_offboard_th < 0); - _parameters.rc_offboard_th = fabs(_parameters.rc_offboard_th); - - /* update RC function mappings */ - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_THROTTLE] = _parameters.rc_map_throttle - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_ROLL] = _parameters.rc_map_roll - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_PITCH] = _parameters.rc_map_pitch - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_YAW] = _parameters.rc_map_yaw - 1; - - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_MODE] = _parameters.rc_map_mode_sw - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_RETURN] = _parameters.rc_map_return_sw - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_POSCTL] = _parameters.rc_map_posctl_sw - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_LOITER] = _parameters.rc_map_loiter_sw - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_ACRO] = _parameters.rc_map_acro_sw - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_OFFBOARD] = _parameters.rc_map_offboard_sw - 1; - - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_FLAPS] = _parameters.rc_map_flaps - 1; - - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_AUX_1] = _parameters.rc_map_aux1 - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_AUX_2] = _parameters.rc_map_aux2 - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_AUX_3] = _parameters.rc_map_aux3 - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_AUX_4] = _parameters.rc_map_aux4 - 1; - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_AUX_5] = _parameters.rc_map_aux5 - 1; - - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - _rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_PARAM_1 + i] = _parameters.rc_map_param[i] - 1; - } - - /* Airspeed offset */ - param_get(_parameter_handles.diff_pres_offset_pa, &(_parameters.diff_pres_offset_pa)); - param_get(_parameter_handles.diff_pres_analog_scale, &(_parameters.diff_pres_analog_scale)); - - /* scaling of ADC ticks to battery voltage */ - if (param_get(_parameter_handles.battery_voltage_scaling, &(_parameters.battery_voltage_scaling)) != OK) { - warnx("%s", paramerr); - } - - /* scaling of ADC ticks to battery current */ - if (param_get(_parameter_handles.battery_current_scaling, &(_parameters.battery_current_scaling)) != OK) { - warnx("%s", paramerr); - } - - param_get(_parameter_handles.board_rotation, &(_parameters.board_rotation)); - param_get(_parameter_handles.flow_rotation, &(_parameters.flow_rotation)); - - /* set px4flow rotation */ - int flowfd; - flowfd = open(PX4FLOW0_DEVICE_PATH, 0); - - if (flowfd >= 0) { - int flowret = ioctl(flowfd, SENSORIOCSROTATION, _parameters.flow_rotation); - - if (flowret) { - warnx("flow rotation could not be set"); - close(flowfd); - return ERROR; - } - - close(flowfd); - } - - get_rot_matrix((enum Rotation)_parameters.board_rotation, &_board_rotation); - - param_get(_parameter_handles.board_offset[0], &(_parameters.board_offset[0])); - param_get(_parameter_handles.board_offset[1], &(_parameters.board_offset[1])); - param_get(_parameter_handles.board_offset[2], &(_parameters.board_offset[2])); - - /** fine tune board offset on parameter update **/ - math::Matrix<3, 3> board_rotation_offset; - board_rotation_offset.from_euler(M_DEG_TO_RAD_F * _parameters.board_offset[0], - M_DEG_TO_RAD_F * _parameters.board_offset[1], - M_DEG_TO_RAD_F * _parameters.board_offset[2]); - - _board_rotation = _board_rotation * board_rotation_offset; - - /* update barometer qnh setting */ - param_get(_parameter_handles.baro_qnh, &(_parameters.baro_qnh)); - int barofd; - barofd = open(BARO0_DEVICE_PATH, 0); - - if (barofd < 0) { - warnx("ERROR: no barometer foundon %s", BARO0_DEVICE_PATH); - return ERROR; - - } else { - int baroret = ioctl(barofd, BAROIOCSMSLPRESSURE, (unsigned long)(_parameters.baro_qnh * 100)); - - if (baroret) { - warnx("qnh could not be set"); - close(barofd); - return ERROR; - } - - close(barofd); - } - - return OK; -} - -int -Sensors::accel_init() -{ - int fd; - - fd = open(ACCEL0_DEVICE_PATH, 0); - - if (fd < 0) { - warnx("FATAL: no accelerometer found: %s", ACCEL0_DEVICE_PATH); - return ERROR; - - } else { - - /* set the accel internal sampling rate to default rate */ - ioctl(fd, ACCELIOCSSAMPLERATE, ACCEL_SAMPLERATE_DEFAULT); - - /* set the driver to poll at default rate */ - ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT); - - close(fd); - } - - return OK; -} - -int -Sensors::gyro_init() -{ - int fd; - - fd = open(GYRO0_DEVICE_PATH, 0); - - if (fd < 0) { - warnx("FATAL: no gyro found: %s", GYRO0_DEVICE_PATH); - return ERROR; - - } else { - - /* set the gyro internal sampling rate to default rate */ - ioctl(fd, GYROIOCSSAMPLERATE, GYRO_SAMPLERATE_DEFAULT); - - /* set the driver to poll at default rate */ - ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT); - - } - - return OK; -} - -int -Sensors::mag_init() -{ - int fd; - int ret; - - fd = open(MAG0_DEVICE_PATH, 0); - - if (fd < 0) { - warnx("FATAL: no magnetometer found: %s", MAG0_DEVICE_PATH); - return ERROR; - } - - /* try different mag sampling rates */ - - - ret = ioctl(fd, MAGIOCSSAMPLERATE, 150); - - if (ret == OK) { - /* set the pollrate accordingly */ - ioctl(fd, SENSORIOCSPOLLRATE, 150); - - } else { - ret = ioctl(fd, MAGIOCSSAMPLERATE, 100); - - /* if the slower sampling rate still fails, something is wrong */ - if (ret == OK) { - /* set the driver to poll also at the slower rate */ - ioctl(fd, SENSORIOCSPOLLRATE, 100); - - } else { - warnx("FATAL: mag sampling rate could not be set"); - return ERROR; - } - } - - close(fd); - - return OK; -} - -int -Sensors::baro_init() -{ - int fd; - - fd = open(BARO0_DEVICE_PATH, 0); - - if (fd < 0) { - warnx("FATAL: No barometer found: %s", BARO0_DEVICE_PATH); - return ERROR; - } - - /* set the driver to poll at 150Hz */ - ioctl(fd, SENSORIOCSPOLLRATE, 150); - - close(fd); - - return OK; -} - -int -Sensors::adc_init() -{ - - _fd_adc = open(ADC0_DEVICE_PATH, O_RDONLY | O_NONBLOCK); - - if (_fd_adc < 0) { - warnx("FATAL: no ADC found: %s", ADC0_DEVICE_PATH); - return ERROR; - } - - return OK; -} - -void -Sensors::accel_poll(struct sensor_combined_s &raw) -{ - bool accel_updated; - orb_check(_accel_sub, &accel_updated); - - if (accel_updated) { - struct accel_report accel_report; - - orb_copy(ORB_ID(sensor_accel), _accel_sub, &accel_report); - - math::Vector<3> vect(accel_report.x, accel_report.y, accel_report.z); - vect = _board_rotation * vect; - - raw.accelerometer_m_s2[0] = vect(0); - raw.accelerometer_m_s2[1] = vect(1); - raw.accelerometer_m_s2[2] = vect(2); - - raw.accelerometer_raw[0] = accel_report.x_raw; - raw.accelerometer_raw[1] = accel_report.y_raw; - raw.accelerometer_raw[2] = accel_report.z_raw; - - raw.accelerometer_timestamp = accel_report.timestamp; - raw.accelerometer_errcount = accel_report.error_count; - raw.accelerometer_temp = accel_report.temperature; - } - - orb_check(_accel1_sub, &accel_updated); - - if (accel_updated) { - struct accel_report accel_report; - - orb_copy(ORB_ID(sensor_accel), _accel1_sub, &accel_report); - - math::Vector<3> vect(accel_report.x, accel_report.y, accel_report.z); - vect = _board_rotation * vect; - - raw.accelerometer1_m_s2[0] = vect(0); - raw.accelerometer1_m_s2[1] = vect(1); - raw.accelerometer1_m_s2[2] = vect(2); - - raw.accelerometer1_raw[0] = accel_report.x_raw; - raw.accelerometer1_raw[1] = accel_report.y_raw; - raw.accelerometer1_raw[2] = accel_report.z_raw; - - raw.accelerometer1_timestamp = accel_report.timestamp; - raw.accelerometer1_errcount = accel_report.error_count; - raw.accelerometer1_temp = accel_report.temperature; - } - - orb_check(_accel2_sub, &accel_updated); - - if (accel_updated) { - struct accel_report accel_report; - - orb_copy(ORB_ID(sensor_accel), _accel2_sub, &accel_report); - - math::Vector<3> vect(accel_report.x, accel_report.y, accel_report.z); - vect = _board_rotation * vect; - - raw.accelerometer2_m_s2[0] = vect(0); - raw.accelerometer2_m_s2[1] = vect(1); - raw.accelerometer2_m_s2[2] = vect(2); - - raw.accelerometer2_raw[0] = accel_report.x_raw; - raw.accelerometer2_raw[1] = accel_report.y_raw; - raw.accelerometer2_raw[2] = accel_report.z_raw; - - raw.accelerometer2_timestamp = accel_report.timestamp; - raw.accelerometer2_errcount = accel_report.error_count; - raw.accelerometer2_temp = accel_report.temperature; - } -} - -void -Sensors::gyro_poll(struct sensor_combined_s &raw) -{ - bool gyro_updated; - orb_check(_gyro_sub, &gyro_updated); - - if (gyro_updated) { - struct gyro_report gyro_report; - - orb_copy(ORB_ID(sensor_gyro), _gyro_sub, &gyro_report); - - math::Vector<3> vect(gyro_report.x, gyro_report.y, gyro_report.z); - vect = _board_rotation * vect; - - raw.gyro_rad_s[0] = vect(0); - raw.gyro_rad_s[1] = vect(1); - raw.gyro_rad_s[2] = vect(2); - - raw.gyro_raw[0] = gyro_report.x_raw; - raw.gyro_raw[1] = gyro_report.y_raw; - raw.gyro_raw[2] = gyro_report.z_raw; - - raw.timestamp = gyro_report.timestamp; - raw.gyro_errcount = gyro_report.error_count; - raw.gyro_temp = gyro_report.temperature; - } - - orb_check(_gyro1_sub, &gyro_updated); - - if (gyro_updated) { - struct gyro_report gyro_report; - - orb_copy(ORB_ID(sensor_gyro), _gyro1_sub, &gyro_report); - - math::Vector<3> vect(gyro_report.x, gyro_report.y, gyro_report.z); - vect = _board_rotation * vect; - - raw.gyro1_rad_s[0] = vect(0); - raw.gyro1_rad_s[1] = vect(1); - raw.gyro1_rad_s[2] = vect(2); - - raw.gyro1_raw[0] = gyro_report.x_raw; - raw.gyro1_raw[1] = gyro_report.y_raw; - raw.gyro1_raw[2] = gyro_report.z_raw; - - raw.gyro1_timestamp = gyro_report.timestamp; - raw.gyro1_errcount = gyro_report.error_count; - raw.gyro1_temp = gyro_report.temperature; - } - - orb_check(_gyro2_sub, &gyro_updated); - - if (gyro_updated) { - struct gyro_report gyro_report; - - orb_copy(ORB_ID(sensor_gyro), _gyro2_sub, &gyro_report); - - math::Vector<3> vect(gyro_report.x, gyro_report.y, gyro_report.z); - vect = _board_rotation * vect; - - raw.gyro2_rad_s[0] = vect(0); - raw.gyro2_rad_s[1] = vect(1); - raw.gyro2_rad_s[2] = vect(2); - - raw.gyro2_raw[0] = gyro_report.x_raw; - raw.gyro2_raw[1] = gyro_report.y_raw; - raw.gyro2_raw[2] = gyro_report.z_raw; - - raw.gyro2_timestamp = gyro_report.timestamp; - raw.gyro2_errcount = gyro_report.error_count; - raw.gyro2_temp = gyro_report.temperature; - } -} - -void -Sensors::mag_poll(struct sensor_combined_s &raw) -{ - bool mag_updated; - orb_check(_mag_sub, &mag_updated); - - if (mag_updated) { - struct mag_report mag_report; - - orb_copy(ORB_ID(sensor_mag), _mag_sub, &mag_report); - - math::Vector<3> vect(mag_report.x, mag_report.y, mag_report.z); - - vect = _mag_rotation[0] * vect; - - raw.magnetometer_ga[0] = vect(0); - raw.magnetometer_ga[1] = vect(1); - raw.magnetometer_ga[2] = vect(2); - - raw.magnetometer_raw[0] = mag_report.x_raw; - raw.magnetometer_raw[1] = mag_report.y_raw; - raw.magnetometer_raw[2] = mag_report.z_raw; - - raw.magnetometer_timestamp = mag_report.timestamp; - raw.magnetometer_errcount = mag_report.error_count; - raw.magnetometer_temp = mag_report.temperature; - } - - orb_check(_mag1_sub, &mag_updated); - - if (mag_updated) { - struct mag_report mag_report; - - orb_copy(ORB_ID(sensor_mag), _mag1_sub, &mag_report); - - math::Vector<3> vect(mag_report.x, mag_report.y, mag_report.z); - - vect = _mag_rotation[1] * vect; - - raw.magnetometer1_ga[0] = vect(0); - raw.magnetometer1_ga[1] = vect(1); - raw.magnetometer1_ga[2] = vect(2); - - raw.magnetometer1_raw[0] = mag_report.x_raw; - raw.magnetometer1_raw[1] = mag_report.y_raw; - raw.magnetometer1_raw[2] = mag_report.z_raw; - - raw.magnetometer1_timestamp = mag_report.timestamp; - raw.magnetometer1_errcount = mag_report.error_count; - raw.magnetometer1_temp = mag_report.temperature; - } - - orb_check(_mag2_sub, &mag_updated); - - if (mag_updated) { - struct mag_report mag_report; - - orb_copy(ORB_ID(sensor_mag), _mag2_sub, &mag_report); - - math::Vector<3> vect(mag_report.x, mag_report.y, mag_report.z); - - vect = _mag_rotation[2] * vect; - - raw.magnetometer2_ga[0] = vect(0); - raw.magnetometer2_ga[1] = vect(1); - raw.magnetometer2_ga[2] = vect(2); - - raw.magnetometer2_raw[0] = mag_report.x_raw; - raw.magnetometer2_raw[1] = mag_report.y_raw; - raw.magnetometer2_raw[2] = mag_report.z_raw; - - raw.magnetometer2_timestamp = mag_report.timestamp; - raw.magnetometer2_errcount = mag_report.error_count; - raw.magnetometer2_temp = mag_report.temperature; - } -} - -void -Sensors::baro_poll(struct sensor_combined_s &raw) -{ - bool baro_updated; - orb_check(_baro_sub, &baro_updated); - - if (baro_updated) { - - orb_copy(ORB_ID(sensor_baro), _baro_sub, &_barometer); - - raw.baro_pres_mbar = _barometer.pressure; // Pressure in mbar - raw.baro_alt_meter = _barometer.altitude; // Altitude in meters - raw.baro_temp_celcius = _barometer.temperature; // Temperature in degrees celcius - - raw.baro_timestamp = _barometer.timestamp; - } - - orb_check(_baro1_sub, &baro_updated); - - if (baro_updated) { - - struct baro_report baro_report; - - orb_copy(ORB_ID(sensor_baro), _baro1_sub, &baro_report); - - raw.baro1_pres_mbar = baro_report.pressure; // Pressure in mbar - raw.baro1_alt_meter = baro_report.altitude; // Altitude in meters - raw.baro1_temp_celcius = baro_report.temperature; // Temperature in degrees celcius - - raw.baro1_timestamp = baro_report.timestamp; - } -} - -void -Sensors::diff_pres_poll(struct sensor_combined_s &raw) -{ - bool updated; - orb_check(_diff_pres_sub, &updated); - - if (updated) { - orb_copy(ORB_ID(differential_pressure), _diff_pres_sub, &_diff_pres); - - raw.differential_pressure_pa = _diff_pres.differential_pressure_raw_pa; - raw.differential_pressure_timestamp = _diff_pres.timestamp; - raw.differential_pressure_filtered_pa = _diff_pres.differential_pressure_filtered_pa; - - float air_temperature_celsius = (_diff_pres.temperature > -300.0f) ? _diff_pres.temperature : - (raw.baro_temp_celcius - PCB_TEMP_ESTIMATE_DEG); - - _airspeed.timestamp = _diff_pres.timestamp; - - /* don't risk to feed negative airspeed into the system */ - _airspeed.indicated_airspeed_m_s = math::max(0.0f, - calc_indicated_airspeed(_diff_pres.differential_pressure_filtered_pa)); - _airspeed.true_airspeed_m_s = math::max(0.0f, - calc_true_airspeed(_diff_pres.differential_pressure_filtered_pa + raw.baro_pres_mbar * 1e2f, - raw.baro_pres_mbar * 1e2f, air_temperature_celsius)); - _airspeed.air_temperature_celsius = air_temperature_celsius; - - /* announce the airspeed if needed, just publish else */ - if (_airspeed_pub > 0) { - orb_publish(ORB_ID(airspeed), _airspeed_pub, &_airspeed); - - } else { - _airspeed_pub = orb_advertise(ORB_ID(airspeed), &_airspeed); - } - } -} - -void -Sensors::vehicle_control_mode_poll() -{ - struct vehicle_control_mode_s vcontrol_mode; - bool vcontrol_mode_updated; - - /* Check HIL state if vehicle control mode has changed */ - orb_check(_vcontrol_mode_sub, &vcontrol_mode_updated); - - if (vcontrol_mode_updated) { - - orb_copy(ORB_ID(vehicle_control_mode), _vcontrol_mode_sub, &vcontrol_mode); - - /* switching from non-HIL to HIL mode */ - //printf("[sensors] Vehicle mode: %i \t AND: %i, HIL: %i\n", vstatus.mode, vstatus.mode & VEHICLE_MODE_FLAG_HIL_ENABLED, hil_enabled); - if (vcontrol_mode.flag_system_hil_enabled && !_hil_enabled) { - _hil_enabled = true; - _publishing = false; - - /* switching from HIL to non-HIL mode */ - - } else if (!_publishing && !_hil_enabled) { - _hil_enabled = false; - _publishing = true; - } - } -} - -void -Sensors::parameter_update_poll(bool forced) -{ - bool param_updated; - - /* Check if any parameter has changed */ - orb_check(_params_sub, ¶m_updated); - - if (param_updated || forced) { - /* read from param to clear updated flag */ - struct parameter_update_s update; - orb_copy(ORB_ID(parameter_update), _params_sub, &update); - - /* update parameters */ - parameters_update(); - - /* set offset parameters to new values */ - bool failed; - int res; - char str[30]; - unsigned mag_count = 0; - unsigned gyro_count = 0; - unsigned accel_count = 0; - - /* run through all gyro sensors */ - for (unsigned s = 0; s < 3; s++) { - - res = ERROR; - (void)sprintf(str, "%s%u", GYRO_BASE_DEVICE_PATH, s); - - int fd = open(str, 0); - - if (fd < 0) { - continue; - } - - bool config_ok = false; - - /* run through all stored calibrations */ - for (unsigned i = 0; i < 3; i++) { - /* initially status is ok per config */ - failed = false; - - (void)sprintf(str, "CAL_GYRO%u_ID", i); - int device_id; - failed = failed || (OK != param_get(param_find(str), &device_id)); - - if (failed) { - close(fd); - continue; - } - - /* if the calibration is for this device, apply it */ - if (device_id == ioctl(fd, DEVIOCGDEVICEID, 0)) { - struct gyro_scale gscale = {}; - (void)sprintf(str, "CAL_GYRO%u_XOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_offset)); - (void)sprintf(str, "CAL_GYRO%u_YOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_offset)); - (void)sprintf(str, "CAL_GYRO%u_ZOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_offset)); - (void)sprintf(str, "CAL_GYRO%u_XSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_scale)); - (void)sprintf(str, "CAL_GYRO%u_YSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_scale)); - (void)sprintf(str, "CAL_GYRO%u_ZSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_scale)); - - if (failed) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "gyro", i); - } else { - /* apply new scaling and offsets */ - res = ioctl(fd, GYROIOCSSCALE, (long unsigned int)&gscale); - if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "gyro", i); - } else { - config_ok = true; - } - } - break; - } - } - - if (config_ok) { - gyro_count++; - } - - close(fd); - } - - /* run through all accel sensors */ - for (unsigned s = 0; s < 3; s++) { - - res = ERROR; - (void)sprintf(str, "%s%u", ACCEL_BASE_DEVICE_PATH, s); - - int fd = open(str, 0); - - if (fd < 0) { - continue; - } - - bool config_ok = false; - - /* run through all stored calibrations */ - for (unsigned i = 0; i < 3; i++) { - /* initially status is ok per config */ - failed = false; - - (void)sprintf(str, "CAL_ACC%u_ID", i); - int device_id; - failed = failed || (OK != param_get(param_find(str), &device_id)); - - if (failed) { - close(fd); - continue; - } - - /* if the calibration is for this device, apply it */ - if (device_id == ioctl(fd, DEVIOCGDEVICEID, 0)) { - struct accel_scale gscale = {}; - (void)sprintf(str, "CAL_ACC%u_XOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_offset)); - (void)sprintf(str, "CAL_ACC%u_YOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_offset)); - (void)sprintf(str, "CAL_ACC%u_ZOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_offset)); - (void)sprintf(str, "CAL_ACC%u_XSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_scale)); - (void)sprintf(str, "CAL_ACC%u_YSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_scale)); - (void)sprintf(str, "CAL_ACC%u_ZSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_scale)); - - if (failed) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "accel", i); - } else { - /* apply new scaling and offsets */ - res = ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&gscale); - if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "accel", i); - } else { - config_ok = true; - } - } - break; - } - } - - if (config_ok) { - accel_count++; - } - - close(fd); - } - - /* run through all mag sensors */ - for (unsigned s = 0; s < 3; s++) { - - res = ERROR; - (void)sprintf(str, "%s%u", MAG_BASE_DEVICE_PATH, s); - - int fd = open(str, 0); - - if (fd < 0) { - /* the driver is not running, abort */ - continue; - } - - /* set a valid default rotation (same as board). - * if the mag is configured, this might be replaced - * in the section below. - */ - _mag_rotation[s] = _board_rotation; - - bool config_ok = false; - - /* run through all stored calibrations */ - for (unsigned i = 0; i < 3; i++) { - /* initially status is ok per config */ - failed = false; - - (void)sprintf(str, "CAL_MAG%u_ID", i); - int device_id; - failed = failed || (OK != param_get(param_find(str), &device_id)); - - if (failed) { - close(fd); - continue; - } - - /* if the calibration is for this device, apply it */ - if (device_id == ioctl(fd, DEVIOCGDEVICEID, 0)) { - struct mag_scale gscale = {}; - (void)sprintf(str, "CAL_MAG%u_XOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_offset)); - (void)sprintf(str, "CAL_MAG%u_YOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_offset)); - (void)sprintf(str, "CAL_MAG%u_ZOFF", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_offset)); - (void)sprintf(str, "CAL_MAG%u_XSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.x_scale)); - (void)sprintf(str, "CAL_MAG%u_YSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.y_scale)); - (void)sprintf(str, "CAL_MAG%u_ZSCALE", i); - failed = failed || (OK != param_get(param_find(str), &gscale.z_scale)); - - (void)sprintf(str, "CAL_MAG%u_ROT", i); - - if (ioctl(fd, MAGIOCGEXTERNAL, 0) <= 0) { - /* mag is internal */ - _mag_rotation[s] = _board_rotation; - /* reset param to -1 to indicate internal mag */ - int32_t minus_one = MAG_ROT_VAL_INTERNAL; - param_set_no_notification(param_find(str), &minus_one); - } else { - - int32_t mag_rot; - param_get(param_find(str), &mag_rot); - - /* check if this mag is still set as internal */ - if (mag_rot < 0) { - /* it was marked as internal, change to external with no rotation */ - mag_rot = 0; - param_set_no_notification(param_find(str), &mag_rot); - } - - /* handling of old setups, will be removed later (noted Feb 2015) */ - int32_t deprecated_mag_rot = 0; - param_get(param_find("SENS_EXT_MAG_ROT"), &deprecated_mag_rot); - - /* - * If the deprecated parameter is non-default (is != 0), - * and the new parameter is default (is == 0), then this board - * was configured already and we need to copy the old value - * to the new parameter. - * The < 0 case is special: It means that this param slot was - * used previously by an internal sensor, but the the call above - * proved that it is currently occupied by an external sensor. - * In that case we consider the orientation to be default as well. - */ - if ((deprecated_mag_rot != 0) && (mag_rot <= 0)) { - mag_rot = deprecated_mag_rot; - param_set_no_notification(param_find(str), &mag_rot); - /* clear the old param, not supported in GUI anyway */ - deprecated_mag_rot = 0; - param_set_no_notification(param_find("SENS_EXT_MAG_ROT"), &deprecated_mag_rot); - } - - /* handling of transition from internal to external */ - if (mag_rot < 0) { - mag_rot = 0; - } - - get_rot_matrix((enum Rotation)mag_rot, &_mag_rotation[s]); - } - - if (failed) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "mag", i); - } else { - /* apply new scaling and offsets */ - res = ioctl(fd, MAGIOCSSCALE, (long unsigned int)&gscale); - if (res) { - warnx(CAL_FAILED_APPLY_CAL_MSG, "mag", i); - } else { - config_ok = true; - } - } - break; - } - } - - if (config_ok) { - mag_count++; - } - - close(fd); - } - - int fd = open(AIRSPEED0_DEVICE_PATH, 0); - - /* this sensor is optional, abort without error */ - - if (fd >= 0) { - struct airspeed_scale airscale = { - _parameters.diff_pres_offset_pa, - 1.0f, - }; - - if (OK != ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) { - warn("WARNING: failed to set scale / offsets for airspeed sensor"); - } - - close(fd); - } - - warnx("valid configs: %u gyros, %u mags, %u accels", gyro_count, mag_count, accel_count); - } -} - -void -Sensors::rc_parameter_map_poll(bool forced) -{ - bool map_updated; - orb_check(_rc_parameter_map_sub, &map_updated); - - if (map_updated) { - orb_copy(ORB_ID(rc_parameter_map), _rc_parameter_map_sub, &_rc_parameter_map); - - /* update paramter handles to which the RC channels are mapped */ - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - if (_rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_PARAM_1 + i] < 0 || !_rc_parameter_map.valid[i]) { - /* This RC channel is not mapped to a RC-Parameter Channel (e.g. RC_MAP_PARAM1 == 0) - * or no request to map this channel to a param has been sent via mavlink - */ - continue; - } - - /* Set the handle by index if the index is set, otherwise use the id */ - if (_rc_parameter_map.param_index[i] >= 0) { - _parameter_handles.rc_param[i] = param_for_index((unsigned)_rc_parameter_map.param_index[i]); - - } else { - _parameter_handles.rc_param[i] = param_find(_rc_parameter_map.param_id[i]); - } - - } - - warnx("rc to parameter map updated"); - - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - warnx("\ti %d param_id %s scale %.3f value0 %.3f, min %.3f, max %.3f", - i, - _rc_parameter_map.param_id[i], - (double)_rc_parameter_map.scale[i], - (double)_rc_parameter_map.value0[i], - (double)_rc_parameter_map.value_min[i], - (double)_rc_parameter_map.value_max[i] - ); - } - } -} - -void -Sensors::adc_poll(struct sensor_combined_s &raw) -{ - /* only read if publishing */ - if (!_publishing) { - return; - } - - hrt_abstime t = hrt_absolute_time(); - - /* rate limit to 100 Hz */ - if (t - _last_adc >= 10000) { - /* make space for a maximum of twelve channels (to ensure reading all channels at once) */ - struct adc_msg_s buf_adc[12]; - /* read all channels available */ - int ret = read(_fd_adc, &buf_adc, sizeof(buf_adc)); - - if (ret >= (int)sizeof(buf_adc[0])) { - - /* Read add channels we got */ - for (unsigned i = 0; i < ret / sizeof(buf_adc[0]); i++) { - /* Save raw voltage values */ - if (i < (sizeof(raw.adc_voltage_v) / sizeof(raw.adc_voltage_v[0]))) { - raw.adc_voltage_v[i] = buf_adc[i].am_data / (4096.0f / 3.3f); - raw.adc_mapping[i] = buf_adc[i].am_channel; - } - - /* look for specific channels and process the raw voltage to measurement data */ - if (ADC_BATTERY_VOLTAGE_CHANNEL == buf_adc[i].am_channel) { - /* Voltage in volts */ - float voltage = (buf_adc[i].am_data * _parameters.battery_voltage_scaling); - - if (voltage > BATT_V_IGNORE_THRESHOLD) { - _battery_status.voltage_v = voltage; - - /* one-time initialization of low-pass value to avoid long init delays */ - if (_battery_status.voltage_filtered_v < BATT_V_IGNORE_THRESHOLD) { - _battery_status.voltage_filtered_v = voltage; - } - - _battery_status.timestamp = t; - _battery_status.voltage_filtered_v += (voltage - _battery_status.voltage_filtered_v) * BATT_V_LOWPASS; - - } else { - /* mark status as invalid */ - _battery_status.voltage_v = -1.0f; - _battery_status.voltage_filtered_v = -1.0f; - } - - } else if (ADC_BATTERY_CURRENT_CHANNEL == buf_adc[i].am_channel) { - /* handle current only if voltage is valid */ - if (_battery_status.voltage_v > 0.0f) { - float current = (buf_adc[i].am_data * _parameters.battery_current_scaling); - - /* check measured current value */ - if (current >= 0.0f) { - _battery_status.timestamp = t; - _battery_status.current_a = current; - - if (_battery_current_timestamp != 0) { - /* initialize discharged value */ - if (_battery_status.discharged_mah < 0.0f) { - _battery_status.discharged_mah = 0.0f; - } - - _battery_discharged += current * (t - _battery_current_timestamp); - _battery_status.discharged_mah = ((float) _battery_discharged) / 3600000.0f; - } - } - } - - _battery_current_timestamp = t; - - } else if (ADC_AIRSPEED_VOLTAGE_CHANNEL == buf_adc[i].am_channel) { - - /* calculate airspeed, raw is the difference from */ - float voltage = (float)(buf_adc[i].am_data) * 3.3f / 4096.0f * 2.0f; // V_ref/4096 * (voltage divider factor) - - /** - * The voltage divider pulls the signal down, only act on - * a valid voltage from a connected sensor. Also assume a non- - * zero offset from the sensor if its connected. - */ - if (voltage > 0.4f && (_parameters.diff_pres_analog_scale > 0.0f)) { - - float diff_pres_pa_raw = voltage * _parameters.diff_pres_analog_scale - _parameters.diff_pres_offset_pa; - - _diff_pres.timestamp = t; - _diff_pres.differential_pressure_raw_pa = diff_pres_pa_raw; - _diff_pres.differential_pressure_filtered_pa = (_diff_pres.differential_pressure_filtered_pa * 0.9f) + - (diff_pres_pa_raw * 0.1f); - _diff_pres.temperature = -1000.0f; - - /* announce the airspeed if needed, just publish else */ - if (_diff_pres_pub > 0) { - orb_publish(ORB_ID(differential_pressure), _diff_pres_pub, &_diff_pres); - - } else { - _diff_pres_pub = orb_advertise(ORB_ID(differential_pressure), &_diff_pres); - } - } - } - } - - _last_adc = t; - - if (_battery_status.voltage_filtered_v > BATT_V_IGNORE_THRESHOLD) { - /* announce the battery status if needed, just publish else */ - if (_battery_pub > 0) { - orb_publish(ORB_ID(battery_status), _battery_pub, &_battery_status); - - } else { - _battery_pub = orb_advertise(ORB_ID(battery_status), &_battery_status); - } - } - } - } -} - -float -Sensors::get_rc_value(uint8_t func, float min_value, float max_value) -{ - if (_rc.function[func] >= 0) { - float value = _rc.channels[_rc.function[func]]; - - if (value < min_value) { - return min_value; - - } else if (value > max_value) { - return max_value; - - } else { - return value; - } - - } else { - return 0.0f; - } -} - -switch_pos_t -Sensors::get_rc_sw3pos_position(uint8_t func, float on_th, bool on_inv, float mid_th, bool mid_inv) -{ - if (_rc.function[func] >= 0) { - float value = 0.5f * _rc.channels[_rc.function[func]] + 0.5f; - - if (on_inv ? value < on_th : value > on_th) { - return manual_control_setpoint_s::SWITCH_POS_ON; - - } else if (mid_inv ? value < mid_th : value > mid_th) { - return manual_control_setpoint_s::SWITCH_POS_MIDDLE; - - } else { - return manual_control_setpoint_s::SWITCH_POS_OFF; - } - - } else { - return manual_control_setpoint_s::SWITCH_POS_NONE; - } -} - -switch_pos_t -Sensors::get_rc_sw2pos_position(uint8_t func, float on_th, bool on_inv) -{ - if (_rc.function[func] >= 0) { - float value = 0.5f * _rc.channels[_rc.function[func]] + 0.5f; - - if (on_inv ? value < on_th : value > on_th) { - return manual_control_setpoint_s::SWITCH_POS_ON; - - } else { - return manual_control_setpoint_s::SWITCH_POS_OFF; - } - - } else { - return manual_control_setpoint_s::SWITCH_POS_NONE; - } -} - -void -Sensors::set_params_from_rc() -{ - static float param_rc_values[RC_PARAM_MAP_NCHAN] = {}; - - for (int i = 0; i < RC_PARAM_MAP_NCHAN; i++) { - if (_rc.function[rc_channels_s::RC_CHANNELS_FUNCTION_PARAM_1 + i] < 0 || !_rc_parameter_map.valid[i]) { - /* This RC channel is not mapped to a RC-Parameter Channel (e.g. RC_MAP_PARAM1 == 0) - * or no request to map this channel to a param has been sent via mavlink - */ - continue; - } - - float rc_val = get_rc_value((rc_channels_s::RC_CHANNELS_FUNCTION_PARAM_1 + i), -1.0, 1.0); - /* Check if the value has changed, - * maybe we need to introduce a more aggressive limit here */ - if (rc_val > param_rc_values[i] + FLT_EPSILON || rc_val < param_rc_values[i] - FLT_EPSILON) { - param_rc_values[i] = rc_val; - float param_val = math::constrain( - _rc_parameter_map.value0[i] + _rc_parameter_map.scale[i] * rc_val, - _rc_parameter_map.value_min[i], _rc_parameter_map.value_max[i]); - param_set(_parameter_handles.rc_param[i], ¶m_val); - } - } -} - -void -Sensors::rc_poll() -{ - bool rc_updated; - orb_check(_rc_sub, &rc_updated); - - if (rc_updated) { - /* read low-level values from FMU or IO RC inputs (PPM, Spektrum, S.Bus) */ - struct rc_input_values rc_input; - - orb_copy(ORB_ID(input_rc), _rc_sub, &rc_input); - - /* detect RC signal loss */ - bool signal_lost; - - /* check flags and require at least four channels to consider the signal valid */ - if (rc_input.rc_lost || rc_input.rc_failsafe || rc_input.channel_count < 4) { - /* signal is lost or no enough channels */ - signal_lost = true; - - } else { - /* signal looks good */ - signal_lost = false; - - /* check failsafe */ - int8_t fs_ch = _rc.function[_parameters.rc_map_failsafe]; // get channel mapped to throttle - - if (_parameters.rc_map_failsafe > 0) { // if not 0, use channel number instead of rc.function mapping - fs_ch = _parameters.rc_map_failsafe - 1; - } - - if (_parameters.rc_fails_thr > 0 && fs_ch >= 0) { - /* failsafe configured */ - if ((_parameters.rc_fails_thr < _parameters.min[fs_ch] && rc_input.values[fs_ch] < _parameters.rc_fails_thr) || - (_parameters.rc_fails_thr > _parameters.max[fs_ch] && rc_input.values[fs_ch] > _parameters.rc_fails_thr)) { - /* failsafe triggered, signal is lost by receiver */ - signal_lost = true; - } - } - } - - unsigned channel_limit = rc_input.channel_count; - - if (channel_limit > _rc_max_chan_count) { - channel_limit = _rc_max_chan_count; - } - - /* read out and scale values from raw message even if signal is invalid */ - for (unsigned int i = 0; i < channel_limit; i++) { - - /* - * 1) Constrain to min/max values, as later processing depends on bounds. - */ - if (rc_input.values[i] < _parameters.min[i]) { - rc_input.values[i] = _parameters.min[i]; - } - - if (rc_input.values[i] > _parameters.max[i]) { - rc_input.values[i] = _parameters.max[i]; - } - - /* - * 2) Scale around the mid point differently for lower and upper range. - * - * This is necessary as they don't share the same endpoints and slope. - * - * First normalize to 0..1 range with correct sign (below or above center), - * the total range is 2 (-1..1). - * If center (trim) == min, scale to 0..1, if center (trim) == max, - * scale to -1..0. - * - * As the min and max bounds were enforced in step 1), division by zero - * cannot occur, as for the case of center == min or center == max the if - * statement is mutually exclusive with the arithmetic NaN case. - * - * DO NOT REMOVE OR ALTER STEP 1! - */ - if (rc_input.values[i] > (_parameters.trim[i] + _parameters.dz[i])) { - _rc.channels[i] = (rc_input.values[i] - _parameters.trim[i] - _parameters.dz[i]) / (float)( - _parameters.max[i] - _parameters.trim[i] - _parameters.dz[i]); - - } else if (rc_input.values[i] < (_parameters.trim[i] - _parameters.dz[i])) { - _rc.channels[i] = (rc_input.values[i] - _parameters.trim[i] + _parameters.dz[i]) / (float)( - _parameters.trim[i] - _parameters.min[i] - _parameters.dz[i]); - - } else { - /* in the configured dead zone, output zero */ - _rc.channels[i] = 0.0f; - } - - _rc.channels[i] *= _parameters.rev[i]; - - /* handle any parameter-induced blowups */ - if (!isfinite(_rc.channels[i])) { - _rc.channels[i] = 0.0f; - } - } - - _rc.channel_count = rc_input.channel_count; - _rc.rssi = rc_input.rssi; - _rc.signal_lost = signal_lost; - _rc.timestamp = rc_input.timestamp_last_signal; - - /* publish rc_channels topic even if signal is invalid, for debug */ - if (_rc_pub > 0) { - orb_publish(ORB_ID(rc_channels), _rc_pub, &_rc); - - } else { - _rc_pub = orb_advertise(ORB_ID(rc_channels), &_rc); - } - - if (!signal_lost) { - struct manual_control_setpoint_s manual; - memset(&manual, 0 , sizeof(manual)); - - /* fill values in manual_control_setpoint topic only if signal is valid */ - manual.timestamp = rc_input.timestamp_last_signal; - - /* limit controls */ - manual.y = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_ROLL, -1.0, 1.0); - manual.x = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_PITCH, -1.0, 1.0); - manual.r = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_YAW, -1.0, 1.0); - manual.z = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_THROTTLE, 0.0, 1.0); - manual.flaps = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_FLAPS, -1.0, 1.0); - manual.aux1 = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_AUX_1, -1.0, 1.0); - manual.aux2 = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_AUX_2, -1.0, 1.0); - manual.aux3 = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_AUX_3, -1.0, 1.0); - manual.aux4 = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_AUX_4, -1.0, 1.0); - manual.aux5 = get_rc_value (rc_channels_s::RC_CHANNELS_FUNCTION_AUX_5, -1.0, 1.0); - - /* mode switches */ - manual.mode_switch = get_rc_sw3pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_MODE, _parameters.rc_auto_th, _parameters.rc_auto_inv, _parameters.rc_assist_th, _parameters.rc_assist_inv); - manual.posctl_switch = get_rc_sw2pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_POSCTL, _parameters.rc_posctl_th, _parameters.rc_posctl_inv); - manual.return_switch = get_rc_sw2pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_RETURN, _parameters.rc_return_th, _parameters.rc_return_inv); - manual.loiter_switch = get_rc_sw2pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_LOITER, _parameters.rc_loiter_th, _parameters.rc_loiter_inv); - manual.acro_switch = get_rc_sw2pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_ACRO, _parameters.rc_acro_th, _parameters.rc_acro_inv); - manual.offboard_switch = get_rc_sw2pos_position (rc_channels_s::RC_CHANNELS_FUNCTION_OFFBOARD, _parameters.rc_offboard_th, _parameters.rc_offboard_inv); - - /* publish manual_control_setpoint topic */ - if (_manual_control_pub > 0) { - orb_publish(ORB_ID(manual_control_setpoint), _manual_control_pub, &manual); - - } else { - _manual_control_pub = orb_advertise(ORB_ID(manual_control_setpoint), &manual); - } - - /* copy from mapped manual control to control group 3 */ - struct actuator_controls_s actuator_group_3; - memset(&actuator_group_3, 0 , sizeof(actuator_group_3)); - - actuator_group_3.timestamp = rc_input.timestamp_last_signal; - - actuator_group_3.control[0] = manual.y; - actuator_group_3.control[1] = manual.x; - actuator_group_3.control[2] = manual.r; - actuator_group_3.control[3] = manual.z; - actuator_group_3.control[4] = manual.flaps; - actuator_group_3.control[5] = manual.aux1; - actuator_group_3.control[6] = manual.aux2; - actuator_group_3.control[7] = manual.aux3; - - /* publish actuator_controls_3 topic */ - if (_actuator_group_3_pub > 0) { - orb_publish(ORB_ID(actuator_controls_3), _actuator_group_3_pub, &actuator_group_3); - - } else { - _actuator_group_3_pub = orb_advertise(ORB_ID(actuator_controls_3), &actuator_group_3); - } - - /* Update parameters from RC Channels (tuning with RC) if activated */ - static hrt_abstime last_rc_to_param_map_time = 0; - - if (hrt_elapsed_time(&last_rc_to_param_map_time) > 1e6) { - set_params_from_rc(); - last_rc_to_param_map_time = hrt_absolute_time(); - } - } - } -} - -void -Sensors::task_main_trampoline(int argc, char *argv[]) -{ - sensors::g_sensors->task_main(); -} - -void -Sensors::task_main() -{ - - /* start individual sensors */ - int ret; - ret = accel_init(); - - if (ret) { - goto exit_immediate; - } - - ret = gyro_init(); - - if (ret) { - goto exit_immediate; - } - - ret = mag_init(); - - if (ret) { - goto exit_immediate; - } - - ret = baro_init(); - - if (ret) { - goto exit_immediate; - } - - ret = adc_init(); - - if (ret) { - goto exit_immediate; - } - - /* - * do subscriptions - */ - _gyro_sub = orb_subscribe_multi(ORB_ID(sensor_gyro), 0); - _accel_sub = orb_subscribe_multi(ORB_ID(sensor_accel), 0); - _mag_sub = orb_subscribe_multi(ORB_ID(sensor_mag), 0); - _gyro1_sub = orb_subscribe_multi(ORB_ID(sensor_gyro), 1); - _accel1_sub = orb_subscribe_multi(ORB_ID(sensor_accel), 1); - _mag1_sub = orb_subscribe_multi(ORB_ID(sensor_mag), 1); - _gyro2_sub = orb_subscribe_multi(ORB_ID(sensor_gyro), 2); - _accel2_sub = orb_subscribe_multi(ORB_ID(sensor_accel), 2); - _mag2_sub = orb_subscribe_multi(ORB_ID(sensor_mag), 2); - _rc_sub = orb_subscribe(ORB_ID(input_rc)); - _baro_sub = orb_subscribe_multi(ORB_ID(sensor_baro), 0); - _baro1_sub = orb_subscribe_multi(ORB_ID(sensor_baro), 1); - _diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure)); - _vcontrol_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode)); - _params_sub = orb_subscribe(ORB_ID(parameter_update)); - _rc_parameter_map_sub = orb_subscribe(ORB_ID(rc_parameter_map)); - _manual_control_sub = orb_subscribe(ORB_ID(manual_control_setpoint)); - - /* rate limit vehicle status updates to 5Hz */ - orb_set_interval(_vcontrol_mode_sub, 200); - - /* rate limit gyro to 250 Hz (the gyro signal is lowpassed accordingly earlier) */ - orb_set_interval(_gyro_sub, 4); - - /* - * do advertisements - */ - struct sensor_combined_s raw; - memset(&raw, 0, sizeof(raw)); - raw.timestamp = hrt_absolute_time(); - raw.adc_voltage_v[0] = 0.0f; - raw.adc_voltage_v[1] = 0.0f; - raw.adc_voltage_v[2] = 0.0f; - raw.adc_voltage_v[3] = 0.0f; - - /* set high initial error counts to deselect gyros */ - raw.gyro_errcount = 100000; - raw.gyro1_errcount = 100000; - raw.gyro2_errcount = 100000; - - /* set high initial error counts to deselect accels */ - raw.accelerometer_errcount = 100000; - raw.accelerometer1_errcount = 100000; - raw.accelerometer2_errcount = 100000; - - /* set high initial error counts to deselect mags */ - raw.magnetometer_errcount = 100000; - raw.magnetometer1_errcount = 100000; - raw.magnetometer2_errcount = 100000; - - memset(&_battery_status, 0, sizeof(_battery_status)); - _battery_status.voltage_v = -1.0f; - _battery_status.voltage_filtered_v = -1.0f; - _battery_status.current_a = -1.0f; - _battery_status.discharged_mah = -1.0f; - - /* get a set of initial values */ - accel_poll(raw); - gyro_poll(raw); - mag_poll(raw); - baro_poll(raw); - diff_pres_poll(raw); - - parameter_update_poll(true /* forced */); - rc_parameter_map_poll(true /* forced */); - - /* advertise the sensor_combined topic and make the initial publication */ - _sensor_pub = orb_advertise(ORB_ID(sensor_combined), &raw); - - /* wakeup source(s) */ - struct pollfd fds[1]; - - /* use the gyro to pace output - XXX BROKEN if we are using the L3GD20 */ - fds[0].fd = _gyro_sub; - fds[0].events = POLLIN; - - _task_should_exit = false; - - while (!_task_should_exit) { - - /* wait for up to 50ms for data */ - int pret = poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 50); - - /* if pret == 0 it timed out - periodic check for _task_should_exit, etc. */ - - /* this is undesirable but not much we can do - might want to flag unhappy status */ - if (pret < 0) { - warn("poll error %d, %d", pret, errno); - continue; - } - - perf_begin(_loop_perf); - - /* check vehicle status for changes to publication state */ - vehicle_control_mode_poll(); - - /* the timestamp of the raw struct is updated by the gyro_poll() method */ - /* copy most recent sensor data */ - gyro_poll(raw); - accel_poll(raw); - mag_poll(raw); - baro_poll(raw); - - /* work out if main gyro timed out and fail over to alternate gyro */ - if (hrt_elapsed_time(&raw.timestamp) > 20 * 1000) { - - /* if the secondary failed as well, go to the tertiary */ - if (hrt_elapsed_time(&raw.gyro1_timestamp) > 20 * 1000) { - fds[0].fd = _gyro2_sub; - } else { - fds[0].fd = _gyro1_sub; - } - } - - /* check battery voltage */ - adc_poll(raw); - - diff_pres_poll(raw); - - /* Inform other processes that new data is available to copy */ - if (_publishing) { - orb_publish(ORB_ID(sensor_combined), _sensor_pub, &raw); - } - - /* check parameters for updates */ - parameter_update_poll(); - - /* check rc parameter map for updates */ - rc_parameter_map_poll(); - - /* Look for new r/c input data */ - rc_poll(); - - perf_end(_loop_perf); - } - - warnx("exiting."); - -exit_immediate: - _sensors_task = -1; - _exit(ret); -} - -int -Sensors::start() -{ - ASSERT(_sensors_task == -1); - - /* start the task */ - _sensors_task = task_spawn_cmd("sensors_task", - SCHED_DEFAULT, - SCHED_PRIORITY_MAX - 5, - 2000, - (main_t)&Sensors::task_main_trampoline, - nullptr); - - /* wait until the task is up and running or has failed */ - while (_sensors_task > 0 && _task_should_exit) { - usleep(100); - } - - if (_sensors_task < 0) { - return -ERROR; - } - - return OK; -} - -int sensors_main(int argc, char *argv[]) -{ - if (argc < 2) { - errx(1, "usage: sensors {start|stop|status}"); - } - - if (!strcmp(argv[1], "start")) { - - if (sensors::g_sensors != nullptr) { - errx(0, "already running"); - } - - sensors::g_sensors = new Sensors; - - if (sensors::g_sensors == nullptr) { - errx(1, "alloc failed"); - } - - if (OK != sensors::g_sensors->start()) { - delete sensors::g_sensors; - sensors::g_sensors = nullptr; - err(1, "start failed"); - } - - exit(0); - } - - if (!strcmp(argv[1], "stop")) { - if (sensors::g_sensors == nullptr) { - errx(1, "not running"); - } - - delete sensors::g_sensors; - sensors::g_sensors = nullptr; - exit(0); - } - - if (!strcmp(argv[1], "status")) { - if (sensors::g_sensors) { - errx(0, "is running"); - - } else { - errx(1, "not running"); - } - } - - warnx("unrecognized command"); - return 1; -} diff --git a/src/modules/simulator/simulator.cpp b/src/modules/simulator/simulator.cpp index 9984896525..1b3b6fa2c4 100644 --- a/src/modules/simulator/simulator.cpp +++ b/src/modules/simulator/simulator.cpp @@ -37,13 +37,15 @@ */ #include -#include +#include #include #include #include #include +#ifndef __PX4_QURT #include #include +#endif #include "simulator.h" using namespace simulator; @@ -76,8 +78,11 @@ int Simulator::start(int argc, char *argv[]) { int ret = 0; _instance = new Simulator(); - if (_instance) + if (_instance) { +#ifndef __PX4_QURT _instance->updateSamples(); +#endif + } else { printf("Simulator creation failed\n"); ret = 1; @@ -86,6 +91,7 @@ int Simulator::start(int argc, char *argv[]) } +#ifndef __PX4_QURT void Simulator::updateSamples() { // get samples from external provider @@ -133,6 +139,7 @@ void Simulator::updateSamples() } } } +#endif static void usage() { diff --git a/src/modules/simulator/simulator.h b/src/modules/simulator/simulator.h index e07cc0f296..f27b2fe017 100644 --- a/src/modules/simulator/simulator.h +++ b/src/modules/simulator/simulator.h @@ -148,7 +148,9 @@ private: Simulator() : _accel(1), _mpu(1), _baro(1) {} ~Simulator() { _instance=NULL; } +#ifndef __PX4_QURT void updateSamples(); +#endif static Simulator *_instance; diff --git a/src/modules/uORB/MuORB.cpp b/src/modules/uORB/MuORB.cpp index 0f2a79822b..e55e137d61 100644 --- a/src/modules/uORB/MuORB.cpp +++ b/src/modules/uORB/MuORB.cpp @@ -37,6 +37,7 @@ */ #include +#include #include diff --git a/src/platforms/posix/drivers/adcsim/adcsim.cpp b/src/platforms/posix/drivers/adcsim/adcsim.cpp index db167331f9..1e859c386e 100644 --- a/src/platforms/posix/drivers/adcsim/adcsim.cpp +++ b/src/platforms/posix/drivers/adcsim/adcsim.cpp @@ -41,6 +41,7 @@ */ #include +#include #include #include #include @@ -89,8 +90,6 @@ private: unsigned _channel_count; adc_msg_s *_samples; /**< sample buffer */ - orb_advert_t _to_system_power; - /** work trampoline */ static void _tick_trampoline(void *arg); @@ -114,8 +113,7 @@ ADCSIM::ADCSIM(uint32_t channels) : VDev("adcsim", ADCSIM0_DEVICE_PATH), _sample_perf(perf_alloc(PC_ELAPSED, "adc_samples")), _channel_count(0), - _samples(nullptr), - _to_system_power(0) + _samples(nullptr) { //_debug_enabled = true; @@ -259,7 +257,7 @@ test(void) unsigned channels = count / sizeof(data[0]); for (unsigned j = 0; j < channels; j++) { - printf ("%d: %u ", data[j].am_channel, data[j].am_data); + printf ("%d: %lu ", data[j].am_channel, (unsigned long)data[j].am_data); } printf("\n"); diff --git a/src/platforms/posix/drivers/airspeedsim/airspeedsim.cpp b/src/platforms/posix/drivers/airspeedsim/airspeedsim.cpp new file mode 100644 index 0000000000..2a500af794 --- /dev/null +++ b/src/platforms/posix/drivers/airspeedsim/airspeedsim.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** + * + * Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file ets_airspeed.cpp + * @author Simon Wilks + * + * Driver for the Eagle Tree Airspeed V3 connected via I2C. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +AirspeedSim::AirspeedSim(int bus, int address, unsigned conversion_interval, const char* path) : + I2C("Airspeed", path, bus, address), + _reports(nullptr), + _buffer_overflows(perf_alloc(PC_COUNT, "airspeed_buffer_overflows")), + _max_differential_pressure_pa(0), + _sensor_ok(false), + _last_published_sensor_ok(true), /* initialize differently to force publication */ + _measure_ticks(0), + _collect_phase(false), + _diff_pres_offset(0.0f), + _airspeed_pub(-1), + _subsys_pub(-1), + _class_instance(-1), + _conversion_interval(conversion_interval), + _sample_perf(perf_alloc(PC_ELAPSED, "airspeed_read")), + _comms_errors(perf_alloc(PC_COUNT, "airspeed_comms_errors")) +{ + // enable debug() calls + _debug_enabled = false; + + // work_cancel in the dtor will explode if we don't do this... + memset(&_work, 0, sizeof(_work)); +} + +AirspeedSim::~AirspeedSim() +{ + /* make sure we are truly inactive */ + stop(); + + if (_class_instance != -1) + unregister_class_devname(AIRSPEED_BASE_DEVICE_PATH, _class_instance); + + /* free any existing reports */ + if (_reports != nullptr) + delete _reports; + + // free perf counters + perf_free(_sample_perf); + perf_free(_comms_errors); + perf_free(_buffer_overflows); +} + +int +AirspeedSim::init() +{ + int ret = ERROR; + + /* do I2C init (and probe) first */ + if (I2C::init() != OK) + goto out; + + /* allocate basic report buffers */ + _reports = new RingBuffer(2, sizeof(differential_pressure_s)); + if (_reports == nullptr) + goto out; + + /* register alternate interfaces if we have to */ + _class_instance = register_class_devname(AIRSPEED_BASE_DEVICE_PATH); + + /* publication init */ + if (_class_instance == CLASS_DEVICE_PRIMARY) { + + /* advertise sensor topic, measure manually to initialize valid report */ + struct differential_pressure_s arp; + measure(); + _reports->get(&arp); + + /* measurement will have generated a report, publish */ + _airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &arp); + + if (_airspeed_pub < 0) + warnx("uORB started?"); + } + + ret = OK; + +out: + return ret; +} + +int +AirspeedSim::probe() +{ + /* on initial power up the device may need more than one retry + for detection. Once it is running the number of retries can + be reduced + */ + _retries = 4; + int ret = measure(); + + // drop back to 2 retries once initialised + _retries = 2; + return ret; +} + +int +AirspeedSim::ioctl(px4_dev_handle_t *handlep, int cmd, unsigned long arg) +{ + switch (cmd) { + + case SENSORIOCSPOLLRATE: { + switch (arg) { + + /* switching to manual polling */ + case SENSOR_POLLRATE_MANUAL: + stop(); + _measure_ticks = 0; + return OK; + + /* external signalling (DRDY) not supported */ + case SENSOR_POLLRATE_EXTERNAL: + + /* zero would be bad */ + case 0: + return -EINVAL; + + /* set default/max polling rate */ + case SENSOR_POLLRATE_MAX: + case SENSOR_POLLRATE_DEFAULT: { + /* do we need to start internal polling? */ + bool want_start = (_measure_ticks == 0); + + /* set interval for next measurement to minimum legal value */ + _measure_ticks = USEC2TICK(_conversion_interval); + + /* if we need to start the poll state machine, do it */ + if (want_start) + start(); + + return OK; + } + + /* adjust to a legal polling interval in Hz */ + default: { + /* do we need to start internal polling? */ + bool want_start = (_measure_ticks == 0); + + /* convert hz to tick interval via microseconds */ + unsigned ticks = USEC2TICK(1000000 / arg); + + /* check against maximum rate */ + if (ticks < USEC2TICK(_conversion_interval)) + return -EINVAL; + + /* update interval for next measurement */ + _measure_ticks = ticks; + + /* if we need to start the poll state machine, do it */ + if (want_start) + start(); + + return OK; + } + } + } + + case SENSORIOCGPOLLRATE: + if (_measure_ticks == 0) + return SENSOR_POLLRATE_MANUAL; + + return (1000 / _measure_ticks); + + case SENSORIOCSQUEUEDEPTH: { + /* lower bound is mandatory, upper bound is a sanity check */ + if ((arg < 1) || (arg > 100)) + return -EINVAL; + + irqstate_t flags = irqsave(); + if (!_reports->resize(arg)) { + irqrestore(flags); + return -ENOMEM; + } + irqrestore(flags); + + return OK; + } + + case SENSORIOCGQUEUEDEPTH: + return _reports->size(); + + case SENSORIOCRESET: + /* XXX implement this */ + return -EINVAL; + + case AIRSPEEDIOCSSCALE: { + struct airspeed_scale *s = (struct airspeed_scale*)arg; + _diff_pres_offset = s->offset_pa; + return OK; + } + + case AIRSPEEDIOCGSCALE: { + struct airspeed_scale *s = (struct airspeed_scale*)arg; + s->offset_pa = _diff_pres_offset; + s->scale = 1.0f; + return OK; + } + + default: + /* give it to the superclass */ + return I2C::ioctl(handlep, cmd, arg); + } +} + +ssize_t +AirspeedSim::read(px4_dev_handle_t *handlep, char *buffer, size_t buflen) +{ + unsigned count = buflen / sizeof(differential_pressure_s); + differential_pressure_s *abuf = reinterpret_cast(buffer); + int ret = 0; + + /* buffer must be large enough */ + if (count < 1) + return -ENOSPC; + + /* if automatic measurement is enabled */ + if (_measure_ticks > 0) { + + /* + * While there is space in the caller's buffer, and reports, copy them. + * Note that we may be pre-empted by the workq thread while we are doing this; + * we are careful to avoid racing with them. + */ + while (count--) { + if (_reports->get(abuf)) { + ret += sizeof(*abuf); + abuf++; + } + } + + /* if there was no data, warn the caller */ + return ret ? ret : -EAGAIN; + } + + /* manual measurement - run one conversion */ + do { + _reports->flush(); + + /* trigger a measurement */ + if (OK != measure()) { + ret = -EIO; + break; + } + + /* wait for it to complete */ + usleep(_conversion_interval); + + /* run the collection phase */ + if (OK != collect()) { + ret = -EIO; + break; + } + + /* state machine will have generated a report, copy it out */ + if (_reports->get(abuf)) { + ret = sizeof(*abuf); + } + + } while (0); + + return ret; +} + +void +AirspeedSim::start() +{ + /* reset the report ring and state machine */ + _collect_phase = false; + _reports->flush(); + + /* schedule a cycle to start things */ + work_queue(HPWORK, &_work, (worker_t)&AirspeedSim::cycle_trampoline, this, 1); +} + +void +AirspeedSim::stop() +{ + work_cancel(HPWORK, &_work); +} + +void +AirspeedSim::update_status() +{ + if (_sensor_ok != _last_published_sensor_ok) { + /* notify about state change */ + struct subsystem_info_s info = { + true, + true, + _sensor_ok, + SUBSYSTEM_TYPE_DIFFPRESSURE + }; + + if (_subsys_pub > 0) { + orb_publish(ORB_ID(subsystem_info), _subsys_pub, &info); + } else { + _subsys_pub = orb_advertise(ORB_ID(subsystem_info), &info); + } + + _last_published_sensor_ok = _sensor_ok; + } +} + +void +AirspeedSim::cycle_trampoline(void *arg) +{ + Airspeed *dev = (Airspeed *)arg; + + dev->cycle(); + // XXX we do not know if this is + // really helping - do not update the + // subsys state right now + //dev->update_status(); +} + +void +AirspeedSim::print_info() +{ + perf_print_counter(_sample_perf); + perf_print_counter(_comms_errors); + perf_print_counter(_buffer_overflows); + warnx("poll interval: %u ticks", _measure_ticks); + _reports->print_info("report queue"); +} + +void +AirspeedSim::new_report(const differential_pressure_s &report) +{ + if (!_reports->force(&report)) + perf_count(_buffer_overflows); +} diff --git a/src/platforms/posix/drivers/airspeedsim/airspeedsim.h b/src/platforms/posix/drivers/airspeedsim/airspeedsim.h new file mode 100644 index 0000000000..66f4c58627 --- /dev/null +++ b/src/platforms/posix/drivers/airspeedsim/airspeedsim.h @@ -0,0 +1,187 @@ +/**************************************************************************** + * + * Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file airspeed.h + * @author Simon Wilks + * + * Generic driver for airspeed sensors connected via I2C. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* Default I2C bus */ +#define PX4_I2C_BUS_DEFAULT PX4_I2C_BUS_EXPANSION + +/* Oddly, ERROR is not defined for C++ */ +#ifdef ERROR +# undef ERROR +#endif +static const int ERROR = -1; + +#ifndef CONFIG_SCHED_WORKQUEUE +# error This requires CONFIG_SCHED_WORKQUEUE. +#endif + +class __EXPORT AirspeedSim : public device::I2C +{ +public: + AirspeedSim(int bus, int address, unsigned conversion_interval, const char *path); + virtual ~AirspeedSim(); + + virtual int init(); + + virtual ssize_t read(px4_dev_handle_t *handlep, char *buffer, size_t buflen); + virtual int ioctl(px4_dev_handle_t *handlep, int cmd, unsigned long arg); + + /** + * Diagnostics - print some basic information about the driver. + */ + virtual void print_info(); + +private: + RingBuffer *_reports; + perf_counter_t _buffer_overflows; + + /* this class has pointer data members and should not be copied */ + AirspeedSim(const AirspeedSim &); + AirspeedSim &operator=(const AirspeedSim &); + +protected: + virtual int probe(); + + /** + * Perform a poll cycle; collect from the previous measurement + * and start a new one. + */ + virtual void cycle() = 0; + virtual int measure() = 0; + virtual int collect() = 0; + + /** + * Update the subsystem status + */ + void update_status(); + + work_s _work; + float _max_differential_pressure_pa; + bool _sensor_ok; + bool _last_published_sensor_ok; + int _measure_ticks; + bool _collect_phase; + float _diff_pres_offset; + + orb_advert_t _airspeed_pub; + orb_advert_t _subsys_pub; + + int _class_instance; + + unsigned _conversion_interval; + + perf_counter_t _sample_perf; + perf_counter_t _comms_errors; + + + /** + * Test whether the device supported by the driver is present at a + * specific address. + * + * @param address The I2C bus address to probe. + * @return True if the device is present. + */ + int probe_address(uint8_t address); + + /** + * Initialise the automatic measurement state machine and start it. + * + * @note This function is called at open and error time. It might make sense + * to make it more aggressive about resetting the bus in case of errors. + */ + void start(); + + /** + * Stop the automatic measurement state machine. + */ + void stop(); + + /** + * Static trampoline from the workq context; because we don't have a + * generic workq wrapper yet. + * + * @param arg Instance pointer for the driver that is polling. + */ + static void cycle_trampoline(void *arg); + + /** + * add a new report to the reports queue + * + * @param report differential_pressure_s report + */ + void new_report(const differential_pressure_s &report); +}; + + diff --git a/src/platforms/posix/drivers/airspeedsim/module.mk b/src/platforms/posix/drivers/airspeedsim/module.mk new file mode 100644 index 0000000000..2d971e4d28 --- /dev/null +++ b/src/platforms/posix/drivers/airspeedsim/module.mk @@ -0,0 +1,40 @@ +############################################################################ +# +# Copyright (c) 2013 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# +# Makefile to build the generic airspeed driver. +# + +SRCS = airspeedsim.cpp + +MAXOPTIMIZATION = -Os diff --git a/src/platforms/posix/drivers/barosim/baro.cpp b/src/platforms/posix/drivers/barosim/baro.cpp index 8398d18c58..bef9c9c5aa 100644 --- a/src/platforms/posix/drivers/barosim/baro.cpp +++ b/src/platforms/posix/drivers/barosim/baro.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -755,7 +756,7 @@ BAROSIM::print_info() perf_print_counter(_buffer_overflows); printf("poll interval: %u ticks\n", _measure_ticks); _reports->print_info("report queue"); - printf("TEMP: %d\n", _TEMP); + printf("TEMP: %ld\n", (long)_TEMP); printf("SENS: %lld\n", (long long)_SENS); printf("OFF: %lld\n", (long long)_OFF); printf("P: %.3f\n", (double)_P); @@ -964,12 +965,12 @@ test() /* read the sensor 5x and report each value */ for (unsigned i = 0; i < 5; i++) { - struct pollfd fds; + px4_pollfd_struct_t fds; /* wait for data to be ready */ fds.fd = fd; fds.events = POLLIN; - ret = poll(&fds, 1, 2000); + ret = px4_poll(&fds, 1, 2000); if (ret != 1) { warnx("timed out waiting for sensor data"); @@ -990,7 +991,7 @@ test() warnx("time: %lld", (long long)report.timestamp); } - close(fd); + px4_close(fd); warnx("PASS"); return 0; } @@ -1004,7 +1005,7 @@ reset() struct barosim_bus_option &bus = bus_options[0]; int fd; - fd = open(bus.devpath, O_RDONLY); + fd = px4_open(bus.devpath, O_RDONLY); if (fd < 0) { warn("failed "); return 1; @@ -1068,14 +1069,14 @@ calibrate(unsigned altitude) pressure = 0.0f; for (unsigned i = 0; i < 20; i++) { - struct pollfd fds; + px4_pollfd_struct_t fds; int ret; ssize_t sz; /* wait for data to be ready */ fds.fd = fd; fds.events = POLLIN; - ret = poll(&fds, 1, 1000); + ret = px4_poll(&fds, 1, 1000); if (ret != 1) { warnx("timed out waiting for sensor data"); @@ -1116,7 +1117,7 @@ calibrate(unsigned altitude) return 1; } - close(fd); + px4_close(fd); return 0; } diff --git a/src/platforms/posix/drivers/barosim/baro_sim.cpp b/src/platforms/posix/drivers/barosim/baro_sim.cpp index 2e628f571c..42d52b4fef 100644 --- a/src/platforms/posix/drivers/barosim/baro_sim.cpp +++ b/src/platforms/posix/drivers/barosim/baro_sim.cpp @@ -69,7 +69,7 @@ public: virtual int transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len); private: - barosim::prom_u &_prom; + //barosim::prom_u &_prom; /** * Send a reset command to the barometer simulator. @@ -101,8 +101,7 @@ BAROSIM_sim_interface(barosim::prom_u &prom_buf, uint8_t busnum) } BARO_SIM::BARO_SIM(uint8_t bus, barosim::prom_u &prom) : - SIM("BARO_SIM", "/dev/BARO_SIM", bus, 0), - _prom(prom) + SIM("BARO_SIM", "/dev/BARO_SIM", bus, 0) { } diff --git a/src/platforms/posix/drivers/gyrosim/gyrosim.cpp b/src/platforms/posix/drivers/gyrosim/gyrosim.cpp index a984a310a2..55a34b191a 100644 --- a/src/platforms/posix/drivers/gyrosim/gyrosim.cpp +++ b/src/platforms/posix/drivers/gyrosim/gyrosim.cpp @@ -57,7 +57,6 @@ #include #include #include -#include #include diff --git a/src/platforms/px4_common.h b/src/platforms/px4_common.h new file mode 100644 index 0000000000..d7b7a69421 --- /dev/null +++ b/src/platforms/px4_common.h @@ -0,0 +1,8 @@ +#pragma once + +#ifdef __PX4_QURT +#include +size_t strnlen(const char *s, size_t maxlen); + +//inline bool isfinite(int x) { return true; } +#endif diff --git a/src/platforms/px4_time.h b/src/platforms/px4_time.h new file mode 100644 index 0000000000..02dc1c4a7e --- /dev/null +++ b/src/platforms/px4_time.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#ifdef __PX4_LINUX + +#define px4_clock_gettime clock_gettime +#define px4_clock_settime clock_settime + +#elif defined(__PX4_QURT) + +#define CLOCK_REALTIME 1 + +__BEGIN_DECLS + +#if !defined(__cplusplus) +struct timespec +{ + time_t tv_sec; + long tv_nsec; +}; +#endif +int px4_clock_gettime(clockid_t clk_id, struct timespec *tp); +int px4_clock_settime(clockid_t clk_id, struct timespec *tp); + +__EXPORT int usleep(useconds_t usec); +__EXPORT unsigned int sleep(unsigned int sec); + +__END_DECLS +#endif diff --git a/src/platforms/qurt/include/i2c.h b/src/platforms/qurt/include/i2c.h new file mode 100644 index 0000000000..ee3e4196dd --- /dev/null +++ b/src/platforms/qurt/include/i2c.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * include/nuttx/i2c.h + * + * Copyright(C) 2009-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +#pragma once + +struct i2c_msg_s +{ + uint16_t addr; /* Slave address */ + uint16_t flags; /* See I2C_M_* definitions */ + uint8_t *buffer; + int length; +}; diff --git a/src/platforms/qurt/include/poll.h b/src/platforms/qurt/include/poll.h index 324036aa5c..59f1809e2a 100644 --- a/src/platforms/qurt/include/poll.h +++ b/src/platforms/qurt/include/poll.h @@ -1,3 +1,40 @@ +/**************************************************************************** + * include/poll.h + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + #pragma once typedef unsigned int nfds_t; + +#define POLLIN (0x01) diff --git a/src/platforms/qurt/include/sys/ioctl.h b/src/platforms/qurt/include/sys/ioctl.h new file mode 100644 index 0000000000..0d08f75231 --- /dev/null +++ b/src/platforms/qurt/include/sys/ioctl.h @@ -0,0 +1,3 @@ +#pragma once + +#define _IO(x,y) (x+y) diff --git a/src/platforms/qurt/main.cpp b/src/platforms/qurt/main.cpp index 3697fed0df..55f9ad9a8d 100644 --- a/src/platforms/qurt/main.cpp +++ b/src/platforms/qurt/main.cpp @@ -49,25 +49,29 @@ //typedef int (*px4_main_t)(int argc, char *argv[]); #include "apps.h" -//#include "px4_middleware.h" +#include "px4_middleware.h" -static const char *commands = "hello start\n"; +static const char *commands = "hello start\n" + "list_tasks"; static void run_cmd(const vector &appargs) { // command is appargs[0] string command = appargs[0]; printf("Looking for %s\n", command.c_str()); if (apps.find(command) != apps.end()) { - const char *arg[appargs.size()+2]; + const char *arg[2+1]; unsigned int i = 0; - while (i < appargs.size() && appargs[i] != "") { + printf("size = %d\n", appargs.size()); + while (i < appargs.size() && appargs[i].c_str()[0] != '\0') { arg[i] = (char *)appargs[i].c_str(); printf(" arg = '%s'\n", arg[i]); ++i; } arg[i] = (char *)0; + //printf("BEFORE argc = %d %s %s %p\n", i, arg[0], arg[1], arg[2]); apps[command](i,(char **)arg); + //printf("AFTER argc = %d %s %s %p\n", i, arg[0], arg[1], arg[2]); } else { @@ -76,35 +80,39 @@ static void run_cmd(const vector &appargs) { } } +void eat_whitespace(const char *&b, int &i) +{ + // Eat whitespace + while (b[i] == ' ' || b[i] == '\t') { ++i; } + b = &b[i]; + i=0; +} + static void process_commands(const char *cmds) { - vector appargs(5); + vector appargs; int i=0; - int j=0; const char *b = cmds; bool found_first_char = false; char arg[20]; // Eat leading whitespace - while (b[i] == ' ') { ++i; }; - b = &b[i]; + eat_whitespace(b, i); for(;;) { // End of command line if (b[i] == '\n' || b[i] == '\0') { strncpy(arg, b, i); arg[i] = '\0'; - appargs[j] = arg; + appargs.push_back(arg); // If we have a command to run - if (i > 0 || j > 0) + if (appargs.size() > 0) { run_cmd(appargs); - j=0; + } + appargs.clear(); if (b[i] == '\n') { - // Eat whitespace - while (b[++i] == ' '); - b = &b[i]; - i=0; + eat_whitespace(b, ++i); continue; } else { @@ -115,12 +123,8 @@ static void process_commands(const char *cmds) else if (b[i] == ' ') { strncpy(arg, b, i); arg[i] = '\0'; - appargs[j] = arg; - j++; - // Eat whitespace - while (b[++i] == ' '); - b = &b[i]; - i=0; + appargs.push_back(arg); + eat_whitespace(b, ++i); continue; } ++i; @@ -129,6 +133,7 @@ static void process_commands(const char *cmds) int main(int argc, char **argv) { + px4::init(argc, argv, "mainapp"); process_commands(commands); for (;;) {} } diff --git a/src/platforms/qurt/px4_layer/px4_qurt_tasks.cpp b/src/platforms/qurt/px4_layer/px4_qurt_tasks.cpp index 92f25e5827..94d52be945 100644 --- a/src/platforms/qurt/px4_layer/px4_qurt_tasks.cpp +++ b/src/platforms/qurt/px4_layer/px4_qurt_tasks.cpp @@ -79,14 +79,17 @@ typedef struct static void entry_adapter ( void *ptr ) { - pthdata_t *data; - data = (pthdata_t *) ptr; + pthdata_t *data = (pthdata_t *) ptr; - data->entry(data->argc, data->argv); - free(ptr); + printf("TEST3\n"); +#if 0 + //data->entry(data->argc, data->argv); + printf("TEST4\n"); printf("Before px4_task_exit\n"); px4_task_exit(0); + //free(ptr); printf("After px4_task_exit\n"); +#endif } void @@ -95,7 +98,7 @@ px4_systemreset(bool to_bootloader) printf("Called px4_system_reset\n"); } -px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int stack_size, px4_main_t entry, char * const argv[]) +px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int stack_size, px4_main_t entry, char * const *argv) { int rv; int argc = 0; @@ -105,14 +108,18 @@ px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int unsigned long structsize; char * p; + //printf("arg %d %s %s %p\n", argc, argv[0], argv[1], argv[2]); + printf("arg %d %p\n", argc, argv); // Calculate argc - for(;;) { - p = argv[argc]; - printf("arg %d %s\n", argc, argv[argc]); - if (p == (char *)0) - break; - ++argc; - len += strlen(p)+1; + if (argv) { + for(;;) { + p = argv[argc]; + if (p == (char *)0) + break; + printf("arg %d %s\n", argc, argv[argc]); + ++argc; + len += strlen(p)+1; + } } structsize = sizeof(pthdata_t)+(argc+1)*sizeof(char *); pthdata_t *taskdata; @@ -125,6 +132,7 @@ px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int taskdata->argc = argc; for (i=0; iargv[i] = (char *)offset; strcpy((char *)offset, argv[i]); @@ -138,10 +146,11 @@ px4_task_t px4_task_spawn_cmd(const char *name, int scheduler, int priority, int taskmap[i].pid = i+1; taskmap[i].name = name; taskmap[i].isused = true; - taskmap[i].sp = malloc(stack_size);; + taskmap[i].sp = malloc(stack_size); break; } } + printf("TEST2\n"); thread_create(entry_adapter, taskmap[i].sp, i+1, (void *) taskdata); return i+1; @@ -156,6 +165,8 @@ int px4_task_delete(px4_task_t id) void px4_task_exit(int ret) { thread_stop(); + + // Free stack } void px4_killall(void) diff --git a/src/platforms/qurt/tests/hello/hello_start_qurt.cpp b/src/platforms/qurt/tests/hello/hello_start_qurt.cpp index 987e4807dd..71f30cd8dd 100644 --- a/src/platforms/qurt/tests/hello/hello_start_qurt.cpp +++ b/src/platforms/qurt/tests/hello/hello_start_qurt.cpp @@ -56,7 +56,7 @@ static void usage() } int hello_main(int argc, char *argv[]) { - printf("argc = %d %s %s\n", argc, argv[0], argv[1]); + printf("argc = %d %s %s %p\n", argc, argv[0], argv[1], argv[2]); if (argc < 2) { usage(); return 1;