Compare commits

...

362 Commits

Author SHA1 Message Date
Randy Mackay
3c57e77190 Copter: update version to AC3.1.5 2014-05-27 10:17:31 +09:00
Randy Mackay
a77f070613 Copter: update release notes for AC3.1.5 2014-05-27 10:17:07 +09:00
Randy Mackay
a57b8dbea8 Copter: update release notes for AC3.1.5-rc2 2014-05-20 21:37:26 +09:00
Randy Mackay
3eaa66849e Copter: update version to AC3.1.5-rc2 2014-05-20 21:37:22 +09:00
Jonathan Challinger
effc75f50f Copter: reject bad RC inputs during failsafe 2014-05-15 20:21:11 +09:00
Randy Mackay
7195ba13be Copter: update Release notes again for AC3.1.5-rc1 2014-05-15 20:21:10 +09:00
Randy Mackay
53cefddf6b Copter: version to AC3.1.5-rc1 2014-05-14 11:00:26 +09:00
Randy Mackay
861d934573 Copter: release notes for AC3.1.5-rc1 2014-05-14 10:59:05 +09:00
Jonathan Challinger
505d2d68d6 Copter: protect loiter controller from bad inputs during failsafe 2014-05-14 10:55:54 +09:00
Randy Mackay
ca0652fea9 Copter: version to AC3.1.4 2014-05-08 11:29:32 +09:00
Randy Mackay
36aa4945b3 Copter: update release notes for AC3.1.4 2014-05-08 11:29:14 +09:00
Randy Mackay
459cbd570b Copter: version to AC3.1.4-rc1 2014-05-02 10:13:50 +09:00
Randy Mackay
6dd0b1fc3f Copter: update release notes for AC3.1.4-rc1 2014-05-02 10:12:56 +09:00
Randy Mackay
aefeb38bfd Copter: version to AC3.1.3 2014-04-14 10:35:45 +09:00
Randy Mackay
411fd39a3e Copter: version to AC3.1.3-rc1 2014-04-08 23:09:37 +09:00
Randy Mackay
8a272063dc Copter: version to AC3.1.3 2014-04-07 14:32:54 +09:00
Randy Mackay
e344417ce2 Copter: AC3.1.3 release notes 2014-04-07 14:29:43 +09:00
Jonathan Challinger
fb703ff506 AP_Motors: properly constrain thr_adj_max 2014-04-07 14:18:15 +09:00
Randy Mackay
ddd4d881a9 Copter: firmware to AC3.1.2 2014-02-13 20:52:08 +09:00
Randy Mackay
606e2ff100 Copter: firmware to AC3.1.2-rc2 2014-02-12 16:47:07 +09:00
Randy Mackay
36ff22b000 Copter: firmware to AC3.1.2-rc1 2014-01-30 14:04:05 +09:00
Randy Mackay
ccee8ca6a5 Git : ignore eclipse project files 2014-01-26 09:42:52 +09:00
Randy Mackay
12ba1b9f51 Git: remove old eclipse project file 2014-01-26 09:39:40 +09:00
Randy Mackay
a72bd31e36 Git : ignore eclipse project files 2014-01-26 09:37:02 +09:00
Randy Mackay
efd31a7b1f Copter: Release notes for AC3.1.1 2014-01-26 09:33:49 +09:00
Randy Mackay
da5e40b591 Copter: version to AC3.1.1 2014-01-26 09:33:34 +09:00
Stefan
9564ff3c97 Copter: Update ReleaseNotes.txt 2014-01-22 15:06:33 +09:00
Randy Mackay
c0deef5209 Copter: version to AC3.1.1-rc2
This update applies to pixhawk only
2014-01-22 10:51:24 +09:00
Randy Mackay
6bdba1672b Copter: AC3.1.1-rc2 release notes 2014-01-22 10:51:21 +09:00
Randy Mackay
600162a944 Copter: update AC3.1.1-rc1 release notes 2014-01-14 21:57:26 +09:00
Randy Mackay
166031c569 Copter: update version to AC3.1.1-rc1 2014-01-14 21:03:59 +09:00
Randy Mackay
45511100fd Copter: AC3.1.1-rc1 release notes 2014-01-14 21:02:41 +09:00
Randy Mackay
37ba279b78 TradHeli: Drift mode to use heli manual throttle 2014-01-13 22:31:49 +09:00
Robert Lefebvre
36c288f2e0 TradHeli: Minor change to two param defaults
Also one param name in the code clarified.
2014-01-13 22:31:46 +09:00
Robert Lefebvre
252dd1c8d1 TradHeli: rename Stab_Col parameters
With H_ prefix they appear with the rest of the tradheli specific params in the parameter list.
2014-01-13 22:31:39 +09:00
Robert Lefebvre
e4949bf3b0 TradHeli: enable Landing Collective when we are not moving
This prevents full negative pitch when touching down in Alt Hold or Auto-Landing.
2014-01-13 22:31:37 +09:00
Robert Lefebvre
c940c2538b TradHeli: disable AutoTune for Tradheli compile
We need the flash space, and this probably won't work for tradheli anyway since tradheli needs most of the control from Feedforward rather than P term.  And D-term is very very bad.
2014-01-13 22:31:34 +09:00
Randy Mackay
1b3a1f5337 PX4: enable uartD by default in rc.APM 2014-01-13 14:35:42 +09:00
Andrew Tridgell
3af69f5328 Copter: added SERIAL2_BAUD and rename SERIAL3_BAUD to SERIAL1_BAUD 2014-01-13 12:32:51 +09:00
Andrew Tridgell
3920382150 Copter: removed extra features of copter telemetry merge 2014-01-13 12:32:46 +09:00
Andrew Tridgell
bac572fe17 Copter: added uartD support
this also brings GCS_Mavlink.pde closer to the plane implementation
2014-01-13 12:31:51 +09:00
Andrew Tridgell
c9885123df GCS_MAVLink: added support for 3 UARTs
support 3 UARTs on non-AVR platforms
2014-01-13 12:30:05 +09:00
Andrew Tridgell
0bd68e00a6 HAL_PX4: added uartD 2014-01-13 12:30:01 +09:00
Andrew Tridgell
4af765692d HAL_LINUX: added uartD 2014-01-13 12:29:56 +09:00
Andrew Tridgell
8d1998c796 HAL_FLYMAPLE: added uartD 2014-01-13 12:29:54 +09:00
Andrew Tridgell
3c6dd23a62 HAL_EMPTY: added uartD 2014-01-13 12:29:51 +09:00
Andrew Tridgell
5d99ff1d0d HAL_SITL: added uartD 2014-01-13 12:29:49 +09:00
Andrew Tridgell
1a76dcad64 HAL_AVR: added NULL uartD 2014-01-13 12:29:47 +09:00
Andrew Tridgell
066a7ce966 AP_HAL: support uartD on some boards
PX4 and SITL get an extra UART
2014-01-13 12:29:44 +09:00
Andrew Tridgell
333f0532b7 HAL_PX4: fixed build for new PX4Firmware 2014-01-13 12:17:21 +09:00
Robert Lefebvre
ea90984d8c TradHeli: Fix for yaw offset switching. Yaw Offset should switch on and off with the main motor, not waiting until the rotor has reached full speed. 2014-01-13 12:11:18 +09:00
Michael Oborne
2e56592886 Copter: BugFix DO_SET_ROI returns Lat,Lon,Alt to GCS 2014-01-13 12:06:38 +09:00
Randy Mackay
e15527973a Copter: bugfix for starting in LOITER
Loiter's Roll-Pitch mode was not being set on start-up.
2013-12-30 17:14:42 +09:00
Randy Mackay
5c6503e2f1 Copter: update firmware to 3.1 2013-12-14 17:07:05 +09:00
Randy Mackay
cb733de4fc Copter: 3.1 release notes 2013-12-14 17:06:41 +09:00
Andrew Tridgell
1144b4f3d7 PX4: added automatic IO firmware update 2013-12-14 16:14:28 +11:00
Andrew Tridgell
db254866e5 PX4: change FMUv2 bootloader USB ID to 0x0011 2013-12-14 16:12:00 +11:00
Andrew Tridgell
0257c0d92b build: fixed a build cmp warning 2013-12-14 16:11:57 +11:00
Andrew Tridgell
e1cb1475e4 PX4: added -Wno-packed
we know that packed data structures are not as efficient
2013-12-14 16:11:53 +11:00
Andrew Tridgell
b01487048a build: reduced PX4 warnings and avoid rebuilding when possible 2013-12-14 16:11:49 +11:00
Andrew Tridgell
ce30bd39dc PX4: start all sensor types on PX4
this allows for secondary sensors
2013-12-14 16:11:30 +11:00
Andrew Tridgell
b488f017e6 PX4: added support for the MPU6000 on the v2.4 Pixhawk 2013-12-14 16:10:37 +11:00
Randy Mackay
5bb5f1d5bd AC_WPNav: reduce leash length for stopping
We now limit the target stopping point to 1x the xy leash length while
previously it was 2x.  This is justified because this limit is only used
when the copter is travelling at higher speeds but at higher speeds air
drag tends to make the copter stop more quickly naturally.
2013-12-13 22:39:57 +09:00
Randy Mackay
b89edb94f7 Copter: initialise waypoint leash length
Without this initialisation the first RTL could be too aggressive as it
tries to stop too suddenly
2013-12-13 22:39:05 +09:00
Randy Mackay
4bfa706996 Copter: Y6 new motor factor fix 2013-12-12 11:58:14 +09:00
Randy Mackay
e02827b2b1 Copter: firmware to AC3.1-rc8 2013-12-09 12:01:46 +09:00
Randy Mackay
9329eb96ae Copter: AC3.1-rc8 release notes 2013-12-09 12:01:18 +09:00
Randy Mackay
8146ef7c00 GPSGlitch: reduce radius to 2m 2013-12-09 11:44:47 +09:00
Randy Mackay
0c97136cbd Copter: reduce autotune min rate P to 0.01 (was 0.02) 2013-12-08 11:28:03 +09:00
Randy Mackay
3a7442165c Copter: ignore yaw input during radio failsafe 2013-12-06 13:57:02 +09:00
Randy Mackay
22f07fb141 Copter: log flight mode to dataflash on start-up 2013-12-06 13:54:34 +09:00
Randy Mackay
cb64955806 TradHeli: bug fix for main rotor ramp up
The main rotor ramp was being held back by the rotor speed estimate
instead of being allowed to jump up to the estimate if it's lower.

Also fixed some incorrect indentation
2013-12-05 21:25:46 +09:00
Randy Mackay
1deba935ea Copter: pre arm mag offset limit to 600 for PX4 2013-12-03 23:24:48 +09:00
Randy Mackay
6fd51342fe Copter: add Y6 with all top props CW
Set FRAME parameter to 10
2013-12-03 23:24:45 +09:00
Randy Mackay
9a87f15b28 Copter: correct optflow logging 2013-12-02 12:01:49 +09:00
Randy Mackay
eb1b2c4265 OptFlow: correct SPI mode and baud rates 2013-12-02 12:01:45 +09:00
Randy Mackay
d654931954 Copter: reduce SONAR_GAIN to 0.8 (was 2.0) 2013-12-01 16:27:15 +09:00
Randy Mackay
9d0e09e2be Copter: run GPS glitch detection even when not armed 2013-11-23 17:08:46 +09:00
Andrew Tridgell
6a491f558c autotest: use mavflightview.py from $PATH 2013-11-23 17:08:44 +09:00
Andrew Tridgell
94924571d8 GCS_MAVLink: increase max packet size to 104
this enables the DATA96 packet to be sent
2013-11-23 17:08:43 +09:00
Randy Mackay
e30f4bf193 Copter: remove unused gps_fix_count 2013-11-23 17:08:41 +09:00
Randy Mackay
0447c967b8 Copter: log GPS messages even when no fix 2013-11-23 17:08:39 +09:00
Randy Mackay
8d4a5f0087 Copter: commit to kick-off auto rebuild for -rc7 release 2013-11-23 17:08:38 +09:00
Randy Mackay
133d4ee747 Copter: update -rc7 release notes 2013-11-23 17:08:36 +09:00
Randy Mackay
872e6efa8f Copter: revert pre-arm check for slow GPS 2013-11-23 17:08:35 +09:00
Randy Mackay
2ee22e1b85 Copter: AC3.1-rc7 version and release notes 2013-11-23 17:08:33 +09:00
Randy Mackay
fc4b5c962f Copter: pre-arm check that INAV has no errors 2013-11-23 17:08:31 +09:00
Randy Mackay
e47e1f21d8 Copter: add INAV error count to PM dataflash msg 2013-11-23 17:08:30 +09:00
Randy Mackay
7b849d8cfb INav: record error_count when GPS msg is late 2013-11-23 17:08:28 +09:00
Randy Mackay
6ef0337a30 Ublox: disable NMEA info in 3DR config 2013-11-23 17:08:27 +09:00
Randy Mackay
4c2c3e719b Ublox: set default rate to 5hz in 3DR config 2013-11-23 17:08:25 +09:00
Randy Mackay
5c37526208 Ublox: disable TimePulse Timedata in 3DR config 2013-11-23 17:08:24 +09:00
Randy Mackay
986023495e Ublox: update config to ver 7.03 2013-11-23 17:08:22 +09:00
Randy Mackay
680e3316e4 Copter: increase min LAND_SPEED to 30cm/s 2013-11-23 17:08:20 +09:00
Randy Mackay
878ef115a6 Copter: prefix SingleCopter's MOT param description
This should allow single copter's MOT_ parameter descriptions to be more
easily recognised as belonging to SingleCopter when viewed on the wiki's
arducopter-parameters page
2013-11-23 17:08:19 +09:00
Randy Mackay
46a1649f2c Copter: fix SingleCopter motor parameters link 2013-11-23 17:08:17 +09:00
Randy Mackay
c4a5bbd3c2 TradHeli: remove slash from parameter description
This may fix the issue in which the parameter descriptions are appearing
twice on the arducopter-parameters wiki page
2013-11-23 17:08:16 +09:00
Randy Mackay
514568afcf Copter: arming check for gps if GPS FS set to LAND_EVEN_STABILIZE
Setting the GPS Failsafe to LAND_EVEN_STABILIZE means the copter will
LAND if it loses GPS even if it's in a manual flight mode like
Stabilize.  With this setting it makes sense to check the GPS quality
before arming even if we're in stabilize mode.
2013-11-23 17:08:14 +09:00
Randy Mackay
999f4bf289 INav: degrade pos error slowly on loss of GPS
When GPS message is late by 100ms or we are glitching, degrade the GPS
vs inertial nav position error to 10% over 2 seconds instead of
immediately setting it to zero.  This avoids jumpy position estimates
when the GPS misses an update
2013-11-23 17:08:12 +09:00
Randy Mackay
f84b04daa9 Copter: display pre-arm check failure reason every 30sec 2013-11-23 17:08:11 +09:00
Randy Mackay
5bedb3c683 Copter: default MOT_SPIN_ARMED to 70 2013-11-23 17:08:09 +09:00
Randy Mackay
35e23ff0f3 Copter: pre-arm check for ACRO_BAL_ROLL and PITCH 2013-11-23 17:08:07 +09:00
Randy Mackay
5808515e61 Copter: auto disarm in Loiter, AltHold after 15sec 2013-11-23 17:08:06 +09:00
Randy Mackay
e5cc16b45f Copter: radio, batt failsafe disarm if copter is landed in Loiter or AltHold 2013-11-23 17:08:04 +09:00
Randy Mackay
b66beff283 Copter: CURR dataflash msg to output throttle_out
Previously it was outputting throttle-in which is not as useful in
autonomous modes
2013-11-23 17:08:03 +09:00
Randy Mackay
a266109f8b Rover: log INS errors in PM message 2013-11-23 17:08:01 +09:00
Randy Mackay
3c2a496745 Plane: log INS errors in PM message 2013-11-23 17:07:59 +09:00
Randy Mackay
a5cca22252 Copter: log INS errors in PM message 2013-11-23 17:07:58 +09:00
Andrew Tridgell
64d6d54757 Rover: added basic support for reverse in STEERING mode
this will allow for reverse in steering mode, while also fixing a
problem with AHRS yaw when reversing, and a problem with initial
throttle in steering mode
2013-11-23 17:07:56 +09:00
Andrew Tridgell
661f8b2ae0 Plane: fixed throttle failsafe with reversed throttle 2013-11-23 17:07:55 +09:00
Randy Mackay
8fc03b0d17 Copter: commit to kick off MP rebuild
Required to push back MP Beta Firmwares version to AC3.1-rc5
2013-11-23 17:07:53 +09:00
Randy Mackay
0cbcadb605 Copter: update AC3.1-rc6 release notes again 2013-11-23 17:07:51 +09:00
Randy Mackay
2fca578989 AP_HAL_AVR: resolve compiler warning 2013-11-23 17:07:50 +09:00
Randy Mackay
b7c9f7b4e9 TradHeli: dynamic flight speed minimum to 5m/s 2013-11-23 17:07:48 +09:00
Randy Mackay
74e33d97ef Copter: batt failsafe triggers RTL from AUTO 2013-11-23 17:07:46 +09:00
Randy Mackay
5b4ca2d334 Copter: update AC3.1-rc6 release notes 2013-11-23 17:07:45 +09:00
Randy Mackay
d4ad891265 Copter: allow battery failsafe to trigger RTL 2013-11-23 17:07:43 +09:00
Randy Mackay
4aa7d6e436 Copter: minor comment update for set_mode 2013-11-23 17:07:42 +09:00
Randy Mackay
d9399f35d4 Copter: allow GPS failsafe to trigger AltHold
FS_GPS_ENABLE parameter accepts two new options, 2=AltHold,
3=LandEvenFromStabilize.
If set to 3 the GPS failsafe will trigger and LAND even from manual
flight modes like Stabilize and ACRO.  This is useful for users who want
to ensure their copters can never stray outside the circular fence (the
fence only triggers when it knows it is outside the bounds, and it can't
know this if it has no GPS)
2013-11-23 17:07:40 +09:00
Randy Mackay
5c40424a1b Copter: update contributors list 2013-11-23 17:07:38 +09:00
Randy Mackay
3cdf94a2fd Copter: AC3.1-rc6 version and release notes 2013-11-23 17:07:37 +09:00
Randy Mackay
e5e31de148 Copter: bug fix to Tricopter motor logging
Fourth motor taken from yaw channel's radio_out instead of random
location in memory
2013-11-23 17:07:35 +09:00
Randy Mackay
cebbb082a0 TradHeli: restore CC_COMP and PIRO_COMP 2013-11-23 17:07:34 +09:00
Randy Mackay
69e81587e2 TradHeli: add accessor for phase_angle 2013-11-23 17:07:32 +09:00
Randy Mackay
edcf347b10 TradHeli: set throttle_min to zero by default 2013-11-23 17:07:31 +09:00
Randy Mackay
dc6375f343 TradHeli: remove calls to get_manual_collective in auto throttle
set_collective_for_landing method makes this unnecessary
2013-11-23 17:07:29 +09:00
Randy Mackay
214b403586 TradHeli: angle error to zero while motors runup
Set angle error to zero in get_roll_rate_stabilized_bf,
get_pitch_rate_stabillize_bf, get_yaw_rate_stabilized_bf.
Original commit by Rob Lefebvre
2013-11-23 17:07:27 +09:00
Randy Mackay
099ca84754 TradHeli: move STAB_COL_MIN to main parameter list 2013-11-23 17:07:26 +09:00
Randy Mackay
ea32cc0a2f TradHeli: add RSC_RUNUP_TIME param and rotor speed estimate 2013-11-23 17:07:24 +09:00
Randy Mackay
e860419bae TradHeli: ext gyro gain range 0 to 1000 2013-11-23 17:07:23 +09:00
Randy Mackay
554ee5df66 TradHeli: move pilot desired rotor speed to heli.pde 2013-11-23 17:07:21 +09:00
Randy Mackay
43b0c4f0f4 Copter: remove unused init_rate_controllers 2013-11-23 17:07:19 +09:00
Randy Mackay
6c5f2e6368 Copter: add deadzone to ch8 for TradHeli 2013-11-23 17:07:18 +09:00
Randy Mackay
e619e30a70 Copter: log TradHeli ch7, ch8 in MOT message 2013-11-23 17:07:16 +09:00
Randy Mackay
680fe72937 TradHeli: integrate constructor changes to main code 2013-11-23 17:07:15 +09:00
Randy Mackay
c4ae641c81 TradHeli: ramp up changes
Rewrote tail and main rotor ramp up methods
Moved direct drive ESC speed control into rsc_control method
Pass in ch7 servo as servo_aux to TradHeli motors object constructor
split CH7_SETPOINT parameter into GYR_GAIN and DIRECTDRIVE parameters
replaced RSC_RATE with uint8_t RSC_RAMP_TIME parameter
rename GOV_SETPOINT parameter to RSC_SETPOINT
RSC_MODE parameter description updated to indicate it controls the
source of main rotor speed
2013-11-23 17:07:13 +09:00
Robert Lefebvre
a0a4ea4904 TradHeli: BugFix to ColYaw
Credit to Jolyon Saunders for finding this bug.
2013-11-23 17:07:11 +09:00
Robert Lefebvre
0e2b0a8079 TradHeli: ch6 tuning of ext gyro to use control_in
This could also be used to control the other Heli Ch7 functions (direct drive tail rotor control).  This should be tidied up.

Credit: Jolyon Saunders
2013-11-23 17:07:10 +09:00
Robert Lefebvre
920641931a TradHeli: COLYAW not applied when the motor is not running 2013-11-23 17:07:08 +09:00
Robert Lefebvre
a81922d5fb TradHeli: add support for drive tail rotors
Repurposed external gyro and made it multi-funcitonal.
required PWM on Ch8 to start the motor in RSC Mode moved up from 100 to 400. This is to facilitate two-stage switching of the motors with PWM>100 starting the tail motor, and PWM>400 starting the main motor.
Additional amendments by Randy
2013-11-23 17:07:06 +09:00
Robert Lefebvre
7240765342 TradHeli: Use Leaky Integrator on Yaw Rate controller
Use when rotor is not running to prevent the rudder from slowly moving over
2013-11-23 17:07:05 +09:00
Randy Mackay
0734c13fb4 TradHeli: use landing collective when landed or landing 2013-11-23 17:07:03 +09:00
Randy Mackay
87bd57c9aa TradHeli: add landing collective min 2013-11-23 17:07:02 +09:00
Randy Mackay
15dacea70e Copter: initialise roll, pitch, yaw modes to stabilize
This fixes a bug in which the stabilize throttle controller would be
non-tilt compensated until the user switched to another flight mode and
back again
2013-11-23 17:07:00 +09:00
Randy Mackay
20b2fb7680 TradHeli: add THROTTLE_MANUAL_HELI
Move check_dynamic_flight to run as scheduled task
2013-11-23 17:06:58 +09:00
Randy Mackay
537b4aef38 TradHeli: add get_pilot_desired_collective
Perhaps this should be moved to the main code's heli.pde sketch
2013-11-23 17:06:57 +09:00
Randy Mackay
ab076d002f TradHeli: bugfix to update swash in run_rate_controllers 2013-11-23 17:06:55 +09:00
Randy Mackay
cd538624a0 TradHeli: formatting and param description changes 2013-11-23 17:06:54 +09:00
Randy Mackay
68cc55e98f TradHeli: integrate motor lib changes 2013-11-23 17:06:52 +09:00
Randy Mackay
9172b92fb8 TradHeli: make parameters and variables private
add accessors for variables and params required in main code
replace tabs with spaces
2013-11-23 17:06:50 +09:00
Randy Mackay
259a3296d1 TradHeli: remove setup via CLI
Saves 6k of flash
2013-11-23 17:06:49 +09:00
Randy Mackay
3ebc4e5ede Copter: formatting and param description changes 2013-11-23 17:06:47 +09:00
Robert Lefebvre
7eb43973af Copter: verify_takeoff() should set ap.takeoff_complete to True after the takeoff is complete. 2013-11-23 17:06:46 +09:00
Robert Lefebvre
f9b547061e TradHeli: Add Motor Runup check to the auto_arming check. 2013-11-23 17:06:44 +09:00
Robert Lefebvre
0941615495 TradHeli: Modify Throttle_Auto to prevent helis from pushing hard downward while running up the motor. We will set the collective pitch to stab_col_min which should result in a mild downward pressure if the user has set their parameters correctly. 2013-11-23 17:06:43 +09:00
Robert Lefebvre
c6294eb561 TradHeli: Modify the constrain on the auto throttle controller to prevent it from commanding full down collective if we think we are on the ground still. 2013-11-23 17:06:41 +09:00
Randy Mackay
8e5b398b79 TradHeli: dynamic_flight flag based on inertial nav speed
Created new heli.pde for heli_integrated_swash and check_dynamic_flight
2013-11-23 17:06:39 +09:00
Robert Lefebvre
6f54d63f6f TradHeli: Bug Fix on Dynamic Flight / TakeOff Detector 2013-11-23 17:06:38 +09:00
Robert Lefebvre
2438330b40 TradHeli: Move Take-off Complete flag from the throttle controller, and into the Dynamic Flight check. This is to prevent false positive where the collective is pushed up before the motor is started. 2013-11-23 17:06:36 +09:00
Robert Lefebvre
c60ff46cc5 TradHeli: leaky-I-term based on dynamic_flight_detector 2013-11-23 17:06:35 +09:00
Randy Mackay
19716e21b5 HAL: MPU6k and Baro SPI to 8Mhz 2013-11-23 17:06:33 +09:00
Andrew Tridgell
5999a468ac HAL_AVR: force all devices on SPI0 to low speed when one is low speed
this forces MS5611 to low speed when MPU6K is low speed
2013-11-23 17:06:32 +09:00
Randy Mackay
bea7e4c9bc Copter: ARMING_CHECK made into bitmask
Allows arming checks to be individually enabled or disabled for baro,
compass, GPS, INS, parameters, RC and board voltage
2013-11-23 17:06:30 +09:00
Randy Mackay
32b99867b9 Copter: pre-arm check of INS health 2013-11-23 17:06:28 +09:00
Andrew Tridgell
844d93f362 AP_InertialSensor: use fabsf() 2013-11-23 17:06:27 +09:00
Andrew Tridgell
0cb1325ede AP_InertialSensor: added INS_PRODUCT_ID values 2013-11-23 17:06:25 +09:00
Randy Mackay
eed7ad36b9 CopterMotors: fix example sketch 2013-11-23 17:06:24 +09:00
Randy Mackay
f461a0b55a Copter: remove unused variable from Single copter 2013-11-23 17:06:22 +09:00
proficnc
0af6dff283 Update README.md
Updated build instruction link to the one on the Dev.Ardupilot wiki
2013-11-23 17:06:20 +09:00
Jason Short
44d64a84d9 Copter: Drift Mode
Changes Toy mode declarations to Drift mode.
Requires GPS, Mode 2 transmitter
Drift mode mixes Roll, Pitch and Yaw into a single stick on mode two transmitters.
2013-11-23 17:06:19 +09:00
Randy Mackay
10158185d5 Copter: reject change_command if not in AUTO 2013-11-23 17:06:17 +09:00
Randy Mackay
bc4b2ff05d Copter: disarm routine shortcut
Extra check so we only run the disarm check when we are actually armed.
The ground stations sometimes send many disarm messages which can be
ignored
2013-11-23 17:06:16 +09:00
Randy Mackay
ec73169c02 Copter: parameter files for beg, int, adv and camera ship 2013-11-23 17:06:14 +09:00
Randy Mackay
919b26d28f GPS Glitch: revert accel max to 10m/s/s
This may not be the best real world value but it keeps the autotester
from failing because it recovers from the glitch before the 5second
time-out on the GPS failsafe
2013-11-23 17:06:12 +09:00
Randy Mackay
f0970fc4be Copter: range check pilot requested lean angles
This fixes a bug uncovered by MHA in which the receiver output 900 pwm
for roll and pitch to the APM which was interpreted as requesting an 80
deg lean angle which the copter then attempted to do!
2013-11-23 17:06:11 +09:00
Randy Mackay
5a726ace9b Copter: add @User and @Increment to motor params description 2013-11-23 17:06:09 +09:00
Randy Mackay
19b02f47ea Copter: default SPIN_WHEN_ARMED to zero 2013-11-23 17:06:08 +09:00
Randy Mackay
17b0921f17 GPS Glitch: radius and accel max to 5m and 5m/s/s 2013-11-23 17:06:06 +09:00
Andrew Tridgell
6062dd6d00 build: added new copter frame type 'single' 2013-11-23 17:06:04 +09:00
Andrew Tridgell
aaa9bbac6e build: fixed build_all for heli 2013-11-23 17:06:03 +09:00
Andrew Tridgell
2a776c4466 build: support all copter frame types on all boards 2013-11-23 17:06:01 +09:00
Randy Mackay
898fa2f2a1 Copter: move SINGLE parameters to start at 75 2013-11-23 17:06:00 +09:00
Randy Mackay
e138a12f80 Copter: add SINGLE_FRAME definition 2013-11-23 17:05:58 +09:00
Randy Mackay
586e5a0162 SingleCopter: formatting changes
replace tab with 4-spaces
remove blank lines
2013-11-23 17:05:56 +09:00
ssq870424
374f341c76 Copter: add support for singlecopter airframe
this is the newest singlecopter airframe programme.
This kind of aerial vehicles include Honeywell T-hawk and Goldeneye.
2013-11-23 17:05:55 +09:00
Randy Mackay
0a911f83bf Iris: remove ATTTITUDE_FAST, PID and OPTFLOW logging 2013-11-23 17:05:53 +09:00
Randy Mackay
1bbc7d7185 Copter: gps failsafe disabled until we get first 3d lock 2013-11-23 17:05:52 +09:00
Randy Mackay
acd5846994 Copter: bug fix to take-off in Loiter and AltHold
Always set the target altitude after take-off to be current altitude +
20cm.  This resolves a bug in which the target altitude could end up
being a couple of meters higher than the current altitude if the user
entered Loiter / Alt Hold mode before inertial nav altitude estimate had
settled.
2013-11-23 17:05:50 +09:00
Randy Mackay
259988a0be Copter: GPS ok only when not glitching
Removed redundant checks to GPS_ok before setting flight mode to RTL
(this check is already performed inside the set_mode function)
Removed reset of home distance and bearing when GPS lock is lost, it now
remains at the last known value
2013-11-23 17:05:48 +09:00
Randy Mackay
b33ea01366 Copter: force gyro calibration on start-up 2013-11-23 17:05:47 +09:00
Andrew Tridgell
41f9eebb32 AP_InertialSensor: make PX4 healthy call _get_sample()
this prevents a false positive during times like arming where we are
not reading the sensors
2013-11-23 17:05:45 +09:00
Andrew Tridgell
8114df083f Plane: make batter failsafe docs clearer 2013-11-23 17:05:44 +09:00
Andrew Tridgell
8a68fd236d AP_L1_Control: fixed switchover from loiter capture to circling
Pair-Programmed-With: Paul Riseborough <p_riseborough@live.com.au>
2013-11-23 17:05:42 +09:00
Paul Riseborough
4d2fe4a488 L1_Control : Added hysteresis for rear WP capture 2013-11-23 17:05:40 +09:00
Andrew Tridgell
49bd45cf3a AP_L1_Control: fixed waypoint approach logic
this could cause the RTL approach to not break off onto the circle
correctly
2013-11-23 17:05:39 +09:00
Andrew Tridgell
d435547cf8 AP_InertialSensor: fixed semaphore error on startup for MPU6000 2013-11-23 17:05:37 +09:00
Andrew Tridgell
cccdf27dd2 DataFlash: print FMT messages for wrapped logs
this ensures we have FMT messages in every log, even if the log was
wrapped and the FMT messages were overwritten
2013-11-23 17:05:36 +09:00
Andrew Tridgell
1bec20482f Copter: show git and firmware version in tlog 2013-11-23 17:05:34 +09:00
Andrew Tridgell
407bbed179 Rover: show git and firmware version in tlog 2013-11-23 17:05:32 +09:00
Andrew Tridgell
4cd6040064 Plane: send firmware and git version in tlog 2013-11-23 17:05:31 +09:00
Andrew Tridgell
dccc86957f build: added GIT_VERSION define to Makefile build 2013-11-23 17:05:29 +09:00
Andrew Tridgell
10d2e9a9b6 Plane: update comments on ALT_CTRL_ALG and NAV_CONTROLLER 2013-11-23 17:05:28 +09:00
Andrew Tridgell
a2ea323512 Plane: removed unused variable 2013-11-23 17:05:26 +09:00
Andrew Tridgell
70b0bb475f AP_AHRS: detect and try to cope with bad accels 2013-11-23 17:05:24 +09:00
Andrew Tridgell
74bf82a09b AP_InertialSensor: added healthy check for PX4 and HIL
used to detect bad accels
2013-11-23 17:05:23 +09:00
Andrew Tridgell
8a5729de0a SITL: added SIM_ACCEL_FAIL option
used to test accelerometer failure in flight
2013-11-23 17:05:21 +09:00
Andrew Tridgell
0c5caac632 AP_Airspeed: added healthy() API 2013-11-23 17:05:20 +09:00
Andrew Tridgell
b62ad0d5fb Plane: report INS and airspeed health 2013-11-23 17:05:18 +09:00
Andrew Tridgell
f182169c01 Copter: report INS health 2013-11-23 17:05:16 +09:00
Andrew Tridgell
d8fbfb8ddd Rover: report INS health 2013-11-23 17:05:15 +09:00
Andrew Tridgell
d87b50c35c AP_Baro: start MS5611 at high speed 2013-11-23 17:05:13 +09:00
Andrew Tridgell
ee2fb33567 AP_InertialSensor: detect bad MPU6000 SPI transactions and lower bus speed
this uses bad data or bad INT_STATUS values from the MPU6000 to detect
the sensor running too fast and lower bus speed
2013-11-23 17:05:12 +09:00
Andrew Tridgell
8e55ab5072 AP_Math: fixed zero function for integer vectors 2013-11-23 17:05:10 +09:00
Andrew Tridgell
23eed03852 AP_InertialSensor: automatically lower bus speed on mpu6k bad reads 2013-11-23 17:05:09 +09:00
Andrew Tridgell
f049d19aa3 AP_InertialSensor: try to lower SPI bus speed on errors 2013-11-23 17:05:07 +09:00
Andrew Tridgell
0bda21a3fc HAL_AVR: changed to 16 byte bulk transfer on SPI0 2013-11-23 17:05:05 +09:00
Andrew Tridgell
e3966bdab6 Plane: allow changing of loiter direction while loitering
useful for causing path capture failures in the sim
2013-11-23 17:05:04 +09:00
Craig3DRobotics
69a00ee4b1 Iris: Enable logging of all message types 2013-11-23 17:05:02 +09:00
Andrew Tridgell
9398fa730e Plane: log the AHRS error terms in dataflash
also log raw IMU at 10Hz with default config
2013-11-23 17:05:01 +09:00
Andrew Tridgell
08e1ce428a DataFlash: make the SITL dataflash log 4x larger 2013-11-23 17:04:59 +09:00
Andrew Tridgell
0967aec802 AP_Menu: fixed double display of prompt 2013-11-23 17:04:57 +09:00
Andrew Tridgell
83f8dd150e AP_Menu: added check_for_input() API
this allows for async use of the menus, so that a main loop can run
while allowing the user to enter menu commands
2013-11-23 17:04:56 +09:00
Andrew Tridgell
ff5ddde905 AP_Menu: zero buffer contents on allocation 2013-11-23 17:04:54 +09:00
Andrew Tridgell
a24e3b555e AP_Menu: dynamically allocate the menu buffers
this saves memory when the menus are not used, and allows for the
commandline and argument limits to be changed
2013-11-23 17:04:52 +09:00
Andrew Tridgell
de4d5add6c autotest: raise timelimits again 2013-11-23 17:04:51 +09:00
Andrew Tridgell
85c48e7b41 Plane: prepare for 2.76 release 2013-11-23 17:04:49 +09:00
Andrew Tridgell
01a32d0632 AP_GPS: try harder to get 5Hz updates from a uBlox
check for getting at least one 5Hz update every 15s
2013-11-23 17:04:48 +09:00
Andrew Tridgell
522f248b63 AP_AHRS: lower default roll and yaw drift correction speed
the gyros sustain accuracy over much longer time periods than
previously expected
2013-11-23 17:04:46 +09:00
Andrew Tridgell
97d8007b08 HAL_PX4: don't check USB for data if not connected 2013-11-23 17:04:44 +09:00
Andrew Tridgell
9f36acbb92 HAL_PX4: switch to delay_microseconds_semaphore() for UART timer
this may prevent some timing jitter on the GPS UARTs
2013-11-23 17:04:43 +09:00
Andrew Tridgell
674ec54b5f Plane: only send GPS_RAW_INT if new data
this reduces link load when asking for high rate telemetry
2013-11-23 17:04:41 +09:00
Andrew Tridgell
1875bbe7d6 Plane: make DataFlash objects static 2013-11-23 17:04:39 +09:00
Andrew Tridgell
6fe3004fcc Plane: added time to most plane log messages 2013-11-23 17:04:38 +09:00
Andrew Tridgell
e2991c0f35 DataFlash: added APM time and GPS velz to logged GPS messages 2013-11-23 17:04:36 +09:00
Andrew Tridgell
fea10c3b97 AP_TECS: added time to TECS messages 2013-11-23 17:04:35 +09:00
Andrew Tridgell
4a60319f79 autotest: fixed clean build 2013-11-23 17:04:33 +09:00
Andrew Tridgell
d722e7024a Plane: prevent too large combined pitch/roll angles
this reduces the roll limit by cos(pitch) and pitch minimum by
cos(roll). This prevents unreasonable attitudes in all stabilised
modes

Pair-Programmed-With: Paul Riseborough <p_riseborough@live.com.au>
2013-11-23 17:04:32 +09:00
Andrew Tridgell
c18d1da019 AP_L1_Control: reduced demanded bank angle by cos(pitch)
this prevents attempts to do too tight turns while at a steep pitch

Pair-Programmed-With: Paul Riseborough <p_riseborough@live.com.au>
2013-11-23 17:04:30 +09:00
Andrew Tridgell
ffde756d7e APM_Control: reduce roll compensation in pitch controller by cos(pitch)
This reduces the use of the pitch compensation when in a steep climb
or dive

Pair-Programmed-With: Paul Riseborough <p_riseborough@live.com.au>
2013-11-23 17:04:28 +09:00
Andrew Tridgell
b22ce9843a DataFlash: added timestamp to IMU and VelZ to GPS logging
both are very useful for analysis
2013-11-23 17:04:27 +09:00
Andrew Tridgell
92a52f5e4a AP_AHRS: added accel sum delay buffer to account for GPS lag 2013-11-23 17:04:25 +09:00
Andrew Tridgell
2f5098598d Rover: update for AHRS API changes 2013-11-23 17:04:24 +09:00
Andrew Tridgell
dca5bee080 Copter: update for AHRS API changes 2013-11-23 17:04:22 +09:00
Andrew Tridgell
8d0d8a05c0 Plane: update for API changes 2013-11-23 17:04:20 +09:00
Andrew Tridgell
4da580e229 VARTest: update for AHRS API change 2013-11-23 17:04:19 +09:00
Andrew Tridgell
f0d5cde9cf AP_InertialNav: update for AHRS API changes 2013-11-23 17:04:17 +09:00
Andrew Tridgell
fc920df8d4 AP_InertialSensor: use const reference returns
saves some vector copies
2013-11-23 17:04:16 +09:00
Andrew Tridgell
a18582673d AP_TECS: update for AHRS API change 2013-11-23 17:04:14 +09:00
Andrew Tridgell
14d2453216 DataFlash: use const ins reference
save some pointer dereferences
2013-11-23 17:04:13 +09:00
Andrew Tridgell
b258a63b8c AP_YawController: update for AHRS API change 2013-11-23 17:04:11 +09:00
Andrew Tridgell
41d0fda92c AC_Fence: update for AHRS API changes 2013-11-23 17:04:09 +09:00
Andrew Tridgell
3004ed9c41 AP_AHRS: save memory and reduce pointer references
use a refence for ins, and don't save gyro and accel between updates
2013-11-23 17:04:08 +09:00
Andrew Tridgell
a69ecfa06b AP_AHRS: removed limit on normalisation of accel reference vectors
this could lead to a bias in the accel drift correction
2013-11-23 17:04:06 +09:00
Andrew Tridgell
f9c72f9dbf AP_AHRS: removed vertical G limit on GPS velocity correction
this limit could lead to a bias in the accel drift correction, and is
frequenctly exceeded
2013-11-23 17:04:05 +09:00
Andrew Tridgell
820ec465c7 AP_AHRS: fixed wrapping bug in GPS based heading error
this bug could cause the GPS based yaw to use an expensive reset far
too often
2013-11-23 17:04:03 +09:00
Andrew Tridgell
1c9dfb9b8a AP_AHRS: prevent GPS yaw resets on compass errors
when we switch from compass heading to GPS heading we don't want to
trigger a sudden GPS yaw reset
2013-11-23 17:04:01 +09:00
Andrew Tridgell
81ddab4ea8 AP_Notify: make APM2 ToshibaLED driver more efficient
use one I2C transfer, not 3
2013-11-23 17:04:00 +09:00
Randy Mackay
917d9226b2 Copter: formatting fix to config.h 2013-11-23 17:03:58 +09:00
Robert Lefebvre
05397bc024 TradHeli: Change user description for COLYAW parameter. 2013-11-23 17:03:57 +09:00
Robert Lefebvre
7e49f630ad TradHeli: Change default Auto-Yaw to Yaw Look Ahead
This leads to smoother flight in Auto modes, particularly with fast waypoints.
2013-11-23 17:03:55 +09:00
Jason Short
558dd6db04 Copter: updated toy gains 2013-11-23 17:03:53 +09:00
Jason Short
b9a4a7e0bf InertialNav: fix for get_velocity_xy
forgot to sq
2013-11-23 17:03:52 +09:00
Randy Mackay
8e68ca931b AutoTest: remove unnecessary wait from SaveWP test 2013-11-23 17:03:50 +09:00
Randy Mackay
6f29ba3da9 AutoTest: wait 1sec when saving wp 2013-11-23 17:03:49 +09:00
Randy Mackay
fcf188646f AutoTest: copter ch7 option to SaveWP 2013-11-23 17:03:47 +09:00
Jason Short
945b9260b5 Copter: CH7 SaveWP fix corner case
If the user is on the ground and flips CH7, do nothing instead of recording a bad takeoff altitude. Do another check to avoid a land right after a takeoff.
2013-11-23 17:03:46 +09:00
Randy Mackay
bb0f18e2d4 Copter: remove unused get_acro_yaw 2013-11-23 17:03:44 +09:00
Jason Short
cbbd3ae50e Copter: remove unused Toy param 2013-11-23 17:03:42 +09:00
Jason Short
60775e94b9 Copter: TOY mode updates 2013-11-23 17:03:41 +09:00
Jason Short
55b22f8635 InertialNav: added get_velocity_xy 2013-11-23 17:03:39 +09:00
Andrew Tridgell
94deb1d599 Plane: mark 2.76beta1 2013-11-23 17:03:37 +09:00
Andrew Tridgell
36b52b65e1 Rover: fixed PM message 2013-11-23 17:03:36 +09:00
Andrew Tridgell
8775593402 Plane: fixed PM message 2013-11-23 17:03:34 +09:00
Paul Riseborough
e3a96094ca AP_Airspeed : Fixes bug that caused airspeed calibration to be sent a zero airspeed
This bug resulted in the airspeed ratio going to the maximum value of 4 and staying there. This could lead to a very slow flying model and a stall.
2013-11-23 17:03:33 +09:00
Andrew Tridgell
3c19ea050c Plane: added altitude and ground speed to NTUN logs 2013-11-23 17:03:31 +09:00
Andrew Tridgell
3e6a17a89f AP_InertialSensor: SITL doesn't use Oilpan code any more 2013-11-23 17:03:29 +09:00
Andrew Tridgell
50ef260d69 Plane: faster startup
make it less likely to send wrong INS_PRODUCT_ID, plus don't waste as
much time
2013-11-23 17:03:28 +09:00
Andrew Tridgell
8cefe8e198 PX4: changed startup to fail if no px4io on FMUv2 2013-11-23 17:03:26 +09:00
Andrew Tridgell
4194b2fdd7 Copter: int gyros on arm, not on first boot
this makes first boot much faster
2013-11-23 17:03:25 +09:00
Randy Mackay
d06d999903 Copter: arming check that throttle is above failsafe 2013-11-23 17:03:23 +09:00
Randy Mackay
a692790342 Copter: disable autotune if pilot moves yaw stick 2013-11-23 17:03:22 +09:00
Randy Mackay
81ac548e2c Copter: recalc distance to home during arming
fixes an rare edge case in which the fence could trigger immediately
after arming
2013-11-23 17:03:20 +09:00
Randy Mackay
c824ccfb38 Copter: more Ch7/Ch8 event logging
Additional event logging for SaveWP, Fence, Acro trainer, Save Trim
2013-11-23 17:03:18 +09:00
Randy Mackay
249c757b94 Copter: default Ch7 to DO_NOTHING
Ch7/Ch8 Save_WP feature triggers when switch is brought high (instead of
low) to be consistent with other aux features
2013-11-23 17:03:17 +09:00
Randy Mackay
12093f4dd6 Copter: rc10, rc11 available even without MOUNT 2013-11-23 17:03:15 +09:00
Randy Mackay
b98f11d819 RC_Channel: formatting 2013-11-23 17:03:14 +09:00
Randy Mackay
1a8feee298 Copter: disable some aux channels on hexa and octas
Resolves issue #324
2013-11-23 17:03:12 +09:00
Randy Mackay
2240bb80d1 Copter: correct @Range of MOT_TCRV_MAXPCT parameter 2013-11-23 17:03:10 +09:00
Randy Mackay
7f8e9ea27f Copter: remove some commented out send_text code 2013-11-23 17:03:09 +09:00
Randy Mackay
3e139adf08 Copter: add alt and throttle checks to crash detector 2013-11-23 17:03:07 +09:00
Randy Mackay
30d908e2fa Copter: crash checker
Crash is determined to have happened when the copter is 20deg more than
the ANGLE_MAX parameter continuously for more than 2 seconds
Not activated when in ACRO mode or while flipping
2013-11-23 17:03:05 +09:00
Andrew Tridgell
d4af757cbb AP_Airspeed: fixed I2C semaphore handling for I2C airspeed
this affects MS4525DO on APM2
2013-11-23 17:03:04 +09:00
Randy Mackay
b4c8dd5a41 Copter: add ANGLE_RATE_MAX param
Limits the maximum rotation rate requested by the angle controller which
is used in stabilize, loiter, rtl and auto flight modes
2013-11-23 17:03:02 +09:00
Randy Mackay
05cf1015fc Copter: add @Increment to battery failsafe descriptions 2013-11-23 17:03:00 +09:00
Randy Mackay
9a6433eeeb Plane: add @Increment to battery failsafe descriptions 2013-11-23 17:02:59 +09:00
Randy Mackay
c6a6fb29df BattMonitor: add @Increment to CAPACITY description 2013-11-23 17:02:57 +09:00
Randy Mackay
e596bbe147 BoardLEDs: all leds off during init 2013-11-23 17:02:55 +09:00
Andrew Tridgell
c700f61ffa Copter: fixed HIL build 2013-11-23 17:02:54 +09:00
Andrew Tridgell
3a5e21ab93 Plane: ready for 2.75 release 2013-11-23 17:02:52 +09:00
Andrew Tridgell
ea81b05e47 Rover: fixed performance monitoring
now the same as plane
2013-11-23 17:02:51 +09:00
Andrew Tridgell
b91274f44c Plane: improved perf monitoring with SCHED_DEBUG 2013-11-23 17:02:49 +09:00
Andrew Tridgell
3b72741e15 HAL_AVR: switch back to 500kHz SPI for MPU6k until we understand the issues
this is for new plane release. We need for analysis before we can
re-enable high speed SPI
2013-11-23 17:02:48 +09:00
Andrew Tridgell
f1ebd036b0 Copter: fixed baro-only preflight cal
this was causing a full level, which mucked up the INS calibration
2013-11-23 17:02:46 +09:00
Andrew Tridgell
7c4067e154 HAL_PX4: prevent excessive writes on startup from blocking
this could cause copter on PX4 to hang on startup
2013-11-23 17:02:44 +09:00
Randy Mackay
eee7a1de22 Copter: remove unused #defines from config.h 2013-11-23 17:02:43 +09:00
Randy Mackay
9a6c61d42f Copter: add features that can be disabled to APM_Config.h 2013-11-23 17:02:41 +09:00
Andrew Tridgell
91c3b669c7 Plane: allow parameters to download at full speed 2013-11-23 17:02:40 +09:00
Andrew Tridgell
53a9d2745c Rover: removed fast_loop() and use scheduler for all tasks
this also fixes a parameter download speed issue
2013-11-23 17:02:38 +09:00
Randy Mackay
7157a44fdb AC_Fence: fix example sketch 2013-11-23 17:02:36 +09:00
Andrew Tridgell
d4fdead45a AP_InertialNav: fixed example build 2013-11-23 17:02:35 +09:00
Randy Mackay
e563a236ab AP_InertialNav: remove unused velocity fns
remove get_longitude_velocity and get_latitude_velocity
2013-11-23 17:02:33 +09:00
Randy Mackay
8b293f10a4 Copter: remove ins from InertialNav object instantiation 2013-11-23 17:02:32 +09:00
Randy Mackay
bf062cc4bb AP_InertialNav: add comments, make ahrs const from neurocopter
These fixes are provided by neurocopter but with my name because of
merge conflicts
_position and _velocity vectors added to save some floating point add
operations
unused reference to ins in constructor removed
2013-11-23 17:02:30 +09:00
Tobias
aac51eb670 Copter/position_vector: remove const specifiers on objects returned by
value
2013-11-23 17:02:29 +09:00
Tobias
c34de8d9ad AP_Buffer: remove header/source separation to allow arbitrary template
parameters without explicit instantiation in the cpp file.

http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
2013-11-23 17:02:27 +09:00
Randy Mackay
16baa7557c AP_InertialNav: bug fix for gps delay handling 2013-11-23 17:02:25 +09:00
Tobias
01074f9839 AP_InertialNav: rename AP_Buffer functions, fix delay handling bug
The most recent value was used instead of the intended historical value
as indicated by the comment.
2013-11-23 17:02:24 +09:00
Tobias
a809d57e4b AP_Buffer: add comments and rename functions to conform with the
STL-container naming conventions
Comment format changes by Randy
2013-11-23 17:02:22 +09:00
Tobias
a19093b1c4 AP_InertialNav: move variable definitions to elide unused default
construction of objects (saves 106 bytes)
2013-11-23 17:02:21 +09:00
Tobias
ec72095fc2 AC_WPNav: make more member pointers const 2013-11-23 17:02:19 +09:00
Tobias
de9778ae1c AC_WPNav: make member pointer to AP_InertialNav object const since it's
never modified
2013-11-23 17:02:17 +09:00
Tobias
7377d4a5f1 AC_Fence: replace "_ina->geT_position().z" with more efficent
"_inav->get_altitude()"
2013-11-23 17:02:16 +09:00
Tobias
89173656c5 AC_Fence: make member pointer to AP_InertialNav const, remove unused
gps-pointer member
2013-11-23 17:02:14 +09:00
Tobias
3b718e8dd5 Copter: use const refs instead of unneeded copies 2013-11-23 17:02:12 +09:00
Randy Mackay
3e9e0f82aa AC_Sprayer: add doxygen info 2013-11-23 17:02:11 +09:00
Tobias
43be74c60a AC_WPNav: replace unnecessary objects with const refs 2013-11-23 17:02:09 +09:00
Tobias
a56efe837f AC_Sprayer: replace unnecessary object with const ref 2013-11-23 17:02:08 +09:00
Tobias
e313647aa0 Copter: Log.pde: replace unused copy with ref (saves again some bytes) 2013-11-23 17:02:06 +09:00
Tobias
176096df4e AC_Sprayer: add consts, update comments
* removed some comments that were left over from the classes this class
was copypasta'ed from
2013-11-23 17:02:05 +09:00
Tobias
07a95b398d Filter: add consts 2013-11-23 17:02:03 +09:00
Tobias
c02c8806cc AP_Baro: add time-unit comment 2013-11-23 17:02:02 +09:00
Tobias
ac463652f4 Copter: add comment (unit of G_Dt) 2013-11-23 17:02:00 +09:00
Tobias
9a743d0444 AP_InertialNav: remove unused AP_InertialSensor pointer 2013-11-23 17:01:59 +09:00
Tobias
9fb8352d32 AP_InertialNav: add comments, rename incorrectly named member,
initialize member, remove redundant assignment
adjustments to original commit by randy
2013-11-23 17:01:58 +09:00
Andrew Tridgell
61d4134ba9 HAL_Linux: fixed scheduler initialisation bug in Linux HAL as well 2013-11-23 17:01:56 +09:00
Andrew Tridgell
13d9103a83 HAL_PX4: prevent threads running before subsystems are initialised
this fixes a bug where the timer thread would hang waiting for the
console on startup. This caused the "hit enter" behaviour with recent
PX4 bugs, as AnalogIn tried to read from fd==0, which was a console
read
2013-11-23 17:01:55 +09:00
Andrew Tridgell
d1bdca301b Plane: tag 2.75beta5 2013-11-23 17:01:54 +09:00
Paul Riseborough
8e8f3f87d9 APM_Control : Moved scaler on roll and pitch integrator to be before integrator
This means that the value of aileron and elevator trim offset won't change with airspeed
2013-11-23 17:01:52 +09:00
Randy Mackay
c7d16d2c3b Copter: remove unnecessary check of flight mode from fence response 2013-11-23 17:01:51 +09:00
Randy Mackay
fcc1b8e190 Copter: report RC receiver health to GCS 2013-11-23 17:01:50 +09:00
Randy Mackay
ebd60ebcdc GCS_MAVLink: generate after adding RC reciever to SYS_STATUS enum 2013-11-23 17:01:48 +09:00
Randy Mackay
65f69dcfdb GCS_MAVLink: add RC receiver to SYS_STATUS enum 2013-11-23 17:01:47 +09:00
Andrew Tridgell
04cca7aee6 AntennaTracker: first cut at antenna tracking sketch 2013-11-23 17:01:46 +09:00
Andrew Tridgell
191c104748 AP_GPS: fixed date handling in NMEA driver 2013-11-23 17:01:44 +09:00
Andrew Tridgell
e11dbb4803 HAL_SITL: fixed time strings in simulated NMEA GPS 2013-11-23 17:01:43 +09:00
Andrew Tridgell
0fd28e3e99 Copter: set system time on GPS lock 2013-11-23 17:01:42 +09:00
Andrew Tridgell
11d127b66b Rover: set system time on GPS lock 2013-11-23 17:01:40 +09:00
Andrew Tridgell
45493cc67a Plane: set system time on GPS lock 2013-11-23 17:01:39 +09:00
Andrew Tridgell
4eefd2683b DataFlash: show timestamps on flash logs 2013-11-23 17:01:38 +09:00
Andrew Tridgell
304737ade3 HAL_PX4: implement set_system_clock() 2013-11-23 17:01:36 +09:00
Andrew Tridgell
343b520d93 AP_HAL: added set_system_clock() API 2013-11-23 17:01:35 +09:00
Andrew Tridgell
d3dcae1b08 AP_GPS: added fake time to fake GPS lock 2013-11-23 17:01:34 +09:00
Andrew Tridgell
35e67f37c6 Rover: added MAVLink SYSTEM_TIME message 2013-11-23 17:01:32 +09:00
Andrew Tridgell
b68b624b30 Copter: added MAVLink SYSTEM_TIME message 2013-11-23 17:01:31 +09:00
Andrew Tridgell
4915315614 Plane: added MAVLink SYSTEM_TIME message 2013-11-23 17:01:29 +09:00
Andrew Tridgell
cdede70433 DataFlash: updates for new GPS API 2013-11-23 17:01:28 +09:00
Andrew Tridgell
0ad43b58a3 AP_InertialNav: updates for new GPS API 2013-11-23 17:01:27 +09:00
Andrew Tridgell
8084a71c02 HAL_SITL: properly emulate timestamps on ublox and MTK 2013-11-23 17:01:25 +09:00
Andrew Tridgell
3b2ba78aca AP_GPS: added support for GPS time in week/millisec
also adds time_epoch_usec() for MAVLink SYSTEM_TIME
2013-11-23 17:01:24 +09:00
Andrew Tridgell
3893e2ca92 HAL_SITL: get the ublox GPS timestamps right in SITL 2013-11-23 17:01:23 +09:00
Randy Mackay
ae89c028e5 Copter: remove unnecessary Log_Write_Optflow 2013-11-23 17:01:21 +09:00
Randy Mackay
d39de52e2f Copter: reenable optical flow by default
correct optflow test compile error
2013-10-23 20:43:14 +09:00
197 changed files with 7060 additions and 3060 deletions

2
.gitignore vendored
View File

@ -1,11 +1,13 @@
*~ *~
*.bin *.bin
*.cproject
*.d *.d
*.dll *.dll
*.exe *.exe
*.lst *.lst
*.o *.o
*.obj *.obj
*.project
*.px4 *.px4
*.pyc *.pyc
*.tlog *.tlog

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ArduPilotMega-Source@ardupilotone</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

View File

@ -252,7 +252,7 @@ AP_InertialSensor_Oilpan ins( &adc );
#error Unrecognised CONFIG_INS_TYPE setting. #error Unrecognised CONFIG_INS_TYPE setting.
#endif // CONFIG_INS_TYPE #endif // CONFIG_INS_TYPE
AP_AHRS_DCM ahrs(&ins, g_gps); AP_AHRS_DCM ahrs(ins, g_gps);
static AP_L1_Control L1_controller(ahrs); static AP_L1_Control L1_controller(ahrs);
@ -523,52 +523,56 @@ static float G_Dt = 0.02;
// Timer used to accrue data and trigger recording of the performanc monitoring log message // Timer used to accrue data and trigger recording of the performanc monitoring log message
static int32_t perf_mon_timer; static int32_t perf_mon_timer;
// The maximum main loop execution time recorded in the current performance monitoring interval // The maximum main loop execution time recorded in the current performance monitoring interval
static int16_t G_Dt_max = 0; static uint32_t G_Dt_max;
// The number of gps fixes recorded in the current performance monitoring interval // The number of gps fixes recorded in the current performance monitoring interval
static uint8_t gps_fix_count = 0; static uint8_t gps_fix_count = 0;
// A variable used by developers to track performanc metrics.
// Currently used to record the number of GCS heartbeat messages received
static int16_t pmTest1 = 0;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// System Timers // System Timers
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Time in miliseconds of start of main control loop. Milliseconds // Time in microseconds of start of main control loop.
static uint32_t fast_loopTimer; static uint32_t fast_loopTimer_us;
// Time Stamp when fast loop was complete. Milliseconds
static uint32_t fast_loopTimeStamp;
// Number of milliseconds used in last main loop cycle // Number of milliseconds used in last main loop cycle
static uint8_t delta_ms_fast_loop; static uint32_t delta_us_fast_loop;
// Counter of main loop executions. Used for performance monitoring and failsafe processing // Counter of main loop executions. Used for performance monitoring and failsafe processing
static uint16_t mainLoop_count; static uint16_t mainLoop_count;
// set if we are driving backwards
static bool in_reverse;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Top-level logic // Top-level logic
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* /*
scheduler table - all regular tasks apart from the fast_loop() scheduler table - all regular tasks should be listed here, along
should be listed here, along with how often they should be called with how often they should be called (in 20ms units) and the maximum
(in 20ms units) and the maximum time they are expected to take (in time they are expected to take (in microseconds)
microseconds)
*/ */
static const AP_Scheduler::Task scheduler_tasks[] PROGMEM = { static const AP_Scheduler::Task scheduler_tasks[] PROGMEM = {
{ read_radio, 1, 1000 },
{ ahrs_update, 1, 6400 },
{ read_sonars, 1, 2000 },
{ update_current_mode, 1, 1000 },
{ set_servos, 1, 1000 },
{ update_GPS, 5, 2500 }, { update_GPS, 5, 2500 },
{ navigate, 5, 1600 }, { navigate, 5, 1600 },
{ update_compass, 5, 2000 }, { update_compass, 5, 2000 },
{ update_commands, 5, 1000 }, { update_commands, 5, 1000 },
{ update_logging, 5, 1000 }, { update_logging, 5, 1000 },
{ gcs_retry_deferred, 1, 1000 },
{ gcs_update, 1, 1700 },
{ gcs_data_stream_send, 1, 3000 },
{ read_control_switch, 15, 1000 },
{ read_trim_switch, 5, 1000 },
{ read_battery, 5, 1000 }, { read_battery, 5, 1000 },
{ read_receiver_rssi, 5, 1000 }, { read_receiver_rssi, 5, 1000 },
{ read_trim_switch, 5, 1000 },
{ read_control_switch, 15, 1000 },
{ update_events, 15, 1000 }, { update_events, 15, 1000 },
{ check_usb_mux, 15, 1000 }, { check_usb_mux, 15, 1000 },
{ mount_update, 1, 500 }, { mount_update, 1, 600 },
{ gcs_failsafe_check, 5, 500 }, { gcs_failsafe_check, 5, 600 },
{ compass_accumulate, 1, 900 }, { compass_accumulate, 1, 900 },
{ update_notify, 1, 100 }, { update_notify, 1, 300 },
{ one_second_loop, 50, 3000 } { one_second_loop, 50, 3000 }
}; };
@ -610,66 +614,44 @@ void loop()
if (!ins.wait_for_sample(1000)) { if (!ins.wait_for_sample(1000)) {
return; return;
} }
uint32_t timer = millis(); uint32_t timer = hal.scheduler->micros();
delta_ms_fast_loop = timer - fast_loopTimer; delta_us_fast_loop = timer - fast_loopTimer_us;
G_Dt = (float)delta_ms_fast_loop / 1000.f; G_Dt = delta_us_fast_loop * 1.0e-6f;
fast_loopTimer = timer; fast_loopTimer_us = timer;
if (delta_us_fast_loop > G_Dt_max)
G_Dt_max = delta_us_fast_loop;
mainLoop_count++; mainLoop_count++;
// Execute the fast loop
// ---------------------
fast_loop();
// tell the scheduler one tick has passed // tell the scheduler one tick has passed
scheduler.tick(); scheduler.tick();
fast_loopTimeStamp = millis();
scheduler.run(19000U); scheduler.run(19500U);
} }
// Main loop 50Hz // update AHRS system
static void fast_loop() static void ahrs_update()
{ {
// This is the fast loop - we want it to execute at 50Hz if possible #if HIL_MODE != HIL_MODE_DISABLED
// ----------------------------------------------------------------- // update hil before AHRS update
if (delta_ms_fast_loop > G_Dt_max)
G_Dt_max = delta_ms_fast_loop;
// Read radio
// ----------
read_radio();
// try to send any deferred messages if the serial port now has
// some space available
gcs_send_message(MSG_RETRY_DEFERRED);
#if HIL_MODE != HIL_MODE_DISABLED
// update hil before dcm update
gcs_update(); gcs_update();
#endif #endif
// when in reverse we need to tell AHRS not to assume we are a
// 'fly forward' vehicle, otherwise it will see a large
// discrepancy between the mag and the GPS heading and will try to
// correct for it, leading to a large yaw error
ahrs.set_fly_forward(!in_reverse);
ahrs.update(); ahrs.update();
read_sonars();
if (g.log_bitmask & MASK_LOG_ATTITUDE_FAST) if (g.log_bitmask & MASK_LOG_ATTITUDE_FAST)
Log_Write_Attitude(); Log_Write_Attitude();
if (g.log_bitmask & MASK_LOG_IMU) if (g.log_bitmask & MASK_LOG_IMU)
DataFlash.Log_Write_IMU(&ins); DataFlash.Log_Write_IMU(ins);
// custom code/exceptions for flight modes
// ---------------------------------------
update_current_mode();
// write out the servo PWM values
// ------------------------------
set_servos();
gcs_update();
gcs_data_stream_send();
} }
/* /*
@ -787,9 +769,13 @@ static void one_second_loop(void)
counter++; counter++;
// write perf data every 20s // write perf data every 20s
if (counter == 20) { if (counter % 10 == 0) {
if (scheduler.debug() != 0) {
hal.console->printf_P(PSTR("G_Dt_max=%lu\n"), (unsigned long)G_Dt_max);
}
if (g.log_bitmask & MASK_LOG_PM) if (g.log_bitmask & MASK_LOG_PM)
Log_Write_Performance(); Log_Write_Performance();
G_Dt_max = 0;
resetPerfData(); resetPerfData();
} }
@ -832,6 +818,10 @@ static void update_GPS(void)
} else { } else {
init_home(); init_home();
// set system clock for log timestamps
hal.util->set_system_clock(g_gps->time_epoch_usec());
if (g.compass_enabled) { if (g.compass_enabled) {
// Set compass declination automatically // Set compass declination automatically
compass.set_initial_location(g_gps->latitude, g_gps->longitude); compass.set_initial_location(g_gps->latitude, g_gps->longitude);
@ -879,7 +869,12 @@ static void update_current_mode(void)
// and throttle gives speed in proportion to cruise speed, up // and throttle gives speed in proportion to cruise speed, up
// to 50% throttle, then uses nudging above that. // to 50% throttle, then uses nudging above that.
float target_speed = channel_throttle->pwm_to_angle() * 0.01 * 2 * g.speed_cruise; float target_speed = channel_throttle->pwm_to_angle() * 0.01 * 2 * g.speed_cruise;
in_reverse = (target_speed < 0);
if (in_reverse) {
target_speed = constrain_float(target_speed, -g.speed_cruise, 0);
} else {
target_speed = constrain_float(target_speed, 0, g.speed_cruise); target_speed = constrain_float(target_speed, 0, g.speed_cruise);
}
calc_throttle(target_speed); calc_throttle(target_speed);
break; break;
} }
@ -894,6 +889,10 @@ static void update_current_mode(void)
*/ */
channel_throttle->servo_out = channel_throttle->control_in; channel_throttle->servo_out = channel_throttle->control_in;
channel_steer->servo_out = channel_steer->pwm_to_angle(); channel_steer->servo_out = channel_steer->pwm_to_angle();
// mark us as in_reverse when using a negative throttle to
// stop AHRS getting off
in_reverse = (channel_throttle->servo_out < 0);
break; break;
case HOLD: case HOLD:

View File

@ -9,6 +9,9 @@ static bool in_mavlink_delay;
// true when we have received at least 1 MAVLink packet // true when we have received at least 1 MAVLink packet
static bool mavlink_active; static bool mavlink_active;
// true if we are out of time in our event timeslice
static bool gcs_out_of_time;
// check if a message will fit in the payload space available // check if a message will fit in the payload space available
#define CHECK_PAYLOAD_SIZE(id) if (payload_space < MAVLINK_MSG_ID_## id ##_LEN) return false #define CHECK_PAYLOAD_SIZE(id) if (payload_space < MAVLINK_MSG_ID_## id ##_LEN) return false
@ -158,6 +161,9 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) { if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS; control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS;
} }
if (!ins.healthy()) {
control_sensors_health &= ~(MAV_SYS_STATUS_SENSOR_3D_GYRO | MAV_SYS_STATUS_SENSOR_3D_ACCEL);
}
int16_t battery_current = -1; int16_t battery_current = -1;
int8_t battery_remaining = -1; int8_t battery_remaining = -1;
@ -246,6 +252,14 @@ static void NOINLINE send_gps_raw(mavlink_channel_t chan)
g_gps->num_sats); g_gps->num_sats);
} }
static void NOINLINE send_system_time(mavlink_channel_t chan)
{
mavlink_msg_system_time_send(
chan,
g_gps->time_epoch_usec(),
hal.scheduler->millis());
}
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
static void NOINLINE send_servo_out(mavlink_channel_t chan) static void NOINLINE send_servo_out(mavlink_channel_t chan)
@ -471,6 +485,14 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
return false; return false;
} }
// if we don't have at least 1ms remaining before the main loop
// wants to fire then don't send a mavlink message. We want to
// prioritise the main flight control loop over communications
if (!in_mavlink_delay && scheduler.time_available_usec() < 1200) {
gcs_out_of_time = true;
return false;
}
switch (id) { switch (id) {
case MSG_HEARTBEAT: case MSG_HEARTBEAT:
CHECK_PAYLOAD_SIZE(HEARTBEAT); CHECK_PAYLOAD_SIZE(HEARTBEAT);
@ -509,6 +531,11 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
send_gps_raw(chan); send_gps_raw(chan);
break; break;
case MSG_SYSTEM_TIME:
CHECK_PAYLOAD_SIZE(SYSTEM_TIME);
send_system_time(chan);
break;
case MSG_SERVO_OUT: case MSG_SERVO_OUT:
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED); CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED);
@ -756,8 +783,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK, streamRates[8], 5), AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK, streamRates[8], 10),
AP_GROUPEND AP_GROUPEND
}; };
@ -858,7 +884,8 @@ bool GCS_MAVLINK::stream_trigger(enum streams stream_num)
// send at a much lower rate while handling waypoints and // send at a much lower rate while handling waypoints and
// parameter sends // parameter sends
if (waypoint_receiving || _queued_parameter != NULL) { if ((stream_num != STREAM_PARAMS) &&
(waypoint_receiving || _queued_parameter != NULL)) {
rate *= 0.25; rate *= 0.25;
} }
@ -883,18 +910,19 @@ bool GCS_MAVLINK::stream_trigger(enum streams stream_num)
void void
GCS_MAVLINK::data_stream_send(void) GCS_MAVLINK::data_stream_send(void)
{ {
gcs_out_of_time = false;
if (_queued_parameter != NULL) { if (_queued_parameter != NULL) {
if (streamRates[STREAM_PARAMS].get() <= 0) { if (streamRates[STREAM_PARAMS].get() <= 0) {
streamRates[STREAM_PARAMS].set(5); streamRates[STREAM_PARAMS].set(10);
}
if (streamRates[STREAM_PARAMS].get() > 5) {
streamRates[STREAM_PARAMS].set(5);
} }
if (stream_trigger(STREAM_PARAMS)) { if (stream_trigger(STREAM_PARAMS)) {
send_message(MSG_NEXT_PARAM); send_message(MSG_NEXT_PARAM);
} }
} }
if (gcs_out_of_time) return;
if (in_mavlink_delay) { if (in_mavlink_delay) {
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
// in HIL we need to keep sending servo values to ensure // in HIL we need to keep sending servo values to ensure
@ -911,11 +939,15 @@ GCS_MAVLINK::data_stream_send(void)
return; return;
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_RAW_SENSORS)) { if (stream_trigger(STREAM_RAW_SENSORS)) {
send_message(MSG_RAW_IMU1); send_message(MSG_RAW_IMU1);
send_message(MSG_RAW_IMU3); send_message(MSG_RAW_IMU3);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_EXTENDED_STATUS)) { if (stream_trigger(STREAM_EXTENDED_STATUS)) {
send_message(MSG_EXTENDED_STATUS1); send_message(MSG_EXTENDED_STATUS1);
send_message(MSG_EXTENDED_STATUS2); send_message(MSG_EXTENDED_STATUS2);
@ -924,33 +956,46 @@ GCS_MAVLINK::data_stream_send(void)
send_message(MSG_NAV_CONTROLLER_OUTPUT); send_message(MSG_NAV_CONTROLLER_OUTPUT);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_POSITION)) { if (stream_trigger(STREAM_POSITION)) {
// sent with GPS read // sent with GPS read
send_message(MSG_LOCATION); send_message(MSG_LOCATION);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_RAW_CONTROLLER)) { if (stream_trigger(STREAM_RAW_CONTROLLER)) {
send_message(MSG_SERVO_OUT); send_message(MSG_SERVO_OUT);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_RC_CHANNELS)) { if (stream_trigger(STREAM_RC_CHANNELS)) {
send_message(MSG_RADIO_OUT); send_message(MSG_RADIO_OUT);
send_message(MSG_RADIO_IN); send_message(MSG_RADIO_IN);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_EXTRA1)) { if (stream_trigger(STREAM_EXTRA1)) {
send_message(MSG_ATTITUDE); send_message(MSG_ATTITUDE);
send_message(MSG_SIMSTATE); send_message(MSG_SIMSTATE);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_EXTRA2)) { if (stream_trigger(STREAM_EXTRA2)) {
send_message(MSG_VFR_HUD); send_message(MSG_VFR_HUD);
} }
if (gcs_out_of_time) return;
if (stream_trigger(STREAM_EXTRA3)) { if (stream_trigger(STREAM_EXTRA3)) {
send_message(MSG_AHRS); send_message(MSG_AHRS);
send_message(MSG_HWSTATUS); send_message(MSG_HWSTATUS);
send_message(MSG_RANGEFINDER); send_message(MSG_RANGEFINDER);
send_message(MSG_SYSTEM_TIME);
} }
} }
@ -1293,8 +1338,10 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
mavlink_msg_param_request_list_decode(msg, &packet); mavlink_msg_param_request_list_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break; if (mavlink_check_target(packet.target_system,packet.target_component)) break;
// Start sending parameters - next call to ::update will kick the first one out // mark the firmware version in the tlog
send_text_P(SEVERITY_LOW, PSTR(FIRMWARE_STRING));
// Start sending parameters - next call to ::update will kick the first one out
_queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type); _queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index = 0; _queued_parameter_index = 0;
_queued_parameter_count = _count_parameters(); _queued_parameter_count = _count_parameters();
@ -1713,7 +1760,6 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
if(msg->sysid != g.sysid_my_gcs) break; if(msg->sysid != g.sysid_my_gcs) break;
last_heartbeat_ms = failsafe.rc_override_timer = millis(); last_heartbeat_ms = failsafe.rc_override_timer = millis();
failsafe_trigger(FAILSAFE_EVENT_GCS, false); failsafe_trigger(FAILSAFE_EVENT_GCS, false);
pmTest1++;
break; break;
} }
@ -2007,3 +2053,11 @@ void gcs_send_text_fmt(const prog_char_t *fmt, ...)
} }
} }
/**
retry any deferred messages
*/
static void gcs_retry_deferred(void)
{
gcs_send_message(MSG_RETRY_DEFERRED);
}

View File

@ -165,15 +165,14 @@ struct PACKED log_Performance {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t loop_time; uint32_t loop_time;
uint16_t main_loop_count; uint16_t main_loop_count;
int16_t g_dt_max; uint32_t g_dt_max;
uint8_t renorm_count; uint8_t renorm_count;
uint8_t renorm_blowup; uint8_t renorm_blowup;
uint8_t gps_fix_count;
int16_t gyro_drift_x; int16_t gyro_drift_x;
int16_t gyro_drift_y; int16_t gyro_drift_y;
int16_t gyro_drift_z; int16_t gyro_drift_z;
int16_t pm_test;
uint8_t i2c_lockup_count; uint8_t i2c_lockup_count;
uint16_t ins_error_count;
}; };
// Write a performance monitoring packet. Total length : 19 bytes // Write a performance monitoring packet. Total length : 19 bytes
@ -186,12 +185,11 @@ static void Log_Write_Performance()
g_dt_max : G_Dt_max, g_dt_max : G_Dt_max,
renorm_count : ahrs.renorm_range_count, renorm_count : ahrs.renorm_range_count,
renorm_blowup : ahrs.renorm_blowup_count, renorm_blowup : ahrs.renorm_blowup_count,
gps_fix_count : gps_fix_count,
gyro_drift_x : (int16_t)(ahrs.get_gyro_drift().x * 1000), gyro_drift_x : (int16_t)(ahrs.get_gyro_drift().x * 1000),
gyro_drift_y : (int16_t)(ahrs.get_gyro_drift().y * 1000), gyro_drift_y : (int16_t)(ahrs.get_gyro_drift().y * 1000),
gyro_drift_z : (int16_t)(ahrs.get_gyro_drift().z * 1000), gyro_drift_z : (int16_t)(ahrs.get_gyro_drift().z * 1000),
pm_test : pmTest1, i2c_lockup_count: hal.i2c->lockup_count(),
i2c_lockup_count: hal.i2c->lockup_count() ins_error_count : ins.error_count()
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
@ -228,6 +226,7 @@ static void Log_Write_Cmd(uint8_t num, const struct Location *wp)
struct PACKED log_Camera { struct PACKED log_Camera {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t gps_time; uint32_t gps_time;
uint16_t gps_week;
int32_t latitude; int32_t latitude;
int32_t longitude; int32_t longitude;
int16_t roll; int16_t roll;
@ -241,7 +240,8 @@ static void Log_Write_Camera()
#if CAMERA == ENABLED #if CAMERA == ENABLED
struct log_Camera pkt = { struct log_Camera pkt = {
LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG), LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG),
gps_time : g_gps->time, gps_time : g_gps->time_week_ms,
gps_week : g_gps->time_week,
latitude : current_loc.lat, latitude : current_loc.lat,
longitude : current_loc.lng, longitude : current_loc.lng,
roll : (int16_t)ahrs.roll_sensor, roll : (int16_t)ahrs.roll_sensor,
@ -454,11 +454,11 @@ static const struct LogStructure log_structure[] PROGMEM = {
{ LOG_ATTITUDE_MSG, sizeof(log_Attitude), { LOG_ATTITUDE_MSG, sizeof(log_Attitude),
"ATT", "ccC", "Roll,Pitch,Yaw" }, "ATT", "ccC", "Roll,Pitch,Yaw" },
{ LOG_PERFORMANCE_MSG, sizeof(log_Performance), { LOG_PERFORMANCE_MSG, sizeof(log_Performance),
"PM", "IHhBBBhhhhB", "LTime,MLC,gDt,RNCnt,RNBl,GPScnt,GDx,GDy,GDz,PMT,I2CErr" }, "PM", "IHIBBhhhBH", "LTime,MLC,gDt,RNCnt,RNBl,GDx,GDy,GDz,I2CErr,INSErr" },
{ LOG_CMD_MSG, sizeof(log_Cmd), { LOG_CMD_MSG, sizeof(log_Cmd),
"CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" }, "CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" },
{ LOG_CAMERA_MSG, sizeof(log_Camera), { LOG_CAMERA_MSG, sizeof(log_Camera),
"CAM", "ILLccC", "GPSTime,Lat,Lng,Roll,Pitch,Yaw" }, "CAM", "IHLLeccC", "GPSTime,GPSWeek,Lat,Lng,Alt,Roll,Pitch,Yaw" },
{ LOG_STARTUP_MSG, sizeof(log_Startup), { LOG_STARTUP_MSG, sizeof(log_Startup),
"STRT", "BB", "SType,CTot" }, "STRT", "BB", "SType,CTot" },
{ LOG_CTUN_MSG, sizeof(log_Control_Tuning), { LOG_CTUN_MSG, sizeof(log_Control_Tuning),
@ -479,7 +479,7 @@ static const struct LogStructure log_structure[] PROGMEM = {
// Read the DataFlash log memory : Packet Parser // Read the DataFlash log memory : Packet Parser
static void Log_Read(uint16_t log_num, uint16_t start_page, uint16_t end_page) static void Log_Read(uint16_t log_num, uint16_t start_page, uint16_t end_page)
{ {
cliSerial->printf_P(PSTR("\n" THISFIRMWARE cliSerial->printf_P(PSTR("\n" FIRMWARE_STRING
"\nFree RAM: %u\n"), "\nFree RAM: %u\n"),
(unsigned) memcheck_available_memory()); (unsigned) memcheck_available_memory());
@ -496,6 +496,7 @@ static void Log_Read(uint16_t log_num, uint16_t start_page, uint16_t end_page)
static void start_logging() static void start_logging()
{ {
DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure); DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure);
DataFlash.Log_Write_Message_P(PSTR(FIRMWARE_STRING));
} }
#else // LOGGING_ENABLED #else // LOGGING_ENABLED

View File

@ -75,13 +75,8 @@ static void calc_throttle(float target_speed)
return; return;
} }
if (target_speed <= 0) { float throttle_base = (fabsf(target_speed) / g.speed_cruise) * g.throttle_cruise;
// cope with zero requested speed int throttle_target = throttle_base + throttle_nudge;
channel_throttle->servo_out = g.throttle_min.get();
return;
}
int throttle_target = g.throttle_cruise + throttle_nudge;
/* /*
reduce target speed in proportion to turning rate, up to the reduce target speed in proportion to turning rate, up to the
@ -102,7 +97,7 @@ static void calc_throttle(float target_speed)
// reduce the target speed by the reduction factor // reduce the target speed by the reduction factor
target_speed *= reduction; target_speed *= reduction;
groundspeed_error = target_speed - ground_speed; groundspeed_error = fabsf(target_speed) - ground_speed;
throttle = throttle_target + (g.pidSpeedThrottle.get_pid(groundspeed_error * 100) / 100); throttle = throttle_target + (g.pidSpeedThrottle.get_pid(groundspeed_error * 100) / 100);
@ -110,7 +105,11 @@ static void calc_throttle(float target_speed)
// much faster response in turns // much faster response in turns
throttle *= reduction; throttle *= reduction;
channel_throttle->servo_out = constrain_int16(throttle, g.throttle_min.get(), g.throttle_max.get()); if (in_reverse) {
channel_throttle->servo_out = constrain_int16(-throttle, -g.throttle_max, -g.throttle_min);
} else {
channel_throttle->servo_out = constrain_int16(throttle, g.throttle_min, g.throttle_max);
}
} }
/***************************************** /*****************************************
@ -179,9 +178,15 @@ static void set_servos(void)
} }
} else { } else {
channel_steer->calc_pwm(); channel_steer->calc_pwm();
if (in_reverse) {
channel_throttle->servo_out = constrain_int16(channel_throttle->servo_out,
-g.throttle_max,
-g.throttle_min);
} else {
channel_throttle->servo_out = constrain_int16(channel_throttle->servo_out, channel_throttle->servo_out = constrain_int16(channel_throttle->servo_out,
g.throttle_min.get(), g.throttle_min.get(),
g.throttle_max.get()); g.throttle_max.get());
}
if ((failsafe.bits & FAILSAFE_EVENT_THROTTLE) && control_mode < AUTO) { if ((failsafe.bits & FAILSAFE_EVENT_THROTTLE) && control_mode < AUTO) {
// suppress throttle if in failsafe // suppress throttle if in failsafe

View File

@ -366,3 +366,13 @@
#ifndef SONAR_ENABLED #ifndef SONAR_ENABLED
# define SONAR_ENABLED DISABLED # define SONAR_ENABLED DISABLED
#endif #endif
/*
build a firmware version string.
GIT_VERSION comes from Makefile builds
*/
#ifndef GIT_VERSION
#define FIRMWARE_STRING THISFIRMWARE
#else
#define FIRMWARE_STRING THISFIRMWARE " (" GIT_VERSION ")"
#endif

View File

@ -101,6 +101,7 @@ enum ap_message {
MSG_RAW_IMU1, MSG_RAW_IMU1,
MSG_RAW_IMU3, MSG_RAW_IMU3,
MSG_GPS_RAW, MSG_GPS_RAW,
MSG_SYSTEM_TIME,
MSG_SERVO_OUT, MSG_SERVO_OUT,
MSG_NEXT_WAYPOINT, MSG_NEXT_WAYPOINT,
MSG_NEXT_PARAM, MSG_NEXT_PARAM,

View File

@ -94,7 +94,7 @@ static void init_ardupilot()
// standard gps running // standard gps running
hal.uartB->begin(115200, 256, 16); hal.uartB->begin(115200, 256, 16);
cliSerial->printf_P(PSTR("\n\nInit " THISFIRMWARE cliSerial->printf_P(PSTR("\n\nInit " FIRMWARE_STRING
"\n\nFree RAM: %u\n"), "\n\nFree RAM: %u\n"),
memcheck_available_memory()); memcheck_available_memory());
@ -252,6 +252,8 @@ static void set_mode(enum mode mode)
control_mode = mode; control_mode = mode;
throttle_last = 0; throttle_last = 0;
throttle = 500; throttle = 500;
in_reverse = false;
g.pidSpeedThrottle.reset_I();
if (control_mode != AUTO) { if (control_mode != AUTO) {
auto_triggered = false; auto_triggered = false;
@ -370,7 +372,6 @@ static void resetPerfData(void) {
ahrs.renorm_range_count = 0; ahrs.renorm_range_count = 0;
ahrs.renorm_blowup_count = 0; ahrs.renorm_blowup_count = 0;
gps_fix_count = 0; gps_fix_count = 0;
pmTest1 = 0;
perf_mon_timer = millis(); perf_mon_timer = millis();
} }

View File

@ -341,14 +341,8 @@ test_ins(uint8_t argc, const Menu::arg *argv)
uint8_t medium_loopCounter = 0; uint8_t medium_loopCounter = 0;
while(1){ while(1){
delay(20); ins.wait_for_sample(1000);
if (millis() - fast_loopTimer > 19) {
delta_ms_fast_loop = millis() - fast_loopTimer;
G_Dt = (float)delta_ms_fast_loop / 1000.f; // used by DCM integrator
fast_loopTimer = millis();
// INS
// ---
ahrs.update(); ahrs.update();
if(g.compass_enabled) { if(g.compass_enabled) {
@ -373,7 +367,6 @@ test_ins(uint8_t argc, const Menu::arg *argv)
if(cliSerial->available() > 0){ if(cliSerial->available() > 0){
return (0); return (0);
} }
}
} }
@ -408,14 +401,7 @@ test_mag(uint8_t argc, const Menu::arg *argv)
uint8_t medium_loopCounter = 0; uint8_t medium_loopCounter = 0;
while(1) { while(1) {
delay(20); ins.wait_for_sample(1000);
if (millis() - fast_loopTimer > 19) {
delta_ms_fast_loop = millis() - fast_loopTimer;
G_Dt = (float)delta_ms_fast_loop / 1000.f; // used by DCM integrator
fast_loopTimer = millis();
// IMU
// ---
ahrs.update(); ahrs.update();
medium_loopCounter++; medium_loopCounter++;
@ -446,7 +432,6 @@ test_mag(uint8_t argc, const Menu::arg *argv)
} }
counter=0; counter=0;
} }
}
if (cliSerial->available() > 0) { if (cliSerial->available() > 0) {
break; break;
} }

View File

@ -15,14 +15,24 @@
* OCTA_FRAME * OCTA_FRAME
* OCTA_QUAD_FRAME * OCTA_QUAD_FRAME
* HELI_FRAME * HELI_FRAME
* SINGLE_FRAME
*/ */
// uncomment the lines below to save on flash space if compiling for the APM using Arduino IDE // uncomment the lines below to save on flash space if compiling for the APM using Arduino IDE. Top items save the most flash space
//#define OPTFLOW DISABLED // disable optical flow sensor to save 5K of flash space
//#define LOGGING_ENABLED DISABLED // disable dataflash logging to save 11K of flash space
//#define MOUNT DISABLED // disable the camera gimbal to save 8K of flash space
//#define CLI_ENABLED DISABLED // disable the CLI (command-line-interface) to save 21K of flash space //#define CLI_ENABLED DISABLED // disable the CLI (command-line-interface) to save 21K of flash space
//#define LOGGING_ENABLED DISABLED // disable dataflash logging to save 11K of flash space
//#define GPS_PROTOCOL GPS_PROTOCOL_UBLOX // hard code GPS to Ublox to save 8k of flash
//#define GPS_PROTOCOL GPS_PROTOCOL_MTK19 // hard cdoe GPS to Mediatek to save 10k of flash
//#define MOUNT DISABLED // disable the camera gimbal to save 8K of flash space
//#define AUTOTUNE DISABLED // disable the auto tune functionality to save 7k of flash //#define AUTOTUNE DISABLED // disable the auto tune functionality to save 7k of flash
//#define OPTFLOW DISABLED // disable optical flow sensor to save 5K of flash space
//#define AC_FENCE DISABLED // disable fence to save 2k of flash
//#define CAMERA DISABLED // disable camera trigger to save 1k of flash
//#define COPTER_LEDS DISABLED // disable external navigation leds to save 1k of flash
//#define CONFIG_SONAR DISABLED // disable sonar to save 1k of flash
// features below are disabled by default
//#define SPRAYER ENABLED // enable the crop sprayer feature (two ESC controlled pumps the speed of which depends upon the vehicle's horizontal velocity)
// redefine size of throttle deadband in pwm (0 ~ 1000) // redefine size of throttle deadband in pwm (0 ~ 1000)
//#define THROTTLE_IN_DEADBAND 100 //#define THROTTLE_IN_DEADBAND 100

View File

@ -25,7 +25,7 @@
// the loop port. Alternatively, use a telemetry/HIL shim like FGShim // the loop port. Alternatively, use a telemetry/HIL shim like FGShim
// https://ardupilot-mega.googlecode.com/svn/Tools/trunk/FlightGear // https://ardupilot-mega.googlecode.com/svn/Tools/trunk/FlightGear
// //
// The buad rate is controlled by SERIAL3_BAUD in this mode. // The buad rate is controlled by SERIAL1_BAUD in this mode.
#define HIL_PORT 3 #define HIL_PORT 3

View File

@ -131,3 +131,10 @@ void set_pre_arm_check(bool b)
} }
} }
void set_pre_arm_rc_check(bool b)
{
if(ap.pre_arm_rc_check != b) {
ap.pre_arm_rc_check = b;
}
}

View File

@ -1,6 +1,6 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- /// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
#define THISFIRMWARE "ArduCopter V3.1-rc5" #define THISFIRMWARE "ArduCopter V3.1.5"
/* /*
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -19,44 +19,55 @@
* ArduCopter Version 3.0 * ArduCopter Version 3.0
* Creator: Jason Short * Creator: Jason Short
* Lead Developer: Randy Mackay * Lead Developer: Randy Mackay
* Based on code and ideas from the Arducopter team: Pat Hickey, Jose Julio, Jani Hirvinen, Andrew Tridgell, Justin Beech, Adam Rivera, Jean-Louis Naudin, Roberto Navoni * Lead Tester: Marco Robustini
* Thanks to: Chris Anderson, Mike Smith, Jordi Munoz, Doug Weibel, James Goppert, Benjamin Pelletier, Robert Lefebvre, Marco Robustini * Based on code and ideas from the Arducopter team: Leonard Hall, Andrew Tridgell, Robert Lefebvre, Pat Hickey, Michael Oborne, Jani Hirvinen,
Olivier Adler, Kevin Hester, Arthur Benemann, Jonathan Challinger, John Arne Birkeland,
Jean-Louis Naudin, Mike Smith, and more
* Thanks to: Chris Anderson, Jordi Munoz, Jason Short, Doug Weibel, Jose Julio
* *
* Special Thanks for Contributors (in alphabetical order by first name): * Special Thanks to contributors (in alphabetical order by first name):
* *
* Adam M Rivera :Auto Compass Declination * Adam M Rivera :Auto Compass Declination
* Amilcar Lucas :Camera mount library * Amilcar Lucas :Camera mount library
* Andrew Tridgell :General development, Mavlink Support * Andrew Tridgell :General development, Mavlink Support
* Angel Fernandez :Alpha testing * Angel Fernandez :Alpha testing
* Doug Weibel :Libraries * AndreasAntonopoulous:GeoFence
* Arthur Benemann :DroidPlanner GCS
* Benjamin Pelletier :Libraries
* Bill King :Single Copter
* Christof Schmid :Alpha testing * Christof Schmid :Alpha testing
* Craig Elder :Release Management, Support
* Dani Saez :V Octo Support * Dani Saez :V Octo Support
* Doug Weibel :DCM, Libraries, Control law advice
* Gregory Fletcher :Camera mount orientation math * Gregory Fletcher :Camera mount orientation math
* Guntars :Arming safety suggestion * Guntars :Arming safety suggestion
* HappyKillmore :Mavlink GCS * HappyKillmore :Mavlink GCS
* Hein Hollander :Octo Support * Hein Hollander :Octo Support, Heli Testing
* Igor van Airde :Control Law optimization * Igor van Airde :Control Law optimization
* Leonard Hall :Flight Dynamics, Throttle, Loiter and Navigation Controllers
* Jonathan Challinger :Inertial Navigation
* Jean-Louis Naudin :Auto Landing
* Max Levine :Tri Support, Graphics
* Jack Dunkle :Alpha testing * Jack Dunkle :Alpha testing
* James Goppert :Mavlink Support * James Goppert :Mavlink Support
* Jani Hiriven :Testing feedback * Jani Hiriven :Testing feedback
* Jean-Louis Naudin :Auto Landing
* John Arne Birkeland :PPM Encoder * John Arne Birkeland :PPM Encoder
* Jose Julio :Stabilization Control laws * Jose Julio :Stabilization Control laws, MPU6k driver
* Julian Oes :Pixhawk
* Jonathan Challinger :Inertial Navigation, CompassMot, Spin-When-Armed
* Kevin Hester :Andropilot GCS
* Max Levine :Tri Support, Graphics
* Leonard Hall :Flight Dynamics, Throttle, Loiter and Navigation Controllers
* Marco Robustini :Lead tester * Marco Robustini :Lead tester
* Michael Oborne :Mission Planner GCS * Michael Oborne :Mission Planner GCS
* Mike Smith :Libraries, Coding support * Mike Smith :Pixhawk driver, coding support
* Oliver :Piezo support * Olivier Adler :PPM Encoder, piezo buzzer
* Olivier Adler :PPM Encoder * Pat Hickey :Hardware Abstraaction Layer (HAL)
* Robert Lefebvre :Heli Support & LEDs * Robert Lefebvre :Heli Support, Copter LEDs
* Sandro Benigno :Camera support * Roberto Navoni :Library testing, Porting to VRBrain
* Sandro Benigno :Camera support, MinimOSD
* ..and many more.
* *
* And much more so PLEASE PM me on DIYDRONES to add your contribution to the List * Code commit statistics can be found here: https://github.com/diydrones/ardupilot/graphs/contributors
* * Wiki: http://copter.ardupilot.com/
* Requires modified "mrelax" version of Arduino, which can be found here: * Requires modified version of Arduino, which can be found here: http://ardupilot.com/downloads/?category=6
* http://code.google.com/p/ardupilot-mega/downloads/list
* *
*/ */
@ -289,7 +300,7 @@ AP_GPS_None g_gps_driver;
#error Unrecognised GPS_PROTOCOL setting. #error Unrecognised GPS_PROTOCOL setting.
#endif // GPS PROTOCOL #endif // GPS PROTOCOL
static AP_AHRS_DCM ahrs(&ins, g_gps); static AP_AHRS_DCM ahrs(ins, g_gps);
#elif HIL_MODE == HIL_MODE_SENSORS #elif HIL_MODE == HIL_MODE_SENSORS
// sensor emulators // sensor emulators
@ -298,7 +309,7 @@ static AP_Baro_HIL barometer;
static AP_Compass_HIL compass; static AP_Compass_HIL compass;
static AP_GPS_HIL g_gps_driver; static AP_GPS_HIL g_gps_driver;
static AP_InertialSensor_HIL ins; static AP_InertialSensor_HIL ins;
static AP_AHRS_DCM ahrs(&ins, g_gps); static AP_AHRS_DCM ahrs(ins, g_gps);
#if CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL #if CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
@ -309,7 +320,7 @@ static SITL sitl;
#elif HIL_MODE == HIL_MODE_ATTITUDE #elif HIL_MODE == HIL_MODE_ATTITUDE
static AP_ADC_HIL adc; static AP_ADC_HIL adc;
static AP_InertialSensor_HIL ins; static AP_InertialSensor_HIL ins;
static AP_AHRS_HIL ahrs(&ins, g_gps); static AP_AHRS_HIL ahrs(ins, g_gps);
static AP_GPS_HIL g_gps_driver; static AP_GPS_HIL g_gps_driver;
static AP_Compass_HIL compass; // never used static AP_Compass_HIL compass; // never used
static AP_Baro_HIL barometer; static AP_Baro_HIL barometer;
@ -335,8 +346,8 @@ static AP_OpticalFlow optflow;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// GCS selection // GCS selection
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static GCS_MAVLINK gcs0; static const uint8_t num_gcs = MAVLINK_COMM_NUM_BUFFERS;
static GCS_MAVLINK gcs3; static GCS_MAVLINK gcs[MAVLINK_COMM_NUM_BUFFERS];
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SONAR selection // SONAR selection
@ -395,6 +406,8 @@ static union {
uint8_t yaw_stopped : 1; // 16 // Used to manage the Yaw hold capabilities uint8_t yaw_stopped : 1; // 16 // Used to manage the Yaw hold capabilities
uint8_t disable_stab_rate_limit : 1; // 17 // disables limits rate request from the stability controller uint8_t disable_stab_rate_limit : 1; // 17 // disables limits rate request from the stability controller
uint8_t rc_receiver_present : 1; // 18 // true if we have an rc receiver present (i.e. if we've ever received an update
}; };
uint32_t value; uint32_t value;
} ap; } ap;
@ -445,14 +458,18 @@ static struct {
#define MOTOR_CLASS AP_MotorsOctaQuad #define MOTOR_CLASS AP_MotorsOctaQuad
#elif FRAME_CONFIG == HELI_FRAME #elif FRAME_CONFIG == HELI_FRAME
#define MOTOR_CLASS AP_MotorsHeli #define MOTOR_CLASS AP_MotorsHeli
#elif FRAME_CONFIG == SINGLE_FRAME
#define MOTOR_CLASS AP_MotorsSingle
#else #else
#error Unrecognised frame type #error Unrecognised frame type
#endif #endif
#if FRAME_CONFIG == HELI_FRAME // helicopter constructor requires more arguments #if FRAME_CONFIG == HELI_FRAME // helicopter constructor requires more arguments
static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4, &g.rc_8, &g.heli_servo_1, &g.heli_servo_2, &g.heli_servo_3, &g.heli_servo_4); static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4, &g.rc_7, &g.rc_8, &g.heli_servo_1, &g.heli_servo_2, &g.heli_servo_3, &g.heli_servo_4);
#elif FRAME_CONFIG == TRI_FRAME // tri constructor requires additional rc_7 argument to allow tail servo reversing #elif FRAME_CONFIG == TRI_FRAME // tri constructor requires additional rc_7 argument to allow tail servo reversing
static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4, &g.rc_7); static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4, &g.rc_7);
#elif FRAME_CONFIG == SINGLE_FRAME // single constructor requires extra servos for flaps
static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4, &g.single_servo_1, &g.single_servo_2, &g.single_servo_3, &g.single_servo_4);
#else #else
static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4); static MOTOR_CLASS motors(&g.rc_1, &g.rc_2, &g.rc_3, &g.rc_4);
#endif #endif
@ -642,8 +659,6 @@ static float target_sonar_alt; // desired altitude in cm above the ground
// The altitude as reported by Baro in cm Values can be quite high // The altitude as reported by Baro in cm Values can be quite high
static int32_t baro_alt; static int32_t baro_alt;
static int16_t saved_toy_throttle;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// flight modes // flight modes
@ -652,11 +667,11 @@ static int16_t saved_toy_throttle;
// Each Flight mode is a unique combination of these modes // Each Flight mode is a unique combination of these modes
// //
// The current desired control scheme for Yaw // The current desired control scheme for Yaw
static uint8_t yaw_mode; static uint8_t yaw_mode = STABILIZE_YAW;
// The current desired control scheme for roll and pitch / navigation // The current desired control scheme for roll and pitch / navigation
static uint8_t roll_pitch_mode; static uint8_t roll_pitch_mode = STABILIZE_RP;
// The current desired control scheme for altitude hold // The current desired control scheme for altitude hold
static uint8_t throttle_mode; static uint8_t throttle_mode = STABILIZE_THR;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -712,7 +727,6 @@ static uint32_t throttle_integrator;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// The Commanded Yaw from the autopilot. // The Commanded Yaw from the autopilot.
static int32_t nav_yaw; static int32_t nav_yaw;
static uint8_t yaw_timer;
// Yaw will point at this location if yaw_mode is set to YAW_LOOK_AT_LOCATION // Yaw will point at this location if yaw_mode is set to YAW_LOOK_AT_LOCATION
static Vector3f yaw_look_at_WP; static Vector3f yaw_look_at_WP;
// bearing from current location to the yaw_look_at_WP // bearing from current location to the yaw_look_at_WP
@ -750,14 +764,14 @@ static uint32_t condition_start;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// IMU variables // IMU variables
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Integration time for the gyros (DCM algorithm) // Integration time (in seconds) for the gyros (DCM algorithm)
// Updated with the fast loop // Updated with the fast loop
static float G_Dt = 0.02; static float G_Dt = 0.02;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Inertial Navigation // Inertial Navigation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static AP_InertialNav inertial_nav(&ahrs, &ins, &barometer, g_gps, gps_glitch); static AP_InertialNav inertial_nav(&ahrs, &barometer, g_gps, gps_glitch);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Waypoint navigation object // Waypoint navigation object
@ -768,8 +782,6 @@ static AC_WPNav wp_nav(&inertial_nav, &ahrs, &g.pi_loiter_lat, &g.pi_loiter_lon,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Performance monitoring // Performance monitoring
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// The number of GPS fixes we have had
static uint8_t gps_fix_count;
static int16_t pmTest1; static int16_t pmTest1;
// System Timers // System Timers
@ -780,8 +792,6 @@ static uint32_t fast_loopTimer;
static uint16_t mainLoop_count; static uint16_t mainLoop_count;
// Loiter timer - Records how long we have been in loiter // Loiter timer - Records how long we have been in loiter
static uint32_t rtl_loiter_start_time; static uint32_t rtl_loiter_start_time;
// prevents duplicate GPS messages from entering system
static uint32_t last_gps_time;
// Used to exit the roll and pitch auto trim function // Used to exit the roll and pitch auto trim function
static uint8_t auto_trim_counter; static uint8_t auto_trim_counter;
@ -861,14 +871,17 @@ static const AP_Scheduler::Task scheduler_tasks[] PROGMEM = {
{ read_aux_switches, 10, 50 }, { read_aux_switches, 10, 50 },
{ arm_motors_check, 10, 10 }, { arm_motors_check, 10, 10 },
{ auto_trim, 10, 140 }, { auto_trim, 10, 140 },
{ update_toy_throttle, 10, 50 },
{ update_altitude, 10, 1000 }, { update_altitude, 10, 1000 },
{ run_nav_updates, 10, 800 }, { run_nav_updates, 10, 800 },
{ three_hz_loop, 33, 90 }, { three_hz_loop, 33, 90 },
{ compass_accumulate, 2, 420 }, { compass_accumulate, 2, 420 },
{ barometer_accumulate, 2, 250 }, { barometer_accumulate, 2, 250 },
#if FRAME_CONFIG == HELI_FRAME
{ check_dynamic_flight, 2, 100 },
#endif
{ update_notify, 2, 100 }, { update_notify, 2, 100 },
{ one_hz_loop, 100, 420 }, { one_hz_loop, 100, 420 },
{ crash_check, 10, 20 },
{ gcs_check_input, 2, 550 }, { gcs_check_input, 2, 550 },
{ gcs_send_heartbeat, 100, 150 }, { gcs_send_heartbeat, 100, 150 },
{ gcs_send_deferred, 2, 720 }, { gcs_send_deferred, 2, 720 },
@ -966,7 +979,6 @@ static void perf_update(void)
(unsigned long)perf_info_get_max_time()); (unsigned long)perf_info_get_max_time());
} }
perf_info_reset(); perf_info_reset();
gps_fix_count = 0;
pmTest1 = 0; pmTest1 = 0;
} }
@ -974,7 +986,7 @@ void loop()
{ {
// wait for an INS sample // wait for an INS sample
if (!ins.wait_for_sample(1000)) { if (!ins.wait_for_sample(1000)) {
Log_Write_Error(ERROR_SUBSYSTEM_MAIN, ERROR_CODE_INS_DELAY); Log_Write_Error(ERROR_SUBSYSTEM_MAIN, ERROR_CODE_MAIN_INS_DELAY);
return; return;
} }
uint32_t timer = micros(); uint32_t timer = micros();
@ -1076,12 +1088,16 @@ static void throttle_loop()
// check if we've landed // check if we've landed
update_land_detector(); update_land_detector();
#if TOY_EDF == ENABLED
edf_toy();
#endif
// check auto_armed status // check auto_armed status
update_auto_armed(); update_auto_armed();
#if FRAME_CONFIG == HELI_FRAME
// update rotor speed
heli_update_rotor_speed_targets();
// update trad heli swash plate movement
heli_update_landing_swash();
#endif
} }
// update_mount - update camera mount position // update_mount - update camera mount position
@ -1155,7 +1171,7 @@ static void fifty_hz_logging_loop()
} }
if (g.log_bitmask & MASK_LOG_IMU && motors.armed()) { if (g.log_bitmask & MASK_LOG_IMU && motors.armed()) {
DataFlash.Log_Write_IMU(&ins); DataFlash.Log_Write_IMU(ins);
} }
#endif #endif
} }
@ -1198,8 +1214,15 @@ static void one_hz_loop()
if ((g.log_bitmask & MASK_LOG_CURRENT) && motors.armed()) if ((g.log_bitmask & MASK_LOG_CURRENT) && motors.armed())
Log_Write_Current(); Log_Write_Current();
// perform pre-arm checks // perform pre-arm checks & display failures every 30 seconds
static uint8_t pre_arm_display_counter = 15;
pre_arm_display_counter++;
if (pre_arm_display_counter >= 30) {
pre_arm_checks(true);
pre_arm_display_counter = 0;
}else{
pre_arm_checks(false); pre_arm_checks(false);
}
// auto disarm checks // auto disarm checks
auto_disarm_check(); auto_disarm_check();
@ -1212,12 +1235,8 @@ static void one_hz_loop()
motors.set_frame_orientation(g.frame_orientation); motors.set_frame_orientation(g.frame_orientation);
} }
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 // update assigned functions and enable auxiliar servos
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12); aux_servos_update_fn();
#elif MOUNT == ENABLED
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_10, &g.rc_11);
#endif
enable_aux_servos(); enable_aux_servos();
#if MOUNT == ENABLED #if MOUNT == ENABLED
@ -1258,27 +1277,22 @@ static void update_optical_flow(void)
// called at 50hz // called at 50hz
static void update_GPS(void) static void update_GPS(void)
{ {
// A counter that is used to grab at least 10 reads before commiting the Home location static uint32_t last_gps_reading; // time of last gps message
static uint8_t ground_start_count = 10; static uint8_t ground_start_count = 10; // counter used to grab at least 10 reads before commiting the Home location
g_gps->update(); g_gps->update();
if (g_gps->new_data && last_gps_time != g_gps->time && g_gps->status() >= GPS::GPS_OK_FIX_2D) { // logging and glitch protection run after every gps message
// clear new data flag if (g_gps->last_message_time_ms() != last_gps_reading) {
g_gps->new_data = false; last_gps_reading = g_gps->last_message_time_ms();
// save GPS time so we don't get duplicate reads // log GPS message
last_gps_time = g_gps->time; if ((g.log_bitmask & MASK_LOG_GPS) && motors.armed()) {
// log location if we have at least a 2D fix
if (g.log_bitmask & MASK_LOG_GPS && motors.armed()) {
DataFlash.Log_Write_GPS(g_gps, current_loc.alt); DataFlash.Log_Write_GPS(g_gps, current_loc.alt);
} }
// for performance monitoring // run glitch protection and update AP_Notify if home has been initialised
gps_fix_count++; if (ap.home_is_set) {
// run glitch protection and update AP_Notify
gps_glitch.check_position(); gps_glitch.check_position();
if (AP_Notify::flags.gps_glitching != gps_glitch.glitching()) { if (AP_Notify::flags.gps_glitching != gps_glitch.glitching()) {
if (gps_glitch.glitching()) { if (gps_glitch.glitching()) {
@ -1288,6 +1302,13 @@ static void update_GPS(void)
} }
AP_Notify::flags.gps_glitching = gps_glitch.glitching(); AP_Notify::flags.gps_glitching = gps_glitch.glitching();
} }
}
}
// checks to initialise home and take location based pictures
if (g_gps->new_data && g_gps->status() >= GPS::GPS_OK_FIX_3D) {
// clear new data flag
g_gps->new_data = false;
// check if we can initialise home yet // check if we can initialise home yet
if (!ap.home_is_set) { if (!ap.home_is_set) {
@ -1300,6 +1321,10 @@ static void update_GPS(void)
// ap.home_is_set will be true so this will only happen once // ap.home_is_set will be true so this will only happen once
ground_start_count = 0; ground_start_count = 0;
init_home(); init_home();
// set system clock for log timestamps
hal.util->set_system_clock(g_gps->time_epoch_usec());
if (g.compass_enabled) { if (g.compass_enabled) {
// Set compass declination automatically // Set compass declination automatically
compass.set_initial_location(g_gps->latitude, g_gps->longitude); compass.set_initial_location(g_gps->latitude, g_gps->longitude);
@ -1375,7 +1400,7 @@ bool set_yaw_mode(uint8_t new_yaw_mode)
yaw_initialised = true; yaw_initialised = true;
} }
break; break;
case YAW_TOY: case YAW_DRIFT:
yaw_initialised = true; yaw_initialised = true;
break; break;
case YAW_RESETTOARMEDYAW: case YAW_RESETTOARMEDYAW:
@ -1397,6 +1422,13 @@ bool set_yaw_mode(uint8_t new_yaw_mode)
// 100hz update rate // 100hz update rate
void update_yaw_mode(void) void update_yaw_mode(void)
{ {
int16_t pilot_yaw = g.rc_4.control_in;
// do not process pilot's yaw input during radio failsafe
if (failsafe.radio) {
pilot_yaw = 0;
}
switch(yaw_mode) { switch(yaw_mode) {
case YAW_HOLD: case YAW_HOLD:
@ -1405,12 +1437,12 @@ void update_yaw_mode(void)
nav_yaw = ahrs.yaw_sensor; nav_yaw = ahrs.yaw_sensor;
} }
// heading hold at heading held in nav_yaw but allow input from pilot // heading hold at heading held in nav_yaw but allow input from pilot
get_yaw_rate_stabilized_ef(g.rc_4.control_in); get_yaw_rate_stabilized_ef(pilot_yaw);
break; break;
case YAW_ACRO: case YAW_ACRO:
// pilot controlled yaw using rate controller // pilot controlled yaw using rate controller
get_yaw_rate_stabilized_bf(g.rc_4.control_in); get_yaw_rate_stabilized_bf(pilot_yaw);
break; break;
case YAW_LOOK_AT_NEXT_WP: case YAW_LOOK_AT_NEXT_WP:
@ -1425,7 +1457,7 @@ void update_yaw_mode(void)
get_stabilize_yaw(nav_yaw); get_stabilize_yaw(nav_yaw);
// if there is any pilot input, switch to YAW_HOLD mode for the next iteration // if there is any pilot input, switch to YAW_HOLD mode for the next iteration
if( g.rc_4.control_in != 0 ) { if (pilot_yaw != 0) {
set_yaw_mode(YAW_HOLD); set_yaw_mode(YAW_HOLD);
} }
break; break;
@ -1439,7 +1471,7 @@ void update_yaw_mode(void)
get_look_at_yaw(); get_look_at_yaw();
// if there is any pilot input, switch to YAW_HOLD mode for the next iteration // if there is any pilot input, switch to YAW_HOLD mode for the next iteration
if( g.rc_4.control_in != 0 ) { if (pilot_yaw != 0) {
set_yaw_mode(YAW_HOLD); set_yaw_mode(YAW_HOLD);
} }
break; break;
@ -1453,7 +1485,7 @@ void update_yaw_mode(void)
get_circle_yaw(); get_circle_yaw();
// if there is any pilot input, switch to YAW_HOLD mode for the next iteration // if there is any pilot input, switch to YAW_HOLD mode for the next iteration
if( g.rc_4.control_in != 0 ) { if (pilot_yaw != 0) {
set_yaw_mode(YAW_HOLD); set_yaw_mode(YAW_HOLD);
} }
break; break;
@ -1469,7 +1501,7 @@ void update_yaw_mode(void)
get_stabilize_yaw(nav_yaw); get_stabilize_yaw(nav_yaw);
// if there is any pilot input, switch to YAW_HOLD mode for the next iteration // if there is any pilot input, switch to YAW_HOLD mode for the next iteration
if( g.rc_4.control_in != 0 ) { if (pilot_yaw != 0) {
set_yaw_mode(YAW_HOLD); set_yaw_mode(YAW_HOLD);
} }
break; break;
@ -1491,22 +1523,16 @@ void update_yaw_mode(void)
nav_yaw = ahrs.yaw_sensor; nav_yaw = ahrs.yaw_sensor;
} }
// Commanded Yaw to automatically look ahead. // Commanded Yaw to automatically look ahead.
get_look_ahead_yaw(g.rc_4.control_in); get_look_ahead_yaw(pilot_yaw);
break; break;
#if TOY_LOOKUP == TOY_EXTERNAL_MIXER case YAW_DRIFT:
case YAW_TOY: // if we have landed reset yaw target to current heading
// if we are landed reset yaw target to current heading
if (ap.land_complete) { if (ap.land_complete) {
nav_yaw = ahrs.yaw_sensor; nav_yaw = ahrs.yaw_sensor;
}else{
// update to allow external roll/yaw mixing
// keep heading always pointing at home with no pilot input allowed
nav_yaw = get_yaw_slew(nav_yaw, home_bearing, AUTO_YAW_SLEW_RATE);
} }
get_stabilize_yaw(nav_yaw); get_yaw_drift();
break; break;
#endif
case YAW_RESETTOARMEDYAW: case YAW_RESETTOARMEDYAW:
// if we are landed reset yaw target to current heading // if we are landed reset yaw target to current heading
@ -1519,7 +1545,7 @@ void update_yaw_mode(void)
get_stabilize_yaw(nav_yaw); get_stabilize_yaw(nav_yaw);
// if there is any pilot input, switch to YAW_HOLD mode for the next iteration // if there is any pilot input, switch to YAW_HOLD mode for the next iteration
if( g.rc_4.control_in != 0 ) { if (pilot_yaw != 0) {
set_yaw_mode(YAW_HOLD); set_yaw_mode(YAW_HOLD);
} }
@ -1577,18 +1603,12 @@ bool set_roll_pitch_mode(uint8_t new_roll_pitch_mode)
break; break;
case ROLL_PITCH_AUTO: case ROLL_PITCH_AUTO:
case ROLL_PITCH_STABLE_OF: case ROLL_PITCH_STABLE_OF:
case ROLL_PITCH_TOY: case ROLL_PITCH_DRIFT:
case ROLL_PITCH_LOITER:
case ROLL_PITCH_SPORT: case ROLL_PITCH_SPORT:
roll_pitch_initialised = true; roll_pitch_initialised = true;
break; break;
case ROLL_PITCH_LOITER:
// require gps lock
if( ap.home_is_set ) {
roll_pitch_initialised = true;
}
break;
#if AUTOTUNE == ENABLED #if AUTOTUNE == ENABLED
case ROLL_PITCH_AUTOTUNE: case ROLL_PITCH_AUTOTUNE:
// only enter autotune mode from stabilized roll-pitch mode when armed and flying // only enter autotune mode from stabilized roll-pitch mode when armed and flying
@ -1633,7 +1653,7 @@ void update_roll_pitch_mode(void)
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
// ACRO does not get SIMPLE mode ability // ACRO does not get SIMPLE mode ability
if (motors.flybar_mode == 1) { if (motors.has_flybar()) {
g.rc_1.servo_out = g.rc_1.control_in; g.rc_1.servo_out = g.rc_1.control_in;
g.rc_2.servo_out = g.rc_2.control_in; g.rc_2.servo_out = g.rc_2.control_in;
}else{ }else{
@ -1654,8 +1674,13 @@ void update_roll_pitch_mode(void)
// apply SIMPLE mode transform // apply SIMPLE mode transform
update_simple_mode(); update_simple_mode();
if(failsafe.radio) {
// don't allow copter to fly away during failsafe
get_pilot_desired_lean_angles(0.0f, 0.0f, control_roll, control_pitch);
} else {
// convert pilot input to lean angles // convert pilot input to lean angles
get_pilot_desired_lean_angles(g.rc_1.control_in, g.rc_2.control_in, control_roll, control_pitch); get_pilot_desired_lean_angles(g.rc_1.control_in, g.rc_2.control_in, control_roll, control_pitch);
}
// pass desired roll, pitch to stabilize attitude controllers // pass desired roll, pitch to stabilize attitude controllers
get_stabilize_roll(control_roll); get_stabilize_roll(control_roll);
@ -1679,18 +1704,21 @@ void update_roll_pitch_mode(void)
// apply SIMPLE mode transform // apply SIMPLE mode transform
update_simple_mode(); update_simple_mode();
if(failsafe.radio) {
// don't allow copter to fly away during failsafe
get_pilot_desired_lean_angles(0.0f, 0.0f, control_roll, control_pitch);
} else {
// convert pilot input to lean angles // convert pilot input to lean angles
get_pilot_desired_lean_angles(g.rc_1.control_in, g.rc_2.control_in, control_roll, control_pitch); get_pilot_desired_lean_angles(g.rc_1.control_in, g.rc_2.control_in, control_roll, control_pitch);
}
// mix in user control with optical flow // mix in user control with optical flow
get_stabilize_roll(get_of_roll(control_roll)); get_stabilize_roll(get_of_roll(control_roll));
get_stabilize_pitch(get_of_pitch(control_pitch)); get_stabilize_pitch(get_of_pitch(control_pitch));
break; break;
// THOR case ROLL_PITCH_DRIFT:
// a call out to the main toy logic get_roll_pitch_drift();
case ROLL_PITCH_TOY:
roll_pitch_toy();
break; break;
case ROLL_PITCH_LOITER: case ROLL_PITCH_LOITER:
@ -1701,8 +1729,13 @@ void update_roll_pitch_mode(void)
control_roll = g.rc_1.control_in; control_roll = g.rc_1.control_in;
control_pitch = g.rc_2.control_in; control_pitch = g.rc_2.control_in;
if(failsafe.radio) {
// don't allow loiter target to move during failsafe
wp_nav.move_loiter_target(0.0f, 0.0f, 0.01f);
} else {
// update loiter target from user controls // update loiter target from user controls
wp_nav.move_loiter_target(control_roll, control_pitch,0.01f); wp_nav.move_loiter_target(g.rc_1.control_in, g.rc_2.control_in, 0.01f);
}
// copy latest output from nav controller to stabilize controller // copy latest output from nav controller to stabilize controller
nav_roll = wp_nav.get_desired_roll(); nav_roll = wp_nav.get_desired_roll();
@ -1738,7 +1771,7 @@ void update_roll_pitch_mode(void)
get_stabilize_pitch(control_pitch); get_stabilize_pitch(control_pitch);
// copy user input for reporting purposes // copy user input for reporting purposes
get_autotune_roll_pitch_controller(g.rc_1.control_in, g.rc_2.control_in); get_autotune_roll_pitch_controller(g.rc_1.control_in, g.rc_2.control_in, g.rc_4.control_in);
break; break;
#endif #endif
} }
@ -1814,6 +1847,12 @@ void update_super_simple_bearing(bool force_update)
} }
} }
// throttle_mode_manual - returns true if the throttle is directly controlled by the pilot
bool throttle_mode_manual(uint8_t thr_mode)
{
return (thr_mode == THROTTLE_MANUAL || thr_mode == THROTTLE_MANUAL_TILT_COMPENSATED || thr_mode == THROTTLE_MANUAL_HELI);
}
// set_throttle_mode - sets the throttle mode and initialises any variables as required // set_throttle_mode - sets the throttle mode and initialises any variables as required
bool set_throttle_mode( uint8_t new_throttle_mode ) bool set_throttle_mode( uint8_t new_throttle_mode )
{ {
@ -1838,7 +1877,7 @@ bool set_throttle_mode( uint8_t new_throttle_mode )
case THROTTLE_AUTO: case THROTTLE_AUTO:
controller_desired_alt = get_initial_alt_hold(current_loc.alt, climb_rate); // reset controller desired altitude to current altitude controller_desired_alt = get_initial_alt_hold(current_loc.alt, climb_rate); // reset controller desired altitude to current altitude
wp_nav.set_desired_alt(controller_desired_alt); // same as above but for loiter controller wp_nav.set_desired_alt(controller_desired_alt); // same as above but for loiter controller
if ( throttle_mode <= THROTTLE_MANUAL_TILT_COMPENSATED ) { // reset the alt hold I terms if previous throttle mode was manual if (throttle_mode_manual(throttle_mode)) { // reset the alt hold I terms if previous throttle mode was manual
reset_throttle_I(); reset_throttle_I();
set_accel_throttle_I_from_pilot_throttle(get_pilot_desired_throttle(g.rc_3.control_in)); set_accel_throttle_I_from_pilot_throttle(get_pilot_desired_throttle(g.rc_3.control_in));
} }
@ -1850,6 +1889,14 @@ bool set_throttle_mode( uint8_t new_throttle_mode )
controller_desired_alt = get_initial_alt_hold(current_loc.alt, climb_rate); // reset controller desired altitude to current altitude controller_desired_alt = get_initial_alt_hold(current_loc.alt, climb_rate); // reset controller desired altitude to current altitude
throttle_initialised = true; throttle_initialised = true;
break; break;
#if FRAME_CONFIG == HELI_FRAME
case THROTTLE_MANUAL_HELI:
throttle_accel_deactivate(); // this controller does not use accel based throttle controller
altitude_error = 0; // clear altitude error reported to GCS
throttle_initialised = true;
break;
#endif
} }
// update the throttle mode // update the throttle mode
@ -1875,33 +1922,15 @@ void update_throttle_mode(void)
if(ap.do_flip) // this is pretty bad but needed to flip in AP modes. if(ap.do_flip) // this is pretty bad but needed to flip in AP modes.
return; return;
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG != HELI_FRAME
// do not run throttle controllers if motors disarmed
if (control_mode == STABILIZE){
motors.stab_throttle = true;
} else {
motors.stab_throttle = false;
}
// allow swash collective to move if we are in manual throttle modes, even if disarmed
if( !motors.armed() ) {
if ( !(throttle_mode == THROTTLE_MANUAL) && !(throttle_mode == THROTTLE_MANUAL_TILT_COMPENSATED)){
throttle_accel_deactivate(); // do not allow the accel based throttle to override our command
return;
}
}
#else // HELI_FRAME
// do not run throttle controllers if motors disarmed
if( !motors.armed() ) { if( !motors.armed() ) {
set_throttle_out(0, false); set_throttle_out(0, false);
throttle_accel_deactivate(); // do not allow the accel based throttle to override our command throttle_accel_deactivate(); // do not allow the accel based throttle to override our command
set_target_alt_for_reporting(0); set_target_alt_for_reporting(0);
return; return;
} }
#endif // FRAME_CONFIG != HELI_FRAME
#endif // HELI_FRAME
switch(throttle_mode) { switch(throttle_mode) {
@ -1916,12 +1945,11 @@ void update_throttle_mode(void)
// update estimate of throttle cruise // update estimate of throttle cruise
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
update_throttle_cruise(motors.coll_out); update_throttle_cruise(motors.get_collective_out());
#else #else
update_throttle_cruise(pilot_throttle_scaled); update_throttle_cruise(pilot_throttle_scaled);
#endif //HELI_FRAME #endif //HELI_FRAME
// check if we've taken off yet // check if we've taken off yet
if (!ap.takeoff_complete && motors.armed()) { if (!ap.takeoff_complete && motors.armed()) {
if (pilot_throttle_scaled > g.throttle_cruise) { if (pilot_throttle_scaled > g.throttle_cruise) {
@ -1943,7 +1971,7 @@ void update_throttle_mode(void)
// update estimate of throttle cruise // update estimate of throttle cruise
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
update_throttle_cruise(motors.coll_out); update_throttle_cruise(motors.get_collective_out());
#else #else
update_throttle_cruise(pilot_throttle_scaled); update_throttle_cruise(pilot_throttle_scaled);
#endif //HELI_FRAME #endif //HELI_FRAME
@ -2020,6 +2048,20 @@ void update_throttle_mode(void)
get_throttle_land(); get_throttle_land();
set_target_alt_for_reporting(0); set_target_alt_for_reporting(0);
break; break;
#if FRAME_CONFIG == HELI_FRAME
case THROTTLE_MANUAL_HELI:
// trad heli manual throttle controller
// send pilot's output directly to swash plate
pilot_throttle_scaled = get_pilot_desired_collective(g.rc_3.control_in);
set_throttle_out(pilot_throttle_scaled, false);
// update estimate of throttle cruise
update_throttle_cruise(motors.get_collective_out());
set_target_alt_for_reporting(0);
break;
#endif // HELI_FRAME
} }
} }
@ -2219,7 +2261,7 @@ static void tuning(){
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
case CH6_HELI_EXTERNAL_GYRO: case CH6_HELI_EXTERNAL_GYRO:
motors.ext_gyro_gain = tuning_value; motors.ext_gyro_gain(g.rc_6.control_in);
break; break;
#endif #endif

View File

@ -7,6 +7,10 @@ static void get_pilot_desired_lean_angles(int16_t roll_in, int16_t pitch_in, int
static float _scaler = 1.0; static float _scaler = 1.0;
static int16_t _angle_max = 0; static int16_t _angle_max = 0;
// range check the input
roll_in = constrain_int16(roll_in, -ROLL_PITCH_INPUT_MAX, ROLL_PITCH_INPUT_MAX);
pitch_in = constrain_int16(pitch_in, -ROLL_PITCH_INPUT_MAX, ROLL_PITCH_INPUT_MAX);
// return immediately if no scaling required // return immediately if no scaling required
if (g.angle_max == ROLL_PITCH_INPUT_MAX) { if (g.angle_max == ROLL_PITCH_INPUT_MAX) {
roll_out = roll_in; roll_out = roll_in;
@ -36,7 +40,7 @@ get_stabilize_roll(int32_t target_angle)
// constrain the target rate // constrain the target rate
if (!ap.disable_stab_rate_limit) { if (!ap.disable_stab_rate_limit) {
target_rate = constrain_int32(target_rate, -STABILIZE_RATE_LIMIT, STABILIZE_RATE_LIMIT); target_rate = constrain_int32(target_rate, -g.angle_rate_max, g.angle_rate_max);
} }
// set targets for rate controller // set targets for rate controller
@ -54,7 +58,7 @@ get_stabilize_pitch(int32_t target_angle)
// constrain the target rate // constrain the target rate
if (!ap.disable_stab_rate_limit) { if (!ap.disable_stab_rate_limit) {
target_rate = constrain_int32(target_rate, -STABILIZE_RATE_LIMIT, STABILIZE_RATE_LIMIT); target_rate = constrain_int32(target_rate, -g.angle_rate_max, g.angle_rate_max);
} }
// set targets for rate controller // set targets for rate controller
@ -79,7 +83,7 @@ get_stabilize_yaw(int32_t target_angle)
// do not use rate controllers for helicotpers with external gyros // do not use rate controllers for helicotpers with external gyros
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
if(motors.ext_gyro_enabled) { if(motors.tail_type() == AP_MOTORS_HELI_TAILTYPE_SERVO_EXTGYRO) {
g.rc_4.servo_out = constrain_int32(target_rate, -4500, 4500); g.rc_4.servo_out = constrain_int32(target_rate, -4500, 4500);
} }
#endif #endif
@ -99,15 +103,6 @@ get_stabilize_yaw(int32_t target_angle)
set_yaw_rate_target(target_rate, EARTH_FRAME); set_yaw_rate_target(target_rate, EARTH_FRAME);
} }
static void
get_acro_yaw(int32_t target_rate)
{
target_rate = target_rate * g.acro_yaw_p;
// set targets for rate controller
set_yaw_rate_target(target_rate, BODY_FRAME);
}
// get_acro_level_rates - calculate earth frame rate corrections to pull the copter back to level while in ACRO mode // get_acro_level_rates - calculate earth frame rate corrections to pull the copter back to level while in ACRO mode
static void static void
get_acro_level_rates() get_acro_level_rates()
@ -192,9 +187,15 @@ get_roll_rate_stabilized_bf(int32_t stick_angle)
// don't let angle error grow too large // don't let angle error grow too large
angle_error = constrain_float(angle_error, -MAX_ROLL_OVERSHOOT, MAX_ROLL_OVERSHOOT); angle_error = constrain_float(angle_error, -MAX_ROLL_OVERSHOOT, MAX_ROLL_OVERSHOOT);
#if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete()) {
angle_error = 0;
}
#else
if (!motors.armed() || g.rc_3.servo_out == 0) { if (!motors.armed() || g.rc_3.servo_out == 0) {
angle_error = 0; angle_error = 0;
} }
#endif // HELI_FRAME
} }
// Pitch with rate input and stabilized in the body frame // Pitch with rate input and stabilized in the body frame
@ -231,9 +232,15 @@ get_pitch_rate_stabilized_bf(int32_t stick_angle)
// don't let angle error grow too large // don't let angle error grow too large
angle_error = constrain_float(angle_error, -MAX_PITCH_OVERSHOOT, MAX_PITCH_OVERSHOOT); angle_error = constrain_float(angle_error, -MAX_PITCH_OVERSHOOT, MAX_PITCH_OVERSHOOT);
#if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete()) {
angle_error = 0;
}
#else
if (!motors.armed() || g.rc_3.servo_out == 0) { if (!motors.armed() || g.rc_3.servo_out == 0) {
angle_error = 0; angle_error = 0;
} }
#endif // HELI_FRAME
} }
// Yaw with rate input and stabilized in the body frame // Yaw with rate input and stabilized in the body frame
@ -270,9 +277,15 @@ get_yaw_rate_stabilized_bf(int32_t stick_angle)
// don't let angle error grow too large // don't let angle error grow too large
angle_error = constrain_float(angle_error, -MAX_YAW_OVERSHOOT, MAX_YAW_OVERSHOOT); angle_error = constrain_float(angle_error, -MAX_YAW_OVERSHOOT, MAX_YAW_OVERSHOOT);
#if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete()) {
angle_error = 0;
}
#else
if (!motors.armed() || g.rc_3.servo_out == 0) { if (!motors.armed() || g.rc_3.servo_out == 0) {
angle_error = 0; angle_error = 0;
} }
#endif // HELI_FRAME
} }
// Roll with rate input and stabilized in the earth frame // Roll with rate input and stabilized in the earth frame
@ -299,7 +312,7 @@ get_roll_rate_stabilized_ef(int32_t stick_angle)
} }
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete) { if (!motors.motor_runup_complete()) {
angle_error = 0; angle_error = 0;
} }
#else #else
@ -340,7 +353,7 @@ get_pitch_rate_stabilized_ef(int32_t stick_angle)
} }
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete) { if (!motors.motor_runup_complete()) {
angle_error = 0; angle_error = 0;
} }
#else #else
@ -378,7 +391,7 @@ get_yaw_rate_stabilized_ef(int32_t stick_angle)
angle_error = constrain_int32(angle_error, -MAX_YAW_OVERSHOOT, MAX_YAW_OVERSHOOT); angle_error = constrain_int32(angle_error, -MAX_YAW_OVERSHOOT, MAX_YAW_OVERSHOOT);
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
if (!motors.motor_runup_complete) { if (!motors.motor_runup_complete()) {
angle_error = 0; angle_error = 0;
} }
#else #else
@ -447,10 +460,15 @@ update_rate_contoller_targets()
void void
run_rate_controllers() run_rate_controllers()
{ {
#if FRAME_CONFIG == HELI_FRAME // helicopters only use rate controllers for yaw and only when not using an external gyro #if FRAME_CONFIG == HELI_FRAME
if(!motors.ext_gyro_enabled) { // convert desired roll and pitch rate to roll and pitch swash angles
heli_integrated_swash_controller(roll_rate_target_bf, pitch_rate_target_bf); heli_integrated_swash_controller(roll_rate_target_bf, pitch_rate_target_bf);
// helicopters only use rate controllers for yaw and only when not using an external gyro
if(motors.tail_type() != AP_MOTORS_HELI_TAILTYPE_SERVO_EXTGYRO) {
g.rc_4.servo_out = get_heli_rate_yaw(yaw_rate_target_bf); g.rc_4.servo_out = get_heli_rate_yaw(yaw_rate_target_bf);
}else{
// do not use rate controllers for helicotpers with external gyros
g.rc_4.servo_out = constrain_int32(yaw_rate_target_bf, -4500, 4500);
} }
#else #else
// call rate controllers // call rate controllers
@ -465,143 +483,6 @@ run_rate_controllers()
} }
} }
#if FRAME_CONFIG == HELI_FRAME
// init_rate_controllers - set-up filters for rate controller inputs
void init_rate_controllers()
{
// initalise low pass filters on rate controller inputs
// 1st parameter is time_step, 2nd parameter is time_constant
// rate_roll_filter.set_cutoff_frequency(0.01f, 0.1f);
// rate_pitch_filter.set_cutoff_frequency(0.01f, 0.1f);
}
static void heli_integrated_swash_controller(int32_t target_roll_rate, int32_t target_pitch_rate)
{
int32_t roll_p, roll_i, roll_d, roll_ff; // used to capture pid values for logging
int32_t pitch_p, pitch_i, pitch_d, pitch_ff;
int32_t current_roll_rate, current_pitch_rate; // this iteration's rate
int32_t roll_rate_error, pitch_rate_error; // simply target_rate - current_rate
int32_t roll_output, pitch_output; // output from pid controller
static bool roll_pid_saturated, pitch_pid_saturated; // tracker from last loop if the PID was saturated
current_roll_rate = (omega.x * DEGX100); // get current roll rate
current_pitch_rate = (omega.y * DEGX100); // get current pitch rate
roll_rate_error = target_roll_rate - current_roll_rate;
pitch_rate_error = target_pitch_rate - current_pitch_rate;
roll_p = g.pid_rate_roll.get_p(roll_rate_error);
pitch_p = g.pid_rate_pitch.get_p(pitch_rate_error);
if (roll_pid_saturated){
roll_i = g.pid_rate_roll.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
if (motors.flybar_mode == 1) { // Mechanical Flybars get regular integral for rate auto trim
if (target_roll_rate > -50 && target_roll_rate < 50){ // Frozen at high rates
roll_i = g.pid_rate_roll.get_i(roll_rate_error, G_Dt);
} else {
roll_i = g.pid_rate_roll.get_integrator();
}
} else {
roll_i = g.pid_rate_roll.get_leaky_i(roll_rate_error, G_Dt, RATE_INTEGRATOR_LEAK_RATE); // Flybarless Helis get huge I-terms. I-term controls much of the rate
}
}
if (pitch_pid_saturated){
pitch_i = g.pid_rate_pitch.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
if (motors.flybar_mode == 1) { // Mechanical Flybars get regular integral for rate auto trim
if (target_pitch_rate > -50 && target_pitch_rate < 50){ // Frozen at high rates
pitch_i = g.pid_rate_pitch.get_i(pitch_rate_error, G_Dt);
} else {
pitch_i = g.pid_rate_pitch.get_integrator();
}
} else {
pitch_i = g.pid_rate_pitch.get_leaky_i(pitch_rate_error, G_Dt, RATE_INTEGRATOR_LEAK_RATE); // Flybarless Helis get huge I-terms. I-term controls much of the rate
}
}
roll_d = g.pid_rate_roll.get_d(target_roll_rate, G_Dt);
pitch_d = g.pid_rate_pitch.get_d(target_pitch_rate, G_Dt);
roll_ff = g.heli_roll_ff * target_roll_rate;
pitch_ff = g.heli_pitch_ff * target_pitch_rate;
// Joly, I think your PC and CC code goes here
roll_output = roll_p + roll_i + roll_d + roll_ff;
pitch_output = pitch_p + pitch_i + pitch_d + pitch_ff;
if (labs(roll_output) > 4500){
roll_output = constrain_int32(roll_output, -4500, 4500); // constrain output
roll_pid_saturated = true; // freeze integrator next cycle
} else {
roll_pid_saturated = false; // unfreeze integrator
}
if (labs(pitch_output) > 4500){
pitch_output = constrain_int32(pitch_output, -4500, 4500); // constrain output
pitch_pid_saturated = true; // freeze integrator next cycle
} else {
pitch_pid_saturated = false; // unfreeze integrator
}
g.rc_1.servo_out = roll_output;
g.rc_2.servo_out = pitch_output;
}
static int16_t
get_heli_rate_yaw(int32_t target_rate)
{
int32_t p,i,d,ff; // used to capture pid values for logging
int32_t current_rate; // this iteration's rate
int32_t rate_error;
int32_t output;
static bool pid_saturated; // tracker from last loop if the PID was saturated
current_rate = (omega.z * DEGX100); // get current rate
// rate control
rate_error = target_rate - current_rate;
// separately calculate p, i, d values for logging
p = g.pid_rate_yaw.get_p(rate_error);
if (pid_saturated){
i = g.pid_rate_yaw.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
i = g.pid_rate_yaw.get_i(rate_error, G_Dt);
}
d = g.pid_rate_yaw.get_d(rate_error, G_Dt);
ff = g.heli_yaw_ff*target_rate;
output = p + i + d + ff;
if (labs(output) > 4500){
output = constrain_int32(output, -4500, 4500); // constrain output
pid_saturated = true; // freeze integrator next cycle
} else {
pid_saturated = false; // unfreeze integrator
}
#if LOGGING_ENABLED == ENABLED
// log output if PID loggins is on and we are tuning the yaw
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_RATE_KP || g.radio_tuning == CH6_YAW_RATE_KD) ) {
pid_log_counter++;
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
pid_log_counter = 0;
Log_Write_PID(CH6_YAW_RATE_KP, rate_error, p, i, d, output, tuning_value);
}
}
#endif
return output; // output control
}
#endif // HELI_FRAME
#if FRAME_CONFIG != HELI_FRAME #if FRAME_CONFIG != HELI_FRAME
static int16_t static int16_t
get_rate_roll(int32_t target_rate) get_rate_roll(int32_t target_rate)
@ -922,7 +803,7 @@ static int16_t get_angle_boost(int16_t throttle)
{ {
float angle_boost_factor = cos_pitch_x * cos_roll_x; float angle_boost_factor = cos_pitch_x * cos_roll_x;
angle_boost_factor = 1.0f - constrain_float(angle_boost_factor, .5f, 1.0f); angle_boost_factor = 1.0f - constrain_float(angle_boost_factor, .5f, 1.0f);
int16_t throttle_above_mid = max(throttle - motors.throttle_mid,0); int16_t throttle_above_mid = max(throttle - motors.get_collective_mid(),0);
// to allow logging of angle boost // to allow logging of angle boost
angle_boost = throttle_above_mid*angle_boost_factor; angle_boost = throttle_above_mid*angle_boost_factor;
@ -988,9 +869,8 @@ static void
set_throttle_takeoff() set_throttle_takeoff()
{ {
// set alt target // set alt target
if (controller_desired_alt < current_loc.alt) {
controller_desired_alt = current_loc.alt + ALT_HOLD_TAKEOFF_JUMP; controller_desired_alt = current_loc.alt + ALT_HOLD_TAKEOFF_JUMP;
}
// clear i term from acceleration controller // clear i term from acceleration controller
if (g.pid_throttle_accel.get_integrator() < 0) { if (g.pid_throttle_accel.get_integrator() < 0) {
g.pid_throttle_accel.reset_I(); g.pid_throttle_accel.reset_I();
@ -1037,8 +917,6 @@ get_throttle_accel(int16_t z_target_accel)
d = g.pid_throttle_accel.get_d(z_accel_error, .01f); d = g.pid_throttle_accel.get_d(z_accel_error, .01f);
//
// limit the rate
output = constrain_float(p+i+d+g.throttle_cruise, g.throttle_min, g.throttle_max); output = constrain_float(p+i+d+g.throttle_cruise, g.throttle_min, g.throttle_max);
#if LOGGING_ENABLED == ENABLED #if LOGGING_ENABLED == ENABLED

View File

@ -8,7 +8,9 @@
#define __GCS_H #define __GCS_H
#include <AP_HAL.h> #include <AP_HAL.h>
#include <AP_Common.h>
#include <GPS.h> #include <GPS.h>
#include <stdint.h>
/// ///
/// @class GCS /// @class GCS
@ -39,7 +41,6 @@ public:
/// ///
void init(AP_HAL::UARTDriver *port) { void init(AP_HAL::UARTDriver *port) {
_port = port; _port = port;
initialised = true;
} }
/// Update GCS state. /// Update GCS state.
@ -60,6 +61,14 @@ public:
void send_message(enum ap_message id) { void send_message(enum ap_message id) {
} }
/// Send a text message.
///
/// @param severity A value describing the importance of the message.
/// @param str The text to be sent.
///
void send_text(gcs_severity severity, const char *str) {
}
/// Send a text message with a PSTR() /// Send a text message with a PSTR()
/// ///
/// @param severity A value describing the importance of the message. /// @param severity A value describing the importance of the message.
@ -122,6 +131,10 @@ public:
// see if we should send a stream now. Called at 50Hz // see if we should send a stream now. Called at 50Hz
bool stream_trigger(enum streams stream_num); bool stream_trigger(enum streams stream_num);
// this costs us 51 bytes per instance, but means that low priority
// messages don't block the CPU
mavlink_statustext_t pending_status;
// call to reset the timeout window for entering the cli // call to reset the timeout window for entering the cli
void reset_cli_timeout(); void reset_cli_timeout();
private: private:
@ -140,6 +153,7 @@ private:
uint16_t _queued_parameter_count; ///< saved count of uint16_t _queued_parameter_count; ///< saved count of
// parameters for // parameters for
// queued send // queued send
uint32_t _queued_parameter_send_time_ms;
/// Count the number of reportable parameters. /// Count the number of reportable parameters.
/// ///
@ -179,16 +193,8 @@ private:
uint16_t waypoint_send_timeout; // milliseconds uint16_t waypoint_send_timeout; // milliseconds
uint16_t waypoint_receive_timeout; // milliseconds uint16_t waypoint_receive_timeout; // milliseconds
// data stream rates // saveable rate of each stream
AP_Int16 streamRateRawSensors; AP_Int16 streamRates[NUM_STREAMS];
AP_Int16 streamRateExtendedStatus;
AP_Int16 streamRateRCChannels;
AP_Int16 streamRateRawController;
AP_Int16 streamRatePosition;
AP_Int16 streamRateExtra1;
AP_Int16 streamRateExtra2;
AP_Int16 streamRateExtra3;
AP_Int16 streamRateParams;
// number of 50Hz ticks until we next send this stream // number of 50Hz ticks until we next send this stream
uint8_t stream_ticks[NUM_STREAMS]; uint8_t stream_ticks[NUM_STREAMS];

View File

@ -6,11 +6,6 @@
// use this to prevent recursion during sensor init // use this to prevent recursion during sensor init
static bool in_mavlink_delay; static bool in_mavlink_delay;
// this costs us 51 bytes, but means that low priority
// messages don't block the CPU
static mavlink_statustext_t pending_status;
// true when we have received at least 1 MAVLink packet // true when we have received at least 1 MAVLink packet
static bool mavlink_active; static bool mavlink_active;
@ -105,6 +100,8 @@ static NOINLINE void send_heartbeat(mavlink_channel_t chan)
MAV_TYPE_OCTOROTOR, MAV_TYPE_OCTOROTOR,
#elif (FRAME_CONFIG == HELI_FRAME) #elif (FRAME_CONFIG == HELI_FRAME)
MAV_TYPE_HELICOPTER, MAV_TYPE_HELICOPTER,
#elif (FRAME_CONFIG == SINGLE_FRAME) //because mavlink did not define a singlecopter, we use a rocket
MAV_TYPE_ROCKET,
#else #else
#error Unrecognised frame type #error Unrecognised frame type
#endif #endif
@ -156,6 +153,9 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
control_sensors_present |= MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW; control_sensors_present |= MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW;
} }
#endif #endif
if (ap.rc_receiver_present) {
control_sensors_present |= MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
}
// all present sensors enabled by default except altitude and position control which we will set individually // all present sensors enabled by default except altitude and position control which we will set individually
control_sensors_enabled = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL & ~MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL); control_sensors_enabled = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL & ~MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL);
@ -180,14 +180,20 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
break; break;
} }
// default to all healthy except compass and gps which we set individually // default to all healthy except compass, gps and receiver which we set individually
control_sensors_health = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_3D_MAG & ~MAV_SYS_STATUS_SENSOR_GPS); control_sensors_health = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_3D_MAG & ~MAV_SYS_STATUS_SENSOR_GPS & ~MAV_SYS_STATUS_SENSOR_RC_RECEIVER);
if (g.compass_enabled && compass.healthy && ahrs.use_compass()) { if (g.compass_enabled && compass.healthy && ahrs.use_compass()) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_3D_MAG; control_sensors_health |= MAV_SYS_STATUS_SENSOR_3D_MAG;
} }
if (g_gps != NULL && g_gps->status() > GPS::NO_GPS && !gps_glitch.glitching()) { if (g_gps != NULL && g_gps->status() > GPS::NO_GPS && !gps_glitch.glitching()) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS; control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS;
} }
if (ap.rc_receiver_present && !failsafe.radio) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_RC_RECEIVER;
}
if (!ins.healthy()) {
control_sensors_health &= ~(MAV_SYS_STATUS_SENSOR_3D_GYRO | MAV_SYS_STATUS_SENSOR_3D_ACCEL);
}
int16_t battery_current = -1; int16_t battery_current = -1;
int8_t battery_remaining = -1; int8_t battery_remaining = -1;
@ -307,6 +313,14 @@ static void NOINLINE send_gps_raw(mavlink_channel_t chan)
} }
static void NOINLINE send_system_time(mavlink_channel_t chan)
{
mavlink_msg_system_time_send(
chan,
g_gps->time_epoch_usec(),
hal.scheduler->millis());
}
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
static void NOINLINE send_servo_out(mavlink_channel_t chan) static void NOINLINE send_servo_out(mavlink_channel_t chan)
{ {
@ -455,9 +469,9 @@ static void NOINLINE send_raw_imu2(mavlink_channel_t chan)
static void NOINLINE send_raw_imu3(mavlink_channel_t chan) static void NOINLINE send_raw_imu3(mavlink_channel_t chan)
{ {
Vector3f mag_offsets = compass.get_offsets(); const Vector3f &mag_offsets = compass.get_offsets();
Vector3f accel_offsets = ins.get_accel_offsets(); const Vector3f &accel_offsets = ins.get_accel_offsets();
Vector3f gyro_offsets = ins.get_gyro_offsets(); const Vector3f &gyro_offsets = ins.get_gyro_offsets();
mavlink_msg_sensor_offsets_send(chan, mavlink_msg_sensor_offsets_send(chan,
mag_offsets.x, mag_offsets.x,
@ -483,10 +497,11 @@ static void NOINLINE send_current_waypoint(mavlink_channel_t chan)
static void NOINLINE send_statustext(mavlink_channel_t chan) static void NOINLINE send_statustext(mavlink_channel_t chan)
{ {
mavlink_statustext_t *s = &gcs[chan-MAVLINK_COMM_0].pending_status;
mavlink_msg_statustext_send( mavlink_msg_statustext_send(
chan, chan,
pending_status.severity, s->severity,
pending_status.text); s->text);
} }
// are we still delaying telemetry to try to avoid Xbee bricking? // are we still delaying telemetry to try to avoid Xbee bricking?
@ -561,6 +576,11 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
send_gps_raw(chan); send_gps_raw(chan);
break; break;
case MSG_SYSTEM_TIME:
CHECK_PAYLOAD_SIZE(SYSTEM_TIME);
send_system_time(chan);
break;
case MSG_SERVO_OUT: case MSG_SERVO_OUT:
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED); CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED);
@ -605,20 +625,12 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
case MSG_NEXT_PARAM: case MSG_NEXT_PARAM:
CHECK_PAYLOAD_SIZE(PARAM_VALUE); CHECK_PAYLOAD_SIZE(PARAM_VALUE);
if (chan == MAVLINK_COMM_0) { gcs[chan-MAVLINK_COMM_0].queued_param_send();
gcs0.queued_param_send();
} else if (gcs3.initialised) {
gcs3.queued_param_send();
}
break; break;
case MSG_NEXT_WAYPOINT: case MSG_NEXT_WAYPOINT:
CHECK_PAYLOAD_SIZE(MISSION_REQUEST); CHECK_PAYLOAD_SIZE(MISSION_REQUEST);
if (chan == MAVLINK_COMM_0) { gcs[chan-MAVLINK_COMM_0].queued_waypoint_send();
gcs0.queued_waypoint_send();
} else if (gcs3.initialised) {
gcs3.queued_waypoint_send();
}
break; break;
case MSG_STATUSTEXT: case MSG_STATUSTEXT:
@ -663,7 +675,7 @@ static struct mavlink_queue {
enum ap_message deferred_messages[MAX_DEFERRED_MESSAGES]; enum ap_message deferred_messages[MAX_DEFERRED_MESSAGES];
uint8_t next_deferred_message; uint8_t next_deferred_message;
uint8_t num_deferred_messages; uint8_t num_deferred_messages;
} mavlink_queue[2]; } mavlink_queue[MAVLINK_COMM_NUM_BUFFERS];
// send a message using mavlink // send a message using mavlink
static void mavlink_send_message(mavlink_channel_t chan, enum ap_message id, uint16_t packet_drops) static void mavlink_send_message(mavlink_channel_t chan, enum ap_message id, uint16_t packet_drops)
@ -725,15 +737,13 @@ void mavlink_send_text(mavlink_channel_t chan, gcs_severity severity, const char
if (severity == SEVERITY_LOW) { if (severity == SEVERITY_LOW) {
// send via the deferred queuing system // send via the deferred queuing system
pending_status.severity = (uint8_t)severity; mavlink_statustext_t *s = &gcs[chan-MAVLINK_COMM_0].pending_status;
strncpy((char *)pending_status.text, str, sizeof(pending_status.text)); s->severity = (uint8_t)severity;
strncpy((char *)s->text, str, sizeof(s->text));
mavlink_send_message(chan, MSG_STATUSTEXT, 0); mavlink_send_message(chan, MSG_STATUSTEXT, 0);
} else { } else {
// send immediately // send immediately
mavlink_msg_statustext_send( mavlink_msg_statustext_send(chan, severity, str);
chan,
severity,
str);
} }
} }
@ -745,7 +755,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("RAW_SENS", 0, GCS_MAVLINK, streamRateRawSensors, 0), AP_GROUPINFO("RAW_SENS", 0, GCS_MAVLINK, streamRates[0], 0),
// @Param: EXT_STAT // @Param: EXT_STAT
// @DisplayName: Extended status stream rate to ground station // @DisplayName: Extended status stream rate to ground station
@ -754,7 +764,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("EXT_STAT", 1, GCS_MAVLINK, streamRateExtendedStatus, 0), AP_GROUPINFO("EXT_STAT", 1, GCS_MAVLINK, streamRates[1], 0),
// @Param: RC_CHAN // @Param: RC_CHAN
// @DisplayName: RC Channel stream rate to ground station // @DisplayName: RC Channel stream rate to ground station
@ -763,7 +773,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("RC_CHAN", 2, GCS_MAVLINK, streamRateRCChannels, 0), AP_GROUPINFO("RC_CHAN", 2, GCS_MAVLINK, streamRates[2], 0),
// @Param: RAW_CTRL // @Param: RAW_CTRL
// @DisplayName: Raw Control stream rate to ground station // @DisplayName: Raw Control stream rate to ground station
@ -772,7 +782,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("RAW_CTRL", 3, GCS_MAVLINK, streamRateRawController, 0), AP_GROUPINFO("RAW_CTRL", 3, GCS_MAVLINK, streamRates[3], 0),
// @Param: POSITION // @Param: POSITION
// @DisplayName: Position stream rate to ground station // @DisplayName: Position stream rate to ground station
@ -781,7 +791,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("POSITION", 4, GCS_MAVLINK, streamRatePosition, 0), AP_GROUPINFO("POSITION", 4, GCS_MAVLINK, streamRates[4], 0),
// @Param: EXTRA1 // @Param: EXTRA1
// @DisplayName: Extra data type 1 stream rate to ground station // @DisplayName: Extra data type 1 stream rate to ground station
@ -790,7 +800,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("EXTRA1", 5, GCS_MAVLINK, streamRateExtra1, 0), AP_GROUPINFO("EXTRA1", 5, GCS_MAVLINK, streamRates[5], 0),
// @Param: EXTRA2 // @Param: EXTRA2
// @DisplayName: Extra data type 2 stream rate to ground station // @DisplayName: Extra data type 2 stream rate to ground station
@ -799,7 +809,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("EXTRA2", 6, GCS_MAVLINK, streamRateExtra2, 0), AP_GROUPINFO("EXTRA2", 6, GCS_MAVLINK, streamRates[6], 0),
// @Param: EXTRA3 // @Param: EXTRA3
// @DisplayName: Extra data type 3 stream rate to ground station // @DisplayName: Extra data type 3 stream rate to ground station
@ -808,7 +818,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("EXTRA3", 7, GCS_MAVLINK, streamRateExtra3, 0), AP_GROUPINFO("EXTRA3", 7, GCS_MAVLINK, streamRates[7], 0),
// @Param: PARAMS // @Param: PARAMS
// @DisplayName: Parameter stream rate to ground station // @DisplayName: Parameter stream rate to ground station
@ -817,7 +827,7 @@ const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Range: 0 10 // @Range: 0 10
// @Increment: 1 // @Increment: 1
// @User: Advanced // @User: Advanced
AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK, streamRateParams, 0), AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK, streamRates[8], 0),
AP_GROUPEND AP_GROUPEND
}; };
@ -834,12 +844,20 @@ void
GCS_MAVLINK::init(AP_HAL::UARTDriver* port) GCS_MAVLINK::init(AP_HAL::UARTDriver* port)
{ {
GCS_Class::init(port); GCS_Class::init(port);
if (port == hal.uartA) { if (port == (AP_HAL::BetterStream*)hal.uartA) {
mavlink_comm_0_port = port; mavlink_comm_0_port = port;
chan = MAVLINK_COMM_0; chan = MAVLINK_COMM_0;
}else{ initialised = true;
} else if (port == (AP_HAL::BetterStream*)hal.uartC) {
mavlink_comm_1_port = port; mavlink_comm_1_port = port;
chan = MAVLINK_COMM_1; chan = MAVLINK_COMM_1;
initialised = true;
#if MAVLINK_COMM_NUM_BUFFERS > 2
} else if (port == (AP_HAL::BetterStream*)hal.uartD) {
mavlink_comm_2_port = port;
chan = MAVLINK_COMM_2;
initialised = true;
#endif
} }
_queued_parameter = NULL; _queued_parameter = NULL;
reset_cli_timeout(); reset_cli_timeout();
@ -855,7 +873,8 @@ GCS_MAVLINK::update(void)
// process received bytes // process received bytes
uint16_t nbytes = comm_get_available(chan); uint16_t nbytes = comm_get_available(chan);
for (uint16_t i=0; i<nbytes; i++) { for (uint16_t i=0; i<nbytes; i++)
{
uint8_t c = comm_receive_ch(chan); uint8_t c = comm_receive_ch(chan);
#if CLI_ENABLED == ENABLED #if CLI_ENABLED == ENABLED
@ -915,40 +934,19 @@ GCS_MAVLINK::update(void)
// see if we should send a stream now. Called at 50Hz // see if we should send a stream now. Called at 50Hz
bool GCS_MAVLINK::stream_trigger(enum streams stream_num) bool GCS_MAVLINK::stream_trigger(enum streams stream_num)
{ {
uint8_t rate; if (stream_num >= NUM_STREAMS) {
switch (stream_num) { return false;
case STREAM_RAW_SENSORS: }
rate = streamRateRawSensors.get(); float rate = (uint8_t)streamRates[stream_num].get();
break;
case STREAM_EXTENDED_STATUS: // send at a much lower rate while handling waypoints and
rate = streamRateExtendedStatus.get(); // parameter sends
break; if ((stream_num != STREAM_PARAMS) &&
case STREAM_RC_CHANNELS: (waypoint_receiving || _queued_parameter != NULL)) {
rate = streamRateRCChannels.get(); rate *= 0.25;
break;
case STREAM_RAW_CONTROLLER:
rate = streamRateRawController.get();
break;
case STREAM_POSITION:
rate = streamRatePosition.get();
break;
case STREAM_EXTRA1:
rate = streamRateExtra1.get();
break;
case STREAM_EXTRA2:
rate = streamRateExtra2.get();
break;
case STREAM_EXTRA3:
rate = streamRateExtra3.get();
break;
case STREAM_PARAMS:
rate = streamRateParams.get();
break;
default:
rate = 0;
} }
if (rate == 0) { if (rate <= 0) {
return false; return false;
} }
@ -977,8 +975,8 @@ GCS_MAVLINK::data_stream_send(void)
gcs_out_of_time = false; gcs_out_of_time = false;
if (_queued_parameter != NULL) { if (_queued_parameter != NULL) {
if (streamRateParams.get() <= 0) { if (streamRates[STREAM_PARAMS].get() <= 0) {
streamRateParams.set(50); streamRates[STREAM_PARAMS].set(10);
} }
if (stream_trigger(STREAM_PARAMS)) { if (stream_trigger(STREAM_PARAMS)) {
send_message(MSG_NEXT_PARAM); send_message(MSG_NEXT_PARAM);
@ -1048,6 +1046,7 @@ GCS_MAVLINK::data_stream_send(void)
if (stream_trigger(STREAM_EXTRA3)) { if (stream_trigger(STREAM_EXTRA3)) {
send_message(MSG_AHRS); send_message(MSG_AHRS);
send_message(MSG_HWSTATUS); send_message(MSG_HWSTATUS);
send_message(MSG_SYSTEM_TIME);
} }
} }
@ -1077,9 +1076,10 @@ GCS_MAVLINK::send_text_P(gcs_severity severity, const prog_char_t *str)
void GCS_MAVLINK::handleMessage(mavlink_message_t* msg) void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
{ {
struct Location tell_command = {}; // command for telemetry struct Location tell_command = {}; // command for telemetry
switch (msg->msgid) { switch (msg->msgid) {
case MAVLINK_MSG_ID_REQUEST_DATA_STREAM: //66 case MAVLINK_MSG_ID_REQUEST_DATA_STREAM:
{ {
// decode // decode
mavlink_request_data_stream_t packet; mavlink_request_data_stream_t packet;
@ -1100,32 +1100,22 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
switch(packet.req_stream_id) { switch(packet.req_stream_id) {
case MAV_DATA_STREAM_ALL: case MAV_DATA_STREAM_ALL:
streamRateRawSensors = freq; // note that we don't set STREAM_PARAMS - that is internal only
streamRateExtendedStatus = freq; for (uint8_t i=0; i<STREAM_PARAMS; i++) {
streamRateRCChannels = freq; streamRates[i].set(freq);
streamRateRawController = freq; }
streamRatePosition = freq;
streamRateExtra1 = freq;
streamRateExtra2 = freq;
//streamRateExtra3.set_and_save(freq); // We just do set and save on the last as it takes care of the whole group.
streamRateExtra3 = freq; // Don't save!!
break; break;
case MAV_DATA_STREAM_RAW_SENSORS: case MAV_DATA_STREAM_RAW_SENSORS:
streamRateRawSensors = freq; // We do not set and save this one so that if HIL is shut down incorrectly streamRates[STREAM_RAW_SENSORS].set(freq);
// we will not continue to broadcast raw sensor data at 50Hz.
break; break;
case MAV_DATA_STREAM_EXTENDED_STATUS: case MAV_DATA_STREAM_EXTENDED_STATUS:
//streamRateExtendedStatus.set_and_save(freq); streamRates[STREAM_EXTENDED_STATUS].set(freq);
streamRateExtendedStatus = freq;
break; break;
case MAV_DATA_STREAM_RC_CHANNELS: case MAV_DATA_STREAM_RC_CHANNELS:
streamRateRCChannels = freq; streamRates[STREAM_RC_CHANNELS].set(freq);
break; break;
case MAV_DATA_STREAM_RAW_CONTROLLER: case MAV_DATA_STREAM_RAW_CONTROLLER:
streamRateRawController = freq; streamRates[STREAM_RAW_CONTROLLER].set(freq);
break; break;
//case MAV_DATA_STREAM_RAW_SENSOR_FUSION: //case MAV_DATA_STREAM_RAW_SENSOR_FUSION:
@ -1133,22 +1123,16 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
// break; // break;
case MAV_DATA_STREAM_POSITION: case MAV_DATA_STREAM_POSITION:
streamRatePosition = freq; streamRates[STREAM_POSITION].set(freq);
break; break;
case MAV_DATA_STREAM_EXTRA1: case MAV_DATA_STREAM_EXTRA1:
streamRateExtra1 = freq; streamRates[STREAM_EXTRA1].set(freq);
break; break;
case MAV_DATA_STREAM_EXTRA2: case MAV_DATA_STREAM_EXTRA2:
streamRateExtra2 = freq; streamRates[STREAM_EXTRA2].set(freq);
break; break;
case MAV_DATA_STREAM_EXTRA3: case MAV_DATA_STREAM_EXTRA3:
streamRateExtra3 = freq; streamRates[STREAM_EXTRA3].set(freq);
break;
default:
break; break;
} }
break; break;
@ -1190,11 +1174,15 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
case MAV_CMD_PREFLIGHT_CALIBRATION: case MAV_CMD_PREFLIGHT_CALIBRATION:
if (packet.param1 == 1 || if (packet.param1 == 1 ||
packet.param2 == 1 || packet.param2 == 1) {
packet.param3 == 1) {
ins.init_accel(); ins.init_accel();
ahrs.set_trim(Vector3f(0,0,0)); // clear out saved trim ahrs.set_trim(Vector3f(0,0,0)); // clear out saved trim
} }
if (packet.param3 == 1) {
#if HIL_MODE != HIL_MODE_ATTITUDE
init_barometer();
#endif
}
if (packet.param4 == 1) { if (packet.param4 == 1) {
trim_radio(); trim_radio();
} }
@ -1252,7 +1240,8 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_SET_MODE: //11
case MAVLINK_MSG_ID_SET_MODE:
{ {
// decode // decode
mavlink_set_mode_t packet; mavlink_set_mode_t packet;
@ -1280,8 +1269,6 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
*/ */
case MAVLINK_MSG_ID_MISSION_REQUEST_LIST: //43 case MAVLINK_MSG_ID_MISSION_REQUEST_LIST: //43
{ {
//send_text_P(SEVERITY_LOW,PSTR("waypoint request list"));
// decode // decode
mavlink_mission_request_list_t packet; mavlink_mission_request_list_t packet;
mavlink_msg_mission_request_list_decode(msg, &packet); mavlink_msg_mission_request_list_decode(msg, &packet);
@ -1305,8 +1292,6 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
// XXX read a WP from EEPROM and send it to the GCS // XXX read a WP from EEPROM and send it to the GCS
case MAVLINK_MSG_ID_MISSION_REQUEST: // 40 case MAVLINK_MSG_ID_MISSION_REQUEST: // 40
{ {
//send_text_P(SEVERITY_LOW,PSTR("waypoint request"));
// Check if sending waypiont // Check if sending waypiont
//if (!waypoint_sending) break; //if (!waypoint_sending) break;
// 5/10/11 - We are trying out relaxing the requirement that we be in waypoint sending mode to respond to a waypoint request. DEW // 5/10/11 - We are trying out relaxing the requirement that we be in waypoint sending mode to respond to a waypoint request. DEW
@ -1362,6 +1347,9 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
case MAV_CMD_NAV_ROI: case MAV_CMD_NAV_ROI:
case MAV_CMD_DO_SET_ROI: case MAV_CMD_DO_SET_ROI:
param1 = tell_command.p1; // MAV_ROI (aka roi mode) is held in wp's parameter but we actually do nothing with it because we only support pointing at a specific location provided by x,y and z parameters param1 = tell_command.p1; // MAV_ROI (aka roi mode) is held in wp's parameter but we actually do nothing with it because we only support pointing at a specific location provided by x,y and z parameters
x = tell_command.lat/1.0e7f; // local (x), global (latitude)
y = tell_command.lng/1.0e7f; // local (y), global (longitude)
z = tell_command.alt/1.0e2f; // local (z), global/relative (altitude)
break; break;
case MAV_CMD_CONDITION_YAW: case MAV_CMD_CONDITION_YAW:
@ -1434,10 +1422,9 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_MISSION_ACK: //47
{
//send_text_P(SEVERITY_LOW,PSTR("waypoint ack"));
case MAVLINK_MSG_ID_MISSION_ACK:
{
// decode // decode
mavlink_mission_ack_t packet; mavlink_mission_ack_t packet;
mavlink_msg_mission_ack_decode(msg, &packet); mavlink_msg_mission_ack_decode(msg, &packet);
@ -1448,17 +1435,17 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_PARAM_REQUEST_LIST: // 21 case MAVLINK_MSG_ID_PARAM_REQUEST_LIST:
{ {
// gcs_send_text_P(SEVERITY_LOW,PSTR("param request list"));
// decode // decode
mavlink_param_request_list_t packet; mavlink_param_request_list_t packet;
mavlink_msg_param_request_list_decode(msg, &packet); mavlink_msg_param_request_list_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break; if (mavlink_check_target(packet.target_system,packet.target_component)) break;
// Start sending parameters - next call to ::update will kick the first one out // mark the firmware version in the tlog
send_text_P(SEVERITY_LOW, PSTR(FIRMWARE_STRING));
// Start sending parameters - next call to ::update will kick the first one out
_queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type); _queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index = 0; _queued_parameter_index = 0;
_queued_parameter_count = _count_parameters(); _queued_parameter_count = _count_parameters();
@ -1504,10 +1491,8 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_MISSION_CLEAR_ALL: // 45 case MAVLINK_MSG_ID_MISSION_CLEAR_ALL:
{ {
//send_text_P(SEVERITY_LOW,PSTR("waypoint clear all"));
// decode // decode
mavlink_mission_clear_all_t packet; mavlink_mission_clear_all_t packet;
mavlink_msg_mission_clear_all_decode(msg, &packet); mavlink_msg_mission_clear_all_decode(msg, &packet);
@ -1524,10 +1509,8 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_MISSION_SET_CURRENT: // 41 case MAVLINK_MSG_ID_MISSION_SET_CURRENT:
{ {
//send_text_P(SEVERITY_LOW,PSTR("waypoint set current"));
// decode // decode
mavlink_mission_set_current_t packet; mavlink_mission_set_current_t packet;
mavlink_msg_mission_set_current_decode(msg, &packet); mavlink_msg_mission_set_current_decode(msg, &packet);
@ -1540,10 +1523,8 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
break; break;
} }
case MAVLINK_MSG_ID_MISSION_COUNT: // 44 case MAVLINK_MSG_ID_MISSION_COUNT:
{ {
//send_text_P(SEVERITY_LOW,PSTR("waypoint count"));
// decode // decode
mavlink_mission_count_t packet; mavlink_mission_count_t packet;
mavlink_msg_mission_count_decode(msg, &packet); mavlink_msg_mission_count_decode(msg, &packet);
@ -1603,7 +1584,7 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
#endif #endif
// XXX receive a WP from GCS and store in EEPROM // XXX receive a WP from GCS and store in EEPROM
case MAVLINK_MSG_ID_MISSION_ITEM: //39 case MAVLINK_MSG_ID_MISSION_ITEM:
{ {
// decode // decode
uint8_t result = MAV_MISSION_ACCEPTED; uint8_t result = MAV_MISSION_ACCEPTED;
@ -1863,7 +1844,7 @@ mission_failed:
break; break;
} // end case } // end case
case MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE: //70 case MAVLINK_MSG_ID_RC_CHANNELS_OVERRIDE:
{ {
// allow override of RC channel values for HIL // allow override of RC channel values for HIL
// or for complete GCS control of switch position // or for complete GCS control of switch position
@ -2077,9 +2058,23 @@ GCS_MAVLINK::_count_parameters()
void void
GCS_MAVLINK::queued_param_send() GCS_MAVLINK::queued_param_send()
{ {
// Check to see if we are sending parameters if (!initialised || _queued_parameter == NULL) {
if (NULL == _queued_parameter) return; return;
}
uint16_t bytes_allowed;
uint8_t count;
uint32_t tnow = millis();
// use at most 30% of bandwidth on parameters. The constant 26 is
// 1/(1000 * 1/8 * 0.001 * 0.3)
bytes_allowed = g.serial1_baud * (tnow - _queued_parameter_send_time_ms) * 26;
if (bytes_allowed > comm_get_txspace(chan)) {
bytes_allowed = comm_get_txspace(chan);
}
count = bytes_allowed / (MAVLINK_MSG_ID_PARAM_VALUE_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES);
while (_queued_parameter != NULL && count--) {
AP_Param *vp; AP_Param *vp;
float value; float value;
@ -2103,6 +2098,8 @@ GCS_MAVLINK::queued_param_send()
_queued_parameter = AP_Param::next_scalar(&_queued_parameter_token, &_queued_parameter_type); _queued_parameter = AP_Param::next_scalar(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index++; _queued_parameter_index++;
} }
_queued_parameter_send_time_ms = tnow;
}
/** /**
* queued_waypoint_send - Send the next pending waypoint, called from deferred message * queued_waypoint_send - Send the next pending waypoint, called from deferred message
@ -2134,8 +2131,7 @@ void GCS_MAVLINK::reset_cli_timeout() {
static void mavlink_delay_cb() static void mavlink_delay_cb()
{ {
static uint32_t last_1hz, last_50hz, last_5s; static uint32_t last_1hz, last_50hz, last_5s;
if (!gcs[0].initialised) return;
if (!gcs0.initialised) return;
in_mavlink_delay = true; in_mavlink_delay = true;
@ -2166,9 +2162,10 @@ static void mavlink_delay_cb()
*/ */
static void gcs_send_message(enum ap_message id) static void gcs_send_message(enum ap_message id)
{ {
gcs0.send_message(id); for (uint8_t i=0; i<num_gcs; i++) {
if (gcs3.initialised) { if (gcs[i].initialised) {
gcs3.send_message(id); gcs[i].send_message(id);
}
} }
} }
@ -2177,9 +2174,10 @@ static void gcs_send_message(enum ap_message id)
*/ */
static void gcs_data_stream_send(void) static void gcs_data_stream_send(void)
{ {
gcs0.data_stream_send(); for (uint8_t i=0; i<num_gcs; i++) {
if (gcs3.initialised) { if (gcs[i].initialised) {
gcs3.data_stream_send(); gcs[i].data_stream_send();
}
} }
} }
@ -2188,17 +2186,19 @@ static void gcs_data_stream_send(void)
*/ */
static void gcs_check_input(void) static void gcs_check_input(void)
{ {
gcs0.update(); for (uint8_t i=0; i<num_gcs; i++) {
if (gcs3.initialised) { if (gcs[i].initialised) {
gcs3.update(); gcs[i].update();
}
} }
} }
static void gcs_send_text_P(gcs_severity severity, const prog_char_t *str) static void gcs_send_text_P(gcs_severity severity, const prog_char_t *str)
{ {
gcs0.send_text_P(severity, str); for (uint8_t i=0; i<num_gcs; i++) {
if (gcs3.initialised) { if (gcs[i].initialised) {
gcs3.send_text_P(severity, str); gcs[i].send_text_P(severity, str);
}
} }
} }
@ -2207,17 +2207,19 @@ static void gcs_send_text_P(gcs_severity severity, const prog_char_t *str)
* only one fits in the queue, so if you send more than one before the * only one fits in the queue, so if you send more than one before the
* last one gets into the serial buffer then the old one will be lost * last one gets into the serial buffer then the old one will be lost
*/ */
static void gcs_send_text_fmt(const prog_char_t *fmt, ...) void gcs_send_text_fmt(const prog_char_t *fmt, ...)
{ {
va_list arg_list; va_list arg_list;
pending_status.severity = (uint8_t)SEVERITY_LOW; gcs[0].pending_status.severity = (uint8_t)SEVERITY_LOW;
va_start(arg_list, fmt); va_start(arg_list, fmt);
hal.util->vsnprintf_P((char *)pending_status.text, hal.util->vsnprintf_P((char *)gcs[0].pending_status.text,
sizeof(pending_status.text), fmt, arg_list); sizeof(gcs[0].pending_status.text), fmt, arg_list);
va_end(arg_list); va_end(arg_list);
mavlink_send_message(MAVLINK_COMM_0, MSG_STATUSTEXT, 0); mavlink_send_message(MAVLINK_COMM_0, MSG_STATUSTEXT, 0);
if (gcs3.initialised) { for (uint8_t i=1; i<num_gcs; i++) {
mavlink_send_message(MAVLINK_COMM_1, MSG_STATUSTEXT, 0); if (gcs[i].initialised) {
gcs[i].pending_status = gcs[0].pending_status;
mavlink_send_message((mavlink_channel_t)i, MSG_STATUSTEXT, 0);
}
} }
} }

View File

@ -208,7 +208,7 @@ static void Log_Write_AutoTuneDetails(int16_t angle_cd, float rate_cds)
struct PACKED log_Current { struct PACKED log_Current {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
int16_t throttle_in; int16_t throttle_out;
uint32_t throttle_integrator; uint32_t throttle_integrator;
int16_t battery_voltage; int16_t battery_voltage;
int16_t current_amps; int16_t current_amps;
@ -221,7 +221,7 @@ static void Log_Write_Current()
{ {
struct log_Current pkt = { struct log_Current pkt = {
LOG_PACKET_HEADER_INIT(LOG_CURRENT_MSG), LOG_PACKET_HEADER_INIT(LOG_CURRENT_MSG),
throttle_in : g.rc_3.control_in, throttle_out : g.rc_3.servo_out,
throttle_integrator : throttle_integrator, throttle_integrator : throttle_integrator,
battery_voltage : (int16_t) (battery.voltage() * 100.0f), battery_voltage : (int16_t) (battery.voltage() * 100.0f),
current_amps : (int16_t) (battery.current_amps() * 100.0f), current_amps : (int16_t) (battery.current_amps() * 100.0f),
@ -238,8 +238,7 @@ struct PACKED log_Motors {
#elif FRAME_CONFIG == HEXA_FRAME || FRAME_CONFIG == Y6_FRAME #elif FRAME_CONFIG == HEXA_FRAME || FRAME_CONFIG == Y6_FRAME
int16_t motor_out[6]; int16_t motor_out[6];
#elif FRAME_CONFIG == HELI_FRAME #elif FRAME_CONFIG == HELI_FRAME
int16_t motor_out[4]; int16_t motor_out[6];
int16_t ext_gyro_gain;
#else // quads & TRI_FRAME #else // quads & TRI_FRAME
int16_t motor_out[4]; int16_t motor_out[4];
#endif #endif
@ -270,13 +269,14 @@ static void Log_Write_Motors()
motor_out : {motors.motor_out[AP_MOTORS_MOT_1], motor_out : {motors.motor_out[AP_MOTORS_MOT_1],
motors.motor_out[AP_MOTORS_MOT_2], motors.motor_out[AP_MOTORS_MOT_2],
motors.motor_out[AP_MOTORS_MOT_3], motors.motor_out[AP_MOTORS_MOT_3],
motors.motor_out[AP_MOTORS_MOT_4]}, motors.motor_out[AP_MOTORS_MOT_4],
ext_gyro_gain : motors.ext_gyro_gain motors.motor_out[AP_MOTORS_MOT_7],
motors.motor_out[AP_MOTORS_MOT_8]}
#elif FRAME_CONFIG == TRI_FRAME #elif FRAME_CONFIG == TRI_FRAME
motor_out : {motors.motor_out[AP_MOTORS_MOT_1], motor_out : {motors.motor_out[AP_MOTORS_MOT_1],
motors.motor_out[AP_MOTORS_MOT_2], motors.motor_out[AP_MOTORS_MOT_2],
motors.motor_out[AP_MOTORS_MOT_4], motors.motor_out[AP_MOTORS_MOT_4],
motors.motor_out[g.rc_4.radio_out]} g.rc_4.radio_out}
#else // QUAD frame #else // QUAD frame
motor_out : {motors.motor_out[AP_MOTORS_MOT_1], motor_out : {motors.motor_out[AP_MOTORS_MOT_1],
motors.motor_out[AP_MOTORS_MOT_2], motors.motor_out[AP_MOTORS_MOT_2],
@ -307,7 +307,7 @@ static void Log_Write_Optflow()
struct log_Optflow pkt = { struct log_Optflow pkt = {
LOG_PACKET_HEADER_INIT(LOG_OPTFLOW_MSG), LOG_PACKET_HEADER_INIT(LOG_OPTFLOW_MSG),
dx : optflow.dx, dx : optflow.dx,
dy : optflow.dx, dy : optflow.dy,
surface_quality : optflow.surface_quality, surface_quality : optflow.surface_quality,
x_cm : (int16_t) optflow.x_cm, x_cm : (int16_t) optflow.x_cm,
y_cm : (int16_t) optflow.y_cm, y_cm : (int16_t) optflow.y_cm,
@ -339,7 +339,7 @@ struct PACKED log_Nav_Tuning {
// Write an Nav Tuning packet // Write an Nav Tuning packet
static void Log_Write_Nav_Tuning() static void Log_Write_Nav_Tuning()
{ {
Vector3f velocity = inertial_nav.get_velocity(); const Vector3f &velocity = inertial_nav.get_velocity();
struct log_Nav_Tuning pkt = { struct log_Nav_Tuning pkt = {
LOG_PACKET_HEADER_INIT(LOG_NAV_TUNING_MSG), LOG_PACKET_HEADER_INIT(LOG_NAV_TUNING_MSG),
@ -427,12 +427,13 @@ struct PACKED log_Performance {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint8_t renorm_count; uint8_t renorm_count;
uint8_t renorm_blowup; uint8_t renorm_blowup;
uint8_t gps_fix_count;
uint16_t num_long_running; uint16_t num_long_running;
uint16_t num_loops; uint16_t num_loops;
uint32_t max_time; uint32_t max_time;
int16_t pm_test; int16_t pm_test;
uint8_t i2c_lockup_count; uint8_t i2c_lockup_count;
uint16_t ins_error_count;
uint8_t inav_error_count;
}; };
// Write a performance monitoring packet // Write a performance monitoring packet
@ -442,12 +443,13 @@ static void Log_Write_Performance()
LOG_PACKET_HEADER_INIT(LOG_PERFORMANCE_MSG), LOG_PACKET_HEADER_INIT(LOG_PERFORMANCE_MSG),
renorm_count : ahrs.renorm_range_count, renorm_count : ahrs.renorm_range_count,
renorm_blowup : ahrs.renorm_blowup_count, renorm_blowup : ahrs.renorm_blowup_count,
gps_fix_count : gps_fix_count,
num_long_running : perf_info_get_num_long_running(), num_long_running : perf_info_get_num_long_running(),
num_loops : perf_info_get_num_loops(), num_loops : perf_info_get_num_loops(),
max_time : perf_info_get_max_time(), max_time : perf_info_get_max_time(),
pm_test : pmTest1, pm_test : pmTest1,
i2c_lockup_count : hal.i2c->lockup_count() i2c_lockup_count : hal.i2c->lockup_count(),
ins_error_count : ins.error_count(),
inav_error_count : inertial_nav.error_count()
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
@ -525,7 +527,7 @@ struct PACKED log_INAV {
// Write an INAV packet // Write an INAV packet
static void Log_Write_INAV() static void Log_Write_INAV()
{ {
Vector3f accel_corr = inertial_nav.accel_correction_ef; const Vector3f &accel_corr = inertial_nav.accel_correction_ef;
struct log_INAV pkt = { struct log_INAV pkt = {
LOG_PACKET_HEADER_INIT(LOG_INAV_MSG), LOG_PACKET_HEADER_INIT(LOG_INAV_MSG),
@ -715,6 +717,7 @@ static void Log_Write_PID(uint8_t pid_id, int32_t error, int32_t p, int32_t i, i
struct PACKED log_Camera { struct PACKED log_Camera {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t gps_time; uint32_t gps_time;
uint16_t gps_week;
int32_t latitude; int32_t latitude;
int32_t longitude; int32_t longitude;
int32_t altitude; int32_t altitude;
@ -729,7 +732,8 @@ static void Log_Write_Camera()
#if CAMERA == ENABLED #if CAMERA == ENABLED
struct log_Camera pkt = { struct log_Camera pkt = {
LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG), LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG),
gps_time : g_gps->time, gps_time : g_gps->time_week_ms,
gps_week : g_gps->time_week,
latitude : current_loc.lat, latitude : current_loc.lat,
longitude : current_loc.lng, longitude : current_loc.lng,
altitude : current_loc.alt, altitude : current_loc.alt,
@ -767,7 +771,7 @@ static const struct LogStructure log_structure[] PROGMEM = {
"ATDE", "cf", "Angle,Rate" }, "ATDE", "cf", "Angle,Rate" },
#endif #endif
{ LOG_CURRENT_MSG, sizeof(log_Current), { LOG_CURRENT_MSG, sizeof(log_Current),
"CURR", "hIhhhf", "Thr,ThrInt,Volt,Curr,Vcc,CurrTot" }, "CURR", "hIhhhf", "ThrOut,ThrInt,Volt,Curr,Vcc,CurrTot" },
#if FRAME_CONFIG == OCTA_FRAME || FRAME_CONFIG == OCTA_QUAD_FRAME #if FRAME_CONFIG == OCTA_FRAME || FRAME_CONFIG == OCTA_QUAD_FRAME
{ LOG_MOTORS_MSG, sizeof(log_Motors), { LOG_MOTORS_MSG, sizeof(log_Motors),
@ -792,7 +796,7 @@ static const struct LogStructure log_structure[] PROGMEM = {
{ LOG_COMPASS_MSG, sizeof(log_Compass), { LOG_COMPASS_MSG, sizeof(log_Compass),
"MAG", "hhhhhhhhh", "MagX,MagY,MagZ,OfsX,OfsY,OfsZ,MOfsX,MOfsY,MOfsZ" }, "MAG", "hhhhhhhhh", "MagX,MagY,MagZ,OfsX,OfsY,OfsZ,MOfsX,MOfsY,MOfsZ" },
{ LOG_PERFORMANCE_MSG, sizeof(log_Performance), { LOG_PERFORMANCE_MSG, sizeof(log_Performance),
"PM", "BBBHHIhB", "RenCnt,RenBlw,FixCnt,NLon,NLoop,MaxT,PMT,I2CErr" }, "PM", "BBHHIhBHB", "RenCnt,RenBlw,NLon,NLoop,MaxT,PMT,I2CErr,INSErr,INAVErr" },
{ LOG_CMD_MSG, sizeof(log_Cmd), { LOG_CMD_MSG, sizeof(log_Cmd),
"CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" }, "CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" },
{ LOG_ATTITUDE_MSG, sizeof(log_Attitude), { LOG_ATTITUDE_MSG, sizeof(log_Attitude),
@ -818,7 +822,7 @@ static const struct LogStructure log_structure[] PROGMEM = {
{ LOG_PID_MSG, sizeof(log_PID), { LOG_PID_MSG, sizeof(log_PID),
"PID", "Biiiiif", "Id,Error,P,I,D,Out,Gain" }, "PID", "Biiiiif", "Id,Error,P,I,D,Out,Gain" },
{ LOG_CAMERA_MSG, sizeof(log_Camera), { LOG_CAMERA_MSG, sizeof(log_Camera),
"CAM", "ILLeccC", "GPSTime,Lat,Lng,Alt,Roll,Pitch,Yaw" }, "CAM", "IHLLeccC", "GPSTime,GPSWeek,Lat,Lng,Alt,Roll,Pitch,Yaw" },
{ LOG_ERROR_MSG, sizeof(log_Error), { LOG_ERROR_MSG, sizeof(log_Error),
"ERR", "BB", "Subsys,ECode" }, "ERR", "BB", "Subsys,ECode" },
}; };
@ -830,7 +834,7 @@ static void Log_Read(uint16_t log_num, uint16_t start_page, uint16_t end_page)
cliSerial->printf_P(PSTR((AIRFRAME_NAME))); cliSerial->printf_P(PSTR((AIRFRAME_NAME)));
#endif #endif
cliSerial->printf_P(PSTR("\n" THISFIRMWARE cliSerial->printf_P(PSTR("\n" FIRMWARE_STRING
"\nFree RAM: %u\n"), "\nFree RAM: %u\n"),
(unsigned) memcheck_available_memory()); (unsigned) memcheck_available_memory());
@ -849,6 +853,10 @@ static void start_logging()
if (g.log_bitmask != 0 && !ap.logging_started) { if (g.log_bitmask != 0 && !ap.logging_started) {
ap.logging_started = true; ap.logging_started = true;
DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure); DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure);
DataFlash.Log_Write_Message_P(PSTR(FIRMWARE_STRING));
// log the flight mode
Log_Write_Mode(control_mode);
} }
} }

View File

@ -73,11 +73,7 @@ public:
k_param_log_last_filenumber, // *** Deprecated - remove k_param_log_last_filenumber, // *** Deprecated - remove
// with next eeprom number // with next eeprom number
// change // change
k_param_toy_yaw_rate, // THOR The memory k_param_toy_yaw_rate, // deprecated - remove
// location for the
// Yaw Rate 1 = fast,
// 2 = med, 3 = slow
k_param_crosstrack_min_distance, // deprecated - remove with next eeprom number change k_param_crosstrack_min_distance, // deprecated - remove with next eeprom number change
k_param_rssi_pin, k_param_rssi_pin,
k_param_throttle_accel_enabled, // deprecated - remove k_param_throttle_accel_enabled, // deprecated - remove
@ -92,7 +88,8 @@ public:
k_param_angle_max, k_param_angle_max,
k_param_gps_hdop_good, k_param_gps_hdop_good,
k_param_battery, k_param_battery,
k_param_fs_batt_mah, // 37 k_param_fs_batt_mah,
k_param_angle_rate_max, // 38
// 65: AP_Limits Library // 65: AP_Limits Library
k_param_limits = 65, // deprecated - remove k_param_limits = 65, // deprecated - remove
@ -102,6 +99,14 @@ public:
k_param_fence, k_param_fence,
k_param_gps_glitch, // 70 k_param_gps_glitch, // 70
//
// 75: Singlecopter
//
k_param_single_servo_1 = 75,
k_param_single_servo_2,
k_param_single_servo_3,
k_param_single_servo_4, // 78
// //
// 80: Heli // 80: Heli
// //
@ -112,6 +117,8 @@ public:
k_param_heli_pitch_ff, k_param_heli_pitch_ff,
k_param_heli_roll_ff, k_param_heli_roll_ff,
k_param_heli_yaw_ff, k_param_heli_yaw_ff,
k_param_heli_stab_col_min,
k_param_heli_stab_col_max, // 88
// //
// 90: Motors // 90: Motors
@ -127,11 +134,13 @@ public:
// 110: Telemetry control // 110: Telemetry control
// //
k_param_gcs0 = 110, k_param_gcs0 = 110,
k_param_gcs3, k_param_gcs1,
k_param_sysid_this_mav, k_param_sysid_this_mav,
k_param_sysid_my_gcs, k_param_sysid_my_gcs,
k_param_serial3_baud, k_param_serial1_baud,
k_param_telem_delay, k_param_telem_delay,
k_param_gcs2,
k_param_serial2_baud,
// //
// 140: Sensor parameters // 140: Sensor parameters
@ -274,7 +283,10 @@ public:
// //
AP_Int16 sysid_this_mav; AP_Int16 sysid_this_mav;
AP_Int16 sysid_my_gcs; AP_Int16 sysid_my_gcs;
AP_Int8 serial3_baud; AP_Int8 serial1_baud;
#if MAVLINK_COMM_NUM_BUFFERS > 2
AP_Int8 serial2_baud;
#endif
AP_Int8 telem_delay; AP_Int8 telem_delay;
AP_Int16 rtl_altitude; AP_Int16 rtl_altitude;
@ -302,6 +314,7 @@ public:
AP_Int8 rssi_pin; AP_Int8 rssi_pin;
AP_Int8 wp_yaw_behavior; // controls how the autopilot controls yaw during missions AP_Int8 wp_yaw_behavior; // controls how the autopilot controls yaw during missions
AP_Int16 angle_max; // maximum lean angle of the copter in centi-degrees AP_Int16 angle_max; // maximum lean angle of the copter in centi-degrees
AP_Int32 angle_rate_max; // maximum rotation rate in roll/pitch axis requested by angle controller used in stabilize, loiter, rtl, auto flight modes
// Waypoints // Waypoints
// //
@ -336,12 +349,6 @@ public:
// Misc // Misc
// //
AP_Int16 log_bitmask; AP_Int16 log_bitmask;
AP_Int8 toy_yaw_rate; // THOR The
// Yaw Rate 1
// = fast, 2 =
// med, 3 =
// slow
AP_Int8 esc_calibrate; AP_Int8 esc_calibrate;
AP_Int8 radio_tuning; AP_Int8 radio_tuning;
AP_Int16 radio_tuning_high; AP_Int16 radio_tuning_high;
@ -357,6 +364,12 @@ public:
AP_Float heli_pitch_ff; // pitch rate feed-forward AP_Float heli_pitch_ff; // pitch rate feed-forward
AP_Float heli_roll_ff; // roll rate feed-forward AP_Float heli_roll_ff; // roll rate feed-forward
AP_Float heli_yaw_ff; // yaw rate feed-forward AP_Float heli_yaw_ff; // yaw rate feed-forward
AP_Int16 heli_stab_col_min; // min collective while pilot directly controls collective in stabilize mode
AP_Int16 heli_stab_col_max; // min collective while pilot directly controls collective in stabilize mode
#endif
#if FRAME_CONFIG == SINGLE_FRAME
// Single
RC_Channel single_servo_1, single_servo_2, single_servo_3, single_servo_4; // servos for four flaps
#endif #endif
// RC channels // RC channels
@ -368,11 +381,8 @@ public:
RC_Channel_aux rc_6; RC_Channel_aux rc_6;
RC_Channel_aux rc_7; RC_Channel_aux rc_7;
RC_Channel_aux rc_8; RC_Channel_aux rc_8;
#if MOUNT == ENABLED
RC_Channel_aux rc_10; RC_Channel_aux rc_10;
RC_Channel_aux rc_11; RC_Channel_aux rc_11;
#endif
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
RC_Channel_aux rc_9; RC_Channel_aux rc_9;
@ -417,6 +427,12 @@ public:
heli_servo_3 (CH_3), heli_servo_3 (CH_3),
heli_servo_4 (CH_4), heli_servo_4 (CH_4),
#endif #endif
#if FRAME_CONFIG == SINGLE_FRAME
single_servo_1 (CH_1),
single_servo_2 (CH_2),
single_servo_3 (CH_3),
single_servo_4 (CH_4),
#endif
rc_1 (CH_1), rc_1 (CH_1),
rc_2 (CH_2), rc_2 (CH_2),
@ -428,12 +444,11 @@ public:
rc_8 (CH_8), rc_8 (CH_8),
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
rc_9 (CH_9), rc_9 (CH_9),
#endif
rc_10 (CH_10), rc_10 (CH_10),
rc_11 (CH_11), rc_11 (CH_11),
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
rc_12 (CH_12), rc_12 (CH_12),
#elif MOUNT == ENABLED
rc_10 (CH_10),
rc_11 (CH_11),
#endif #endif
// PID controller initial P initial I initial D // PID controller initial P initial I initial D

View File

@ -22,6 +22,7 @@
#define GSCALAR(v, name, def) { g.v.vtype, name, Parameters::k_param_ ## v, &g.v, {def_value : def} } #define GSCALAR(v, name, def) { g.v.vtype, name, Parameters::k_param_ ## v, &g.v, {def_value : def} }
#define GGROUP(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &g.v, {group_info : class::var_info} } #define GGROUP(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &g.v, {group_info : class::var_info} }
#define GOBJECT(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &v, {group_info : class::var_info} } #define GOBJECT(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &v, {group_info : class::var_info} }
#define GOBJECTN(v, pname, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## pname, &v, {group_info : class::var_info} }
const AP_Param::Info var_info[] PROGMEM = { const AP_Param::Info var_info[] PROGMEM = {
// @Param: SYSID_SW_MREV // @Param: SYSID_SW_MREV
@ -48,12 +49,21 @@ const AP_Param::Info var_info[] PROGMEM = {
// @User: Advanced // @User: Advanced
GSCALAR(sysid_my_gcs, "SYSID_MYGCS", 255), GSCALAR(sysid_my_gcs, "SYSID_MYGCS", 255),
// @Param: SERIAL3_BAUD // @Param: SERIAL1_BAUD
// @DisplayName: Telemetry Baud Rate // @DisplayName: Telemetry Baud Rate
// @Description: The baud rate used on the telemetry port // @Description: The baud rate used on the first telemetry port
// @Values: 1:1200,2:2400,4:4800,9:9600,19:19200,38:38400,57:57600,111:111100,115:115200 // @Values: 1:1200,2:2400,4:4800,9:9600,19:19200,38:38400,57:57600,111:111100,115:115200
// @User: Standard // @User: Standard
GSCALAR(serial3_baud, "SERIAL3_BAUD", SERIAL3_BAUD/1000), GSCALAR(serial1_baud, "SERIAL1_BAUD", SERIAL1_BAUD/1000),
#if MAVLINK_COMM_NUM_BUFFERS > 2
// @Param: SERIAL2_BAUD
// @DisplayName: Telemetry Baud Rate
// @Description: The baud rate used on the seconds telemetry port
// @Values: 1:1200,2:2400,4:4800,9:9600,19:19200,38:38400,57:57600,111:111100,115:115200
// @User: Standard
GSCALAR(serial2_baud, "SERIAL2_BAUD", SERIAL2_BAUD/1000),
#endif
// @Param: TELEM_DELAY // @Param: TELEM_DELAY
// @DisplayName: Telemetry startup delay // @DisplayName: Telemetry startup delay
@ -98,14 +108,15 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: FS_BATT_ENABLE // @Param: FS_BATT_ENABLE
// @DisplayName: Battery Failsafe Enable // @DisplayName: Battery Failsafe Enable
// @Description: Controls whether failsafe will be invoked when battery voltage or current runs low // @Description: Controls whether failsafe will be invoked when battery voltage or current runs low
// @Values: 0:Disabled,1:Enabled // @Values: 0:Disabled,1:Land,2:RTL
// @User: Standard // @User: Standard
GSCALAR(failsafe_battery_enabled, "FS_BATT_ENABLE", FS_BATTERY), GSCALAR(failsafe_battery_enabled, "FS_BATT_ENABLE", FS_BATT_DISABLED),
// @Param: FS_BATT_VOLTAGE // @Param: FS_BATT_VOLTAGE
// @DisplayName: Failsafe battery voltage // @DisplayName: Failsafe battery voltage
// @Description: Battery voltage to trigger failsafe. Set to 0 to disable battery voltage failsafe. If the battery voltage drops below this voltage then the copter will RTL // @Description: Battery voltage to trigger failsafe. Set to 0 to disable battery voltage failsafe. If the battery voltage drops below this voltage then the copter will RTL
// @Units: Volts // @Units: Volts
// @Increment: 0.1
// @User: Standard // @User: Standard
GSCALAR(fs_batt_voltage, "FS_BATT_VOLTAGE", FS_BATT_VOLTAGE_DEFAULT), GSCALAR(fs_batt_voltage, "FS_BATT_VOLTAGE", FS_BATT_VOLTAGE_DEFAULT),
@ -113,15 +124,16 @@ const AP_Param::Info var_info[] PROGMEM = {
// @DisplayName: Failsafe battery milliAmpHours // @DisplayName: Failsafe battery milliAmpHours
// @Description: Battery capacity remaining to trigger failsafe. Set to 0 to disable battery remaining failsafe. If the battery remaining drops below this level then the copter will RTL // @Description: Battery capacity remaining to trigger failsafe. Set to 0 to disable battery remaining failsafe. If the battery remaining drops below this level then the copter will RTL
// @Units: mAh // @Units: mAh
// @Increment: 50
// @User: Standard // @User: Standard
GSCALAR(fs_batt_mah, "FS_BATT_MAH", FS_BATT_MAH_DEFAULT), GSCALAR(fs_batt_mah, "FS_BATT_MAH", FS_BATT_MAH_DEFAULT),
// @Param: FS_GPS_ENABLE // @Param: FS_GPS_ENABLE
// @DisplayName: GPS Failsafe Enable // @DisplayName: GPS Failsafe Enable
// @Description: Controls whether failsafe will be invoked when gps signal is lost // @Description: Controls what action will be taken if GPS signal is lost for at least 5 seconds
// @Values: 0:Disabled,1:Enabled // @Values: 0:Disabled,1:Land,2:AltHold,3:Land even from Stabilize
// @User: Standard // @User: Standard
GSCALAR(failsafe_gps_enabled, "FS_GPS_ENABLE", FS_GPS), GSCALAR(failsafe_gps_enabled, "FS_GPS_ENABLE", FS_GPS_LAND),
// @Param: FS_GCS_ENABLE // @Param: FS_GCS_ENABLE
// @DisplayName: Ground Station Failsafe Enable // @DisplayName: Ground Station Failsafe Enable
@ -224,7 +236,7 @@ const AP_Param::Info var_info[] PROGMEM = {
// @DisplayName: Land speed // @DisplayName: Land speed
// @Description: The descent speed for the final stage of landing in cm/s // @Description: The descent speed for the final stage of landing in cm/s
// @Units: cm/s // @Units: cm/s
// @Range: 20 200 // @Range: 30 200
// @Increment: 10 // @Increment: 10
// @User: Standard // @User: Standard
GSCALAR(land_speed, "LAND_SPEED", LAND_SPEED), GSCALAR(land_speed, "LAND_SPEED", LAND_SPEED),
@ -292,42 +304,42 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: FLTMODE1 // @Param: FLTMODE1
// @DisplayName: Flight Mode 1 // @DisplayName: Flight Mode 1
// @Description: Flight mode when Channel 5 pwm is <= 1230 // @Description: Flight mode when Channel 5 pwm is <= 1230
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode1, "FLTMODE1", FLIGHT_MODE_1), GSCALAR(flight_mode1, "FLTMODE1", FLIGHT_MODE_1),
// @Param: FLTMODE2 // @Param: FLTMODE2
// @DisplayName: Flight Mode 2 // @DisplayName: Flight Mode 2
// @Description: Flight mode when Channel 5 pwm is >1230, <= 1360 // @Description: Flight mode when Channel 5 pwm is >1230, <= 1360
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode2, "FLTMODE2", FLIGHT_MODE_2), GSCALAR(flight_mode2, "FLTMODE2", FLIGHT_MODE_2),
// @Param: FLTMODE3 // @Param: FLTMODE3
// @DisplayName: Flight Mode 3 // @DisplayName: Flight Mode 3
// @Description: Flight mode when Channel 5 pwm is >1360, <= 1490 // @Description: Flight mode when Channel 5 pwm is >1360, <= 1490
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode3, "FLTMODE3", FLIGHT_MODE_3), GSCALAR(flight_mode3, "FLTMODE3", FLIGHT_MODE_3),
// @Param: FLTMODE4 // @Param: FLTMODE4
// @DisplayName: Flight Mode 4 // @DisplayName: Flight Mode 4
// @Description: Flight mode when Channel 5 pwm is >1490, <= 1620 // @Description: Flight mode when Channel 5 pwm is >1490, <= 1620
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode4, "FLTMODE4", FLIGHT_MODE_4), GSCALAR(flight_mode4, "FLTMODE4", FLIGHT_MODE_4),
// @Param: FLTMODE5 // @Param: FLTMODE5
// @DisplayName: Flight Mode 5 // @DisplayName: Flight Mode 5
// @Description: Flight mode when Channel 5 pwm is >1620, <= 1749 // @Description: Flight mode when Channel 5 pwm is >1620, <= 1749
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode5, "FLTMODE5", FLIGHT_MODE_5), GSCALAR(flight_mode5, "FLTMODE5", FLIGHT_MODE_5),
// @Param: FLTMODE6 // @Param: FLTMODE6
// @DisplayName: Flight Mode 6 // @DisplayName: Flight Mode 6
// @Description: Flight mode when Channel 5 pwm is >=1750 // @Description: Flight mode when Channel 5 pwm is >=1750
// @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:ToyA,12:ToyM,13:Sport // @Values: 0:Stabilize,1:Acro,2:AltHold,3:Auto,4:Guided,5:Loiter,6:RTL,7:Circle,8:Position,9:Land,10:OF_Loiter,11:Drift,13:Sport
// @User: Standard // @User: Standard
GSCALAR(flight_mode6, "FLTMODE6", FLIGHT_MODE_6), GSCALAR(flight_mode6, "FLTMODE6", FLIGHT_MODE_6),
@ -344,13 +356,6 @@ const AP_Param::Info var_info[] PROGMEM = {
// @User: Advanced // @User: Advanced
GSCALAR(log_bitmask, "LOG_BITMASK", DEFAULT_LOG_BITMASK), GSCALAR(log_bitmask, "LOG_BITMASK", DEFAULT_LOG_BITMASK),
// @Param: TOY_RATE
// @DisplayName: Toy Yaw Rate
// @Description: Controls yaw rate in Toy mode. Higher values will cause a slower yaw rate. Do not set to zero!
// @User: Advanced
// @Range: 1 10
GSCALAR(toy_yaw_rate, "TOY_RATE", 1),
// @Param: ESC // @Param: ESC
// @DisplayName: ESC Calibration // @DisplayName: ESC Calibration
// @Description: Controls whether ArduCopter will enter ESC calibration on the next restart. Do not adjust this parameter manually. // @Description: Controls whether ArduCopter will enter ESC calibration on the next restart. Do not adjust this parameter manually.
@ -402,10 +407,10 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: ARMING_CHECK // @Param: ARMING_CHECK
// @DisplayName: Arming check // @DisplayName: Arming check
// @Description: Allows enabling or disabling of pre-arming checks of receiver, accelerometer, barometer and compass // @Description: Allows enabling or disabling of pre-arming checks of receiver, accelerometer, barometer, compass and GPS
// @Values: 0:Disabled, 1:Enabled // @Values: 0:Disabled, 1:Enabled, -3:Skip Baro, -5:Skip Compass, -9:Skip GPS, -17:Skip INS, -33:Skip Parameters, -65:Skip RC, 127:Skip Voltage
// @User: Standard // @User: Standard
GSCALAR(arming_check_enabled, "ARMING_CHECK", 1), GSCALAR(arming_check_enabled, "ARMING_CHECK", ARMING_CHECK_ALL),
// @Param: ANGLE_MAX // @Param: ANGLE_MAX
// @DisplayName: Angle Max // @DisplayName: Angle Max
@ -414,6 +419,13 @@ const AP_Param::Info var_info[] PROGMEM = {
// @User: Advanced // @User: Advanced
GSCALAR(angle_max, "ANGLE_MAX", DEFAULT_ANGLE_MAX), GSCALAR(angle_max, "ANGLE_MAX", DEFAULT_ANGLE_MAX),
// @Param: ANGLE_RATE_MAX
// @DisplayName: Angle Rate max
// @Description: maximum rotation rate in roll/pitch axis requested by angle controller used in stabilize, loiter, rtl, auto flight modes
// @Range 90000 250000
// @User: Advanced
GSCALAR(angle_rate_max, "ANGLE_RATE_MAX", ANGLE_RATE_MAX),
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
// @Group: HS1_ // @Group: HS1_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp // @Path: ../libraries/RC_Channel/RC_Channel.cpp
@ -432,6 +444,7 @@ const AP_Param::Info var_info[] PROGMEM = {
// @DisplayName: Rate Pitch Feed Forward // @DisplayName: Rate Pitch Feed Forward
// @Description: Rate Pitch Feed Forward (for TradHeli Only) // @Description: Rate Pitch Feed Forward (for TradHeli Only)
// @Range: 0 10 // @Range: 0 10
// @Increment: 0.01
// @User: Standard // @User: Standard
GSCALAR(heli_pitch_ff, "RATE_PIT_FF", HELI_PITCH_FF), GSCALAR(heli_pitch_ff, "RATE_PIT_FF", HELI_PITCH_FF),
@ -439,6 +452,7 @@ const AP_Param::Info var_info[] PROGMEM = {
// @DisplayName: Rate Roll Feed Forward // @DisplayName: Rate Roll Feed Forward
// @Description: Rate Roll Feed Forward (for TradHeli Only) // @Description: Rate Roll Feed Forward (for TradHeli Only)
// @Range: 0 10 // @Range: 0 10
// @Increment: 0.01
// @User: Standard // @User: Standard
GSCALAR(heli_roll_ff, "RATE_RLL_FF", HELI_ROLL_FF), GSCALAR(heli_roll_ff, "RATE_RLL_FF", HELI_ROLL_FF),
@ -446,10 +460,45 @@ const AP_Param::Info var_info[] PROGMEM = {
// @DisplayName: Rate Yaw Feed Forward // @DisplayName: Rate Yaw Feed Forward
// @Description: Rate Yaw Feed Forward (for TradHeli Only) // @Description: Rate Yaw Feed Forward (for TradHeli Only)
// @Range: 0 10 // @Range: 0 10
// @Increment: 0.01
// @User: Standard // @User: Standard
GSCALAR(heli_yaw_ff, "RATE_YAW_FF", HELI_YAW_FF), GSCALAR(heli_yaw_ff, "RATE_YAW_FF", HELI_YAW_FF),
// @Param: H_STAB_COL_MIN
// @DisplayName: Heli Stabilize Throttle Collective Minimum
// @Description: Helicopter's minimum collective position while pilot directly controls collective in stabilize mode
// @Range: 0 500
// @Units: pwm
// @Increment: 1
// @User: Standard
GSCALAR(heli_stab_col_min, "H_STAB_COL_MIN", HELI_STAB_COLLECTIVE_MIN_DEFAULT),
// @Param: H_STAB_COL_MAX
// @DisplayName: Stabilize Throttle Maximum
// @Description: Helicopter's maximum collective position while pilot directly controls collective in stabilize mode
// @Range: 500 1000
// @Units: pwm
// @Increment: 1
// @User: Standard
GSCALAR(heli_stab_col_max, "H_STAB_COL_MAX", HELI_STAB_COLLECTIVE_MAX_DEFAULT),
#endif #endif
#if FRAME_CONFIG == SINGLE_FRAME
// @Group: SS1_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_1, "SS1_", RC_Channel),
// @Group: SS2_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_2, "SS2_", RC_Channel),
// @Group: SS3_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_3, "SS3_", RC_Channel),
// @Group: SS4_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_4, "SS4_", RC_Channel),
#endif
// RC channel // RC channel
//----------- //-----------
// @Group: RC1_ // @Group: RC1_
@ -477,20 +526,20 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp // @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_8, "RC8_", RC_Channel_aux), GGROUP(rc_8, "RC8_", RC_Channel_aux),
#if MOUNT == ENABLED
// @Group: RC10_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_10, "RC10_", RC_Channel_aux),
// @Group: RC11_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_11, "RC11_", RC_Channel_aux),
#endif
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 #if CONFIG_HAL_BOARD == HAL_BOARD_PX4
// @Group: RC9_ // @Group: RC9_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp // @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_9, "RC9_", RC_Channel_aux), GGROUP(rc_9, "RC9_", RC_Channel_aux),
#endif
// @Group: RC10_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_10, "RC10_", RC_Channel_aux),
// @Group: RC11_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_11, "RC11_", RC_Channel_aux),
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
// @Group: RC12_ // @Group: RC12_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp // @Path: ../libraries/RC_Channel/RC_Channel.cpp,../libraries/RC_Channel/RC_Channel_aux.cpp
GGROUP(rc_12, "RC12_", RC_Channel_aux), GGROUP(rc_12, "RC12_", RC_Channel_aux),
@ -929,7 +978,6 @@ const AP_Param::Info var_info[] PROGMEM = {
// variables not in the g class which contain EEPROM saved variables // variables not in the g class which contain EEPROM saved variables
// variables not in the g class which contain EEPROM saved variables
#if CAMERA == ENABLED #if CAMERA == ENABLED
// @Group: CAM_ // @Group: CAM_
// @Path: ../libraries/AP_Camera/AP_Camera.cpp // @Path: ../libraries/AP_Camera/AP_Camera.cpp
@ -960,11 +1008,17 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Group: SR0_ // @Group: SR0_
// @Path: GCS_Mavlink.pde // @Path: GCS_Mavlink.pde
GOBJECT(gcs0, "SR0_", GCS_MAVLINK), GOBJECTN(gcs[0], gcs0, "SR0_", GCS_MAVLINK),
// @Group: SR3_ // @Group: SR1_
// @Path: GCS_Mavlink.pde // @Path: GCS_Mavlink.pde
GOBJECT(gcs3, "SR3_", GCS_MAVLINK), GOBJECTN(gcs[1], gcs1, "SR1_", GCS_MAVLINK),
#if MAVLINK_COMM_NUM_BUFFERS > 2
// @Group: SR2_
// @Path: GCS_Mavlink.pde
GOBJECTN(gcs[2], gcs2, "SR2_", GCS_MAVLINK),
#endif
// @Group: AHRS_ // @Group: AHRS_
// @Path: ../libraries/AP_AHRS/AP_AHRS.cpp // @Path: ../libraries/AP_AHRS/AP_AHRS.cpp
@ -1018,6 +1072,24 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Group: H_ // @Group: H_
// @Path: ../libraries/AP_Motors/AP_MotorsHeli.cpp // @Path: ../libraries/AP_Motors/AP_MotorsHeli.cpp
GOBJECT(motors, "H_", AP_MotorsHeli), GOBJECT(motors, "H_", AP_MotorsHeli),
#elif FRAME_CONFIG == SINGLE_FRAME
// @Group: SS1_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_1, "SS1_", RC_Channel),
// @Group: SS2_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_2, "SS2_", RC_Channel),
// @Group: SS3_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_3, "SS3_", RC_Channel),
// @Group: SS4_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GGROUP(single_servo_4, "SS4_", RC_Channel),
// @Group: (SingleCopter)MOT_
// @Path: ../libraries/AP_Motors/AP_MotorsSingle.cpp
GOBJECT(motors, "MOT_", AP_MotorsSingle),
#else #else
// @Group: MOT_ // @Group: MOT_
// @Path: ../libraries/AP_Motors/AP_Motors_Class.cpp // @Path: ../libraries/AP_Motors/AP_Motors_Class.cpp

View File

@ -1,5 +1,117 @@
ArduCopter Release Notes: ArduCopter Release Notes:
------------------------------------------------------------------ ------------------------------------------------------------------
ArduCopter 3.1.5 27-May-2014 / 3.1.5-rc2 20-May-2014
Changes from 3.1.5-rc1
1) Bug Fix to broken loiter (pixhawk only)
2) Workaround to read from FRAM in 128byte chunks to resolve a few users boot issues (Pixhawk only)
------------------------------------------------------------------
ArduCopter 3.1.5-rc1 14-May-2014
Changes from 3.1.4
1) Bug Fix to ignore roll and pitch inputs to loiter controller when in radio failsafe
2) Bug Fix to allow compassmot to work on Pixhawk
------------------------------------------------------------------
ArduCopter 3.1.4 8-May-2014 / 3.1.4-rc1 2-May-2014
Changes from 3.1.3
1) Bug Fix for Pixhawk/PX4 NuttX I2C memory corruption when errors are found on I2C bus
------------------------------------------------------------------
ArduCopter 3.1.3 7-Apr-2014
Changes from 3.1.2
1) Stability patch fix which could cause motors to go to min at full throttle and with large roll/pitch inputs
------------------------------------------------------------------
ArduCopter 3.1.2 13-Feb-2014 / ArduCopter 3.1.2-rc2 12-Feb-2014
Changes from 3.1.2-rc1
1) GPS Glitch detection disabled when connected via USB
2) RC_FEEL_RP param added for adjusting responsiveness to pilot roll/pitch input in Stabilize, Drift, AltHold modes
------------------------------------------------------------------
ArduCopter 3.1.2-rc1 30-Jan-2014
Changes from 3.1.1
1) Pixhawk baro bug fix to SPI communication which could cause large altitude estimate jumps at high temperatures
------------------------------------------------------------------
ArduCopter 3.1.1 26-Jan-2014 / ArduCopter 3.1.1-rc2 21-Jan-2014
Changes from 3.1.1-rc1
1) Pixhawk improvements (available for APM2 when AC3.2 is released):
a) Faster arming
b) AHRS_TRIM fix - reduces movement in loiter when yawing
c) AUX Out 5 & 6 turned into general purpose I/O pins
d) Three more relays added (relays are pins that can be set to 0V or 5V)
e) do-set-servo fix to allow servos to be controlled from ground station
f) Motorsync CLI test
g) PX4 parameters moved from SD card to eeprom
h) additional pre-arm checks for baro & inertial nav altitude and lean angle
------------------------------------------------------------------
ArduCopter 3.1.1-rc1 14-Jan-2014
Changes from 3.1
1) Pixhawk improvements:
a) Telemetry port 2 enabled (for MinimOSD)
b) SD card reliability improvements
c) parameters moved to FRAM
d) faster parameter loading via USB
e) Futaba SBUS receiver support
2) Bug fixes:
a) Loiter initialisation fix (Loiter would act like AltHold until flight mode switch changed position)
b) ROI commands were not returning Lat, Lon, Alt to mission planner when mission was loaded from APM
3) TradHeli only fixes:
a) Drift now uses same (reduced) collective range as stabilize mode
b) AutoTune disabled (for tradheli only)
c) Landing collective (smaller than normal collective) used whenever copter is not moving
------------------------------------------------------------------
ArduCopter 3.1 14-Dec-2013
Changes from 3.1-rc8
1) Pixhawk improvements:
a) switch to use MPU6k as main accel/gyro
b) auto loading of IO-board firmware on startup
2) RTL fixes:
a) initialise waypoint leash length (first RTL stop would be more aggressive than 2nd)
b) reduce projected stopping distance for higher speed stops
------------------------------------------------------------------
ArduCopter 3.1-rc8 9-Dec-2013
Changes from 3.1-rc7
1) add Y6 motor mapping with all top props CW, bottom pros CCW (set FRAME = 10)
2) Safety Changes:
a) ignore yaw input during radio failsafe (previously the copter could return home spinning if yaw was full over at time of failsafe)
b) Reduce GPSGLITCH_RADIUS to 2m (was 5m) to catch glitches faster
3) Bug fixes:
a) Optical flow SPI bus rates
b) TradHeli main rotor ramp up speed fix
------------------------------------------------------------------
ArduCopter 3.1-rc7 22-Nov-2013
Changes from 3.1-rc6
1) MOT_SPIN_ARMED default to 70
2) Smoother inertial nav response to missed GPS messages
3) Safety related changes
a) radio and battery failsafe disarm copter if landed in Loiter or AltHold (previously they would RTL)
b) Pre-Arm check failure warning output to ground station every 30 seconds until they pass
c) INS and inertial nav errors logged to dataflash's PM message
d) pre-arm check for ACRO_BAL_ROLL, ACRO_BAL_PITCH
------------------------------------------------------------------
ArduCopter 3.1-rc6 16-Nov-2013
Improvements over 3.1-rc5
1) Heli improvements:
a) support for direct drive tails (uses TAIL_TYPE and TAIL_SPEED parameters)
b) smooth main rotor ramp-up for those without external govenor (RSC_RAMP_TIME)
c) internal estimate of rotor speed configurable with RSC_RUNUP_TIME parameter to ensure rotor at top speed before starting missions
d) LAND_COL_MIN collective position used when landed (reduces chance copter will push too hard into the ground when landing or before starting missions)
e) reduced collective while in stabilize mode (STAB_COL_MIN, STAB_COL_MAX) for more precise throttle control
f) external gyro parameter range changed from 1000~2000 to 0~1000 (more consistent with other parameters)
g) dynamic flight detector switches on/off leaky-i term depending on copter speed
2) SingleCopter airframe support (contribution from Bill King)
3) Drift mode replaces TOY
4) MPU6k SPI bus speed decreased to 500khz after 4 errors
5) Safety related changes:
a) crash detector cuts motors if copter upside down for more than 2 seconds
b) INS (accel and gyro) health check in pre-arm checks
c) ARMING_CHECK allows turning on/off individual checks for baro, GPS, compass, parameters, board voltage, radio
d) detect Ublox GPS running at less than 5hz and resend configuration
e) GPSGlitch acceptable radius reduced to 5m (stricter detection of glitches)
f) range check roll, pitch input to ensure crazy radio values don't get through to stabilize controller
g) GPS failsafe options to trigger AltHold instead of LAND or to trigger LAND even if in flight mode that does not require GPS
h) Battery failsafe option to trigger RTL instead of LAND
i) MOT_SPIN_ARMED set to zero by default
6) Bug fixes:
a) missing throttle controller initialisation would mean Stabilize mode's throttle could be non-tilt-compensated
b) inertial nav baro and gps delay compensation fix (contribution from Neurocopter)
c) GPS failsafe was invoking LAND mode which still used GPS for horizontal control
------------------------------------------------------------------
ArduCopter 3.1-rc5 22-Oct-2013 ArduCopter 3.1-rc5 22-Oct-2013
Improvements over 3.1-rc4 Improvements over 3.1-rc4
1) Pixhawk USB reliability improvements 1) Pixhawk USB reliability improvements

View File

@ -35,7 +35,7 @@
#define AUTO_TUNE_RP_RATIO_FINAL 1.0f // I is set 1x P after testing #define AUTO_TUNE_RP_RATIO_FINAL 1.0f // I is set 1x P after testing
#define AUTO_TUNE_RD_MIN 0.004f // minimum Rate D value #define AUTO_TUNE_RD_MIN 0.004f // minimum Rate D value
#define AUTO_TUNE_RD_MAX 0.015f // maximum Rate D value #define AUTO_TUNE_RD_MAX 0.015f // maximum Rate D value
#define AUTO_TUNE_RP_MIN 0.02f // minimum Rate P value #define AUTO_TUNE_RP_MIN 0.01f // minimum Rate P value
#define AUTO_TUNE_RP_MAX 0.25f // maximum Rate P value #define AUTO_TUNE_RP_MAX 0.25f // maximum Rate P value
#define AUTO_TUNE_SP_MAX 15.0f // maximum Stab P value #define AUTO_TUNE_SP_MAX 15.0f // maximum Stab P value
#define AUTO_TUNE_SUCCESS_COUNT 4 // how many successful iterations we need to freeze at current gains #define AUTO_TUNE_SUCCESS_COUNT 4 // how many successful iterations we need to freeze at current gains
@ -279,7 +279,7 @@ void auto_tune_update_gcs(uint8_t message_id)
// Auto tuning roll-pitch controller // Auto tuning roll-pitch controller
static void static void
get_autotune_roll_pitch_controller(int32_t pilot_roll_angle, int32_t pilot_pitch_angle) get_autotune_roll_pitch_controller(int16_t pilot_roll_angle, int16_t pilot_pitch_angle, int16_t pilot_yaw_command)
{ {
int32_t target_roll_rate, target_pitch_rate; int32_t target_roll_rate, target_pitch_rate;
float rotation_rate; // rotation rate in radians/second float rotation_rate; // rotation rate in radians/second
@ -291,7 +291,7 @@ get_autotune_roll_pitch_controller(int32_t pilot_roll_angle, int32_t pilot_pitch
} }
// check for pilot override // check for pilot override
if (pilot_roll_angle != 0 || pilot_pitch_angle != 0 ) { if (pilot_roll_angle != 0 || pilot_pitch_angle != 0 || pilot_yaw_command != 0) {
if (!auto_tune_state.pilot_override) { if (!auto_tune_state.pilot_override) {
// restore pids to their original values // restore pids to their original values
auto_tune_restore_orig_gains(); auto_tune_restore_orig_gains();

View File

@ -178,7 +178,6 @@ static bool verify_nav_command()
break; break;
default: default:
//gcs_send_text_P(SEVERITY_HIGH,PSTR("<verify_must: default> No current Must commands"));
return false; return false;
break; break;
} }
@ -207,7 +206,6 @@ static bool verify_cond_command()
break; break;
default: default:
//gcs_send_text_P(SEVERITY_HIGH,PSTR("<verify_must: default> No current May commands"));
return false; return false;
break; break;
} }
@ -464,6 +462,7 @@ static void do_loiter_time()
static bool verify_takeoff() static bool verify_takeoff()
{ {
// have we reached our target altitude? // have we reached our target altitude?
set_takeoff_complete(wp_nav.reached_destination());
return wp_nav.reached_destination(); return wp_nav.reached_destination();
} }

View File

@ -4,6 +4,11 @@
//---------------------------------------- //----------------------------------------
static void change_command(uint8_t cmd_index) static void change_command(uint8_t cmd_index)
{ {
// check we are in AUTO mode
if (control_mode != AUTO) {
return;
}
// limit range // limit range
cmd_index = min(g.command_total - 1, cmd_index); cmd_index = min(g.command_total - 1, cmd_index);

View File

@ -99,26 +99,33 @@
#ifndef FRAME_ORIENTATION #ifndef FRAME_ORIENTATION
# define FRAME_ORIENTATION X_FRAME # define FRAME_ORIENTATION X_FRAME
#endif #endif
#ifndef TOY_EDF
# define TOY_EDF DISABLED
#endif
#ifndef TOY_MIXER
# define TOY_MIXER TOY_LINEAR_MIXER
#endif
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// TradHeli defaults // TradHeli defaults
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
# define RC_FAST_SPEED 125 # define RC_FAST_SPEED 125
# define WP_YAW_BEHAVIOR_DEFAULT YAW_LOOK_AT_HOME # define WP_YAW_BEHAVIOR_DEFAULT WP_YAW_BEHAVIOR_LOOK_AHEAD
# define RATE_INTEGRATOR_LEAK_RATE 0.02f # define RATE_INTEGRATOR_LEAK_RATE 0.02f
# define RATE_ROLL_D 0 # define RATE_ROLL_D 0
# define RATE_PITCH_D 0 # define RATE_PITCH_D 0
# define HELI_PITCH_FF 0 # define HELI_PITCH_FF 0
# define HELI_ROLL_FF 0 # define HELI_ROLL_FF 0
# define HELI_YAW_FF 0 # define HELI_YAW_FF 0
# define STABILIZE_THROTTLE THROTTLE_MANUAL # define STABILIZE_THR THROTTLE_MANUAL_HELI
# define DRIFT_THR THROTTLE_MANUAL_HELI
# define MPU6K_FILTER 10 # define MPU6K_FILTER 10
# define HELI_STAB_COLLECTIVE_MIN_DEFAULT 0
# define HELI_STAB_COLLECTIVE_MAX_DEFAULT 1000
# define THR_MIN_DEFAULT 0
# define AUTOTUNE DISABLED
# ifndef HELI_CC_COMP
#define HELI_CC_COMP DISABLED
#endif
# ifndef HELI_PIRO_COMP
#define HELI_PIRO_COMP DISABLED
#endif
#endif #endif
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -173,31 +180,19 @@
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 #if CONFIG_HAL_BOARD == HAL_BOARD_APM1
# define LED_ON HIGH # define LED_ON HIGH
# define LED_OFF LOW # define LED_OFF LOW
# define BATTERY_VOLT_PIN 0 // Battery voltage on A0
# define BATTERY_CURR_PIN 1 // Battery current on A1
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM2 #elif CONFIG_HAL_BOARD == HAL_BOARD_APM2
# define LED_ON LOW # define LED_ON LOW
# define LED_OFF HIGH # define LED_OFF HIGH
# define BATTERY_VOLT_PIN 1 // Battery voltage on A1
# define BATTERY_CURR_PIN 2 // Battery current on A2
#elif CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL #elif CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
# define LED_ON LOW # define LED_ON LOW
# define LED_OFF HIGH # define LED_OFF HIGH
# define BATTERY_VOLT_PIN 1 // Battery voltage on A1
# define BATTERY_CURR_PIN 2 // Battery current on A2
#elif CONFIG_HAL_BOARD == HAL_BOARD_PX4 #elif CONFIG_HAL_BOARD == HAL_BOARD_PX4
# define LED_ON LOW # define LED_ON LOW
# define LED_OFF HIGH # define LED_OFF HIGH
# define BATTERY_VOLT_PIN -1
# define BATTERY_CURR_PIN -1
#elif CONFIG_HAL_BOARD == HAL_BOARD_FLYMAPLE #elif CONFIG_HAL_BOARD == HAL_BOARD_FLYMAPLE
# define BATTERY_VOLT_PIN 20
# define BATTERY_CURR_PIN 19
# define LED_ON LOW # define LED_ON LOW
# define LED_OFF HIGH # define LED_OFF HIGH
#elif CONFIG_HAL_BOARD == HAL_BOARD_LINUX #elif CONFIG_HAL_BOARD == HAL_BOARD_LINUX
# define BATTERY_VOLT_PIN -1
# define BATTERY_CURR_PIN -1
# define LED_ON LOW # define LED_ON LOW
# define LED_OFF HIGH # define LED_OFF HIGH
#endif #endif
@ -286,7 +281,7 @@
#endif #endif
#ifndef SONAR_GAIN_DEFAULT #ifndef SONAR_GAIN_DEFAULT
# define SONAR_GAIN_DEFAULT 2.0 // gain for controlling how quickly sonar range adjusts target altitude (lower means slower reaction) # define SONAR_GAIN_DEFAULT 0.8 // gain for controlling how quickly sonar range adjusts target altitude (lower means slower reaction)
#endif #endif
#ifndef THR_SURFACE_TRACKING_VELZ_MAX #ifndef THR_SURFACE_TRACKING_VELZ_MAX
@ -298,7 +293,7 @@
// //
#ifndef CH7_OPTION #ifndef CH7_OPTION
# define CH7_OPTION AUX_SWITCH_SAVE_WP # define CH7_OPTION AUX_SWITCH_DO_NOTHING
#endif #endif
#ifndef CH8_OPTION #ifndef CH8_OPTION
@ -341,8 +336,11 @@
#ifndef SERIAL0_BAUD #ifndef SERIAL0_BAUD
# define SERIAL0_BAUD 115200 # define SERIAL0_BAUD 115200
#endif #endif
#ifndef SERIAL3_BAUD #ifndef SERIAL1_BAUD
# define SERIAL3_BAUD 57600 # define SERIAL1_BAUD 57600
#endif
#ifndef SERIAL2_BAUD
# define SERIAL2_BAUD 57600
#endif #endif
@ -365,15 +363,7 @@
# define BOARD_VOLTAGE_MAX 5800 // max board voltage in milli volts for pre-arm checks # define BOARD_VOLTAGE_MAX 5800 // max board voltage in milli volts for pre-arm checks
#endif #endif
// Battery failsafe
#ifndef FS_BATTERY
# define FS_BATTERY DISABLED
#endif
// GPS failsafe // GPS failsafe
#ifndef FS_GPS
# define FS_GPS ENABLED
#endif
#ifndef FAILSAFE_GPS_TIMEOUT_MS #ifndef FAILSAFE_GPS_TIMEOUT_MS
# define FAILSAFE_GPS_TIMEOUT_MS 5000 // gps failsafe triggers after 5 seconds with no GPS # define FAILSAFE_GPS_TIMEOUT_MS 5000 // gps failsafe triggers after 5 seconds with no GPS
#endif #endif
@ -415,10 +405,21 @@
#endif #endif
#endif #endif
// max compass offset length (i.e. sqrt(offs_x^2+offs_y^2+offs_Z^2))
#ifndef CONFIG_ARCH_BOARD_PX4FMU_V1
#ifndef COMPASS_OFFSETS_MAX
# define COMPASS_OFFSETS_MAX 600 // PX4 onboard compass has high offsets
#endif
#else // APM1, APM2, SITL, FLYMAPLE, etc
#ifndef COMPASS_OFFSETS_MAX
# define COMPASS_OFFSETS_MAX 500
#endif
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// OPTICAL_FLOW // OPTICAL_FLOW
#ifndef OPTFLOW // sets global enabled/disabled flag for optflow (as seen in CLI) #ifndef OPTFLOW // sets global enabled/disabled flag for optflow (as seen in CLI)
# define OPTFLOW DISABLED # define OPTFLOW ENABLED
#endif #endif
#ifndef OPTFLOW_ORIENTATION #ifndef OPTFLOW_ORIENTATION
# define OPTFLOW_ORIENTATION AP_OPTICALFLOW_ADNS3080_PINS_FORWARD # define OPTFLOW_ORIENTATION AP_OPTICALFLOW_ADNS3080_PINS_FORWARD
@ -497,12 +498,6 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Throttle Failsafe // Throttle Failsafe
// //
// possible values for FS_THR parameter
#define FS_THR_DISABLED 0
#define FS_THR_ENABLED_ALWAYS_RTL 1
#define FS_THR_ENABLED_CONTINUE_MISSION 2
#define FS_THR_ENABLED_ALWAYS_LAND 3
#ifndef FS_THR_VALUE_DEFAULT #ifndef FS_THR_VALUE_DEFAULT
# define FS_THR_VALUE_DEFAULT 975 # define FS_THR_VALUE_DEFAULT 975
#endif #endif
@ -517,20 +512,6 @@
# define LAND_DETECTOR_TRIGGER 50 // number of 50hz iterations with near zero climb rate and low throttle that triggers landing complete. # define LAND_DETECTOR_TRIGGER 50 // number of 50hz iterations with near zero climb rate and low throttle that triggers landing complete.
#endif #endif
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// STARTUP BEHAVIOUR
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// GROUND_START_DELAY
//
#ifndef GROUND_START_DELAY
# define GROUND_START_DELAY 3
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// CAMERA TRIGGER AND CONTROL // CAMERA TRIGGER AND CONTROL
// //
@ -563,6 +544,17 @@
// Flight mode roll, pitch, yaw, throttle and navigation definitions // Flight mode roll, pitch, yaw, throttle and navigation definitions
// Stabilize Mode
#ifndef STABILIZE_YAW
# define STABILIZE_YAW YAW_HOLD
#endif
#ifndef STABILIZE_RP
# define STABILIZE_RP ROLL_PITCH_STABLE
#endif
#ifndef STABILIZE_THR
# define STABILIZE_THR THROTTLE_MANUAL_TILT_COMPENSATED
#endif
// Acro Mode // Acro Mode
#ifndef ACRO_YAW #ifndef ACRO_YAW
# define ACRO_YAW YAW_ACRO # define ACRO_YAW YAW_ACRO
@ -580,6 +572,11 @@
# define ACRO_LEVEL_MAX_ANGLE 3000 # define ACRO_LEVEL_MAX_ANGLE 3000
#endif #endif
// Drift Mode
#ifndef DRIFT_THR
# define DRIFT_THR THROTTLE_MANUAL_TILT_COMPENSATED
#endif
// Sport Mode // Sport Mode
#ifndef SPORT_YAW #ifndef SPORT_YAW
# define SPORT_YAW YAW_HOLD # define SPORT_YAW YAW_HOLD
@ -782,10 +779,6 @@
# define STABILIZE_PITCH_IMAX 0 # define STABILIZE_PITCH_IMAX 0
#endif #endif
#ifndef STABILIZE_RATE_LIMIT
# define STABILIZE_RATE_LIMIT 18000
#endif
#ifndef STABILIZE_YAW_P #ifndef STABILIZE_YAW_P
# define STABILIZE_YAW_P 4.5f // increase for more aggressive Yaw Hold, decrease if it's bouncy # define STABILIZE_YAW_P 4.5f // increase for more aggressive Yaw Hold, decrease if it's bouncy
#endif #endif
@ -810,6 +803,9 @@
#ifndef DEFAULT_ANGLE_MAX #ifndef DEFAULT_ANGLE_MAX
# define DEFAULT_ANGLE_MAX 4500 // ANGLE_MAX parameters default value # define DEFAULT_ANGLE_MAX 4500 // ANGLE_MAX parameters default value
#endif #endif
#ifndef ANGLE_RATE_MAX
# define ANGLE_RATE_MAX 18000 // default maximum rotation rate in roll/pitch axis requested by angle controller used in stabilize, loiter, rtl, auto flight modes
#endif
#ifndef RATE_ROLL_P #ifndef RATE_ROLL_P
# define RATE_ROLL_P 0.150f # define RATE_ROLL_P 0.150f
#endif #endif
@ -1086,4 +1082,14 @@
# define CLI_ENABLED ENABLED # define CLI_ENABLED ENABLED
#endif #endif
/*
build a firmware version string.
GIT_VERSION comes from Makefile builds
*/
#ifndef GIT_VERSION
#define FIRMWARE_STRING THISFIRMWARE
#else
#define FIRMWARE_STRING THISFIRMWARE " (" GIT_VERSION ")"
#endif
#endif // __ARDUCOPTER_CONFIG_H__ #endif // __ARDUCOPTER_CONFIG_H__

View File

@ -178,34 +178,50 @@ static void do_aux_switch_function(int8_t ch_function, uint8_t ch_flag)
break; break;
case AUX_SWITCH_SAVE_WP: case AUX_SWITCH_SAVE_WP:
// save waypoint when switch is switched off // save waypoint when switch is brought high
if (ch_flag == AUX_SWITCH_LOW) { if (ch_flag == AUX_SWITCH_HIGH) {
// if in auto mode, reset the mission // if in auto mode, reset the mission
if(control_mode == AUTO) { if(control_mode == AUTO) {
aux_switch_wp_index = 0; aux_switch_wp_index = 0;
g.command_total.set_and_save(1); g.command_total.set_and_save(1);
set_mode(RTL); // if by chance we are unable to switch to RTL we just stay in AUTO and hope the GPS failsafe will take-over set_mode(RTL); // if by chance we are unable to switch to RTL we just stay in AUTO and hope the GPS failsafe will take-over
Log_Write_Event(DATA_SAVEWP_CLEAR_MISSION_RTL);
return; return;
} }
// we're on the ground
if((g.rc_3.control_in == 0) && (aux_switch_wp_index == 0)){
// nothing to do
return;
}
// initialise new waypoint to current location
Location new_wp;
if(aux_switch_wp_index == 0) { if(aux_switch_wp_index == 0) {
// this is our first WP, let's save WP 1 as a takeoff // this is our first WP, let's save WP 1 as a takeoff
// increment index to WP index of 1 (home is stored at 0) // increment index to WP index of 1 (home is stored at 0)
aux_switch_wp_index = 1; aux_switch_wp_index = 1;
Location temp = home;
// set our location ID to 16, MAV_CMD_NAV_WAYPOINT // set our location ID to 16, MAV_CMD_NAV_WAYPOINT
temp.id = MAV_CMD_NAV_TAKEOFF; new_wp.id = MAV_CMD_NAV_TAKEOFF;
temp.alt = current_loc.alt; new_wp.options = 0;
new_wp.p1 = 0;
new_wp.lat = 0;
new_wp.lng = 0;
new_wp.alt = max(current_loc.alt,100);
// save command: // save command:
// we use the current altitude to be the target for takeoff. // we use the current altitude to be the target for takeoff.
// only altitude will matter to the AP mission script for takeoff. // only altitude will matter to the AP mission script for takeoff.
// If we are above the altitude, we will skip the command. // If we are above the altitude, we will skip the command.
set_cmd_with_index(temp, aux_switch_wp_index); set_cmd_with_index(new_wp, aux_switch_wp_index);
} }
// initialise new waypoint to current location
new_wp = current_loc;
// increment index // increment index
aux_switch_wp_index++; aux_switch_wp_index++;
@ -215,14 +231,17 @@ static void do_aux_switch_function(int8_t ch_function, uint8_t ch_flag)
if(g.rc_3.control_in > 0) { if(g.rc_3.control_in > 0) {
// set our location ID to 16, MAV_CMD_NAV_WAYPOINT // set our location ID to 16, MAV_CMD_NAV_WAYPOINT
current_loc.id = MAV_CMD_NAV_WAYPOINT; new_wp.id = MAV_CMD_NAV_WAYPOINT;
}else{ }else{
// set our location ID to 21, MAV_CMD_NAV_LAND // set our location ID to 21, MAV_CMD_NAV_LAND
current_loc.id = MAV_CMD_NAV_LAND; new_wp.id = MAV_CMD_NAV_LAND;
} }
// save command // save command
set_cmd_with_index(current_loc, aux_switch_wp_index); set_cmd_with_index(new_wp, aux_switch_wp_index);
// log event
Log_Write_Event(DATA_SAVEWP_ADD_WP);
// Cause the CopterLEDs to blink twice to indicate saved waypoint // Cause the CopterLEDs to blink twice to indicate saved waypoint
copter_leds_nav_blink = 10; copter_leds_nav_blink = 10;
@ -251,8 +270,10 @@ static void do_aux_switch_function(int8_t ch_function, uint8_t ch_flag)
// enable or disable the fence // enable or disable the fence
if (ch_flag == AUX_SWITCH_HIGH) { if (ch_flag == AUX_SWITCH_HIGH) {
fence.enable(true); fence.enable(true);
Log_Write_Event(DATA_FENCE_ENABLE);
}else{ }else{
fence.enable(false); fence.enable(false);
Log_Write_Event(DATA_FENCE_DISABLE);
} }
break; break;
#endif #endif
@ -268,12 +289,15 @@ static void do_aux_switch_function(int8_t ch_function, uint8_t ch_flag)
switch(ch_flag) { switch(ch_flag) {
case AUX_SWITCH_LOW: case AUX_SWITCH_LOW:
g.acro_trainer = ACRO_TRAINER_DISABLED; g.acro_trainer = ACRO_TRAINER_DISABLED;
Log_Write_Event(DATA_ACRO_TRAINER_DISABLED);
break; break;
case AUX_SWITCH_MIDDLE: case AUX_SWITCH_MIDDLE:
g.acro_trainer = ACRO_TRAINER_LEVELING; g.acro_trainer = ACRO_TRAINER_LEVELING;
Log_Write_Event(DATA_ACRO_TRAINER_LEVELING);
break; break;
case AUX_SWITCH_HIGH: case AUX_SWITCH_HIGH:
g.acro_trainer = ACRO_TRAINER_LIMITED; g.acro_trainer = ACRO_TRAINER_LIMITED;
Log_Write_Event(DATA_ACRO_TRAINER_LIMITED);
break; break;
} }
break; break;
@ -337,6 +361,7 @@ static void save_trim()
float roll_trim = ToRad((float)g.rc_1.control_in/100.0f); float roll_trim = ToRad((float)g.rc_1.control_in/100.0f);
float pitch_trim = ToRad((float)g.rc_2.control_in/100.0f); float pitch_trim = ToRad((float)g.rc_2.control_in/100.0f);
ahrs.add_trim(roll_trim, pitch_trim); ahrs.add_trim(roll_trim, pitch_trim);
Log_Write_Event(DATA_SAVE_TRIM);
} }
// auto_trim - slightly adjusts the ahrs.roll_trim and ahrs.pitch_trim towards the current stick positions // auto_trim - slightly adjusts the ahrs.roll_trim and ahrs.pitch_trim towards the current stick positions

View File

@ -0,0 +1,61 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
// Code to detect a crash main ArduCopter code
#ifndef CRASH_CHECK_ITERATIONS_MAX
# define CRASH_CHECK_ITERATIONS_MAX 20 // 2 second (ie. 10 iterations at 10hz) inverted indicates a crash
#endif
#ifndef CRASH_CHECK_ANGLE_DEVIATION_CD
# define CRASH_CHECK_ANGLE_DEVIATION_CD 2000 // 20 degrees beyond angle max is signal we are inverted
#endif
#ifndef CRASH_CHECK_ALT_CHANGE_LIMIT_CM
# define CRASH_CHECK_ALT_CHANGE_LIMIT_CM 50 // baro altitude must not change by more than 50cm
#endif
// crash_check - disarms motors if a crash has been detected
// crashes are detected by the vehicle being more than 20 degrees beyond it's angle limits continuously for more than 1 second
// should be called at 10hz
void crash_check()
{
static uint8_t inverted_count; // number of iterations we have been inverted
static int32_t baro_alt_prev;
// return immediately if motors are not armed or pilot's throttle is above zero
if (!motors.armed() || (g.rc_3.control_in != 0 && !failsafe.radio)) {
inverted_count = 0;
return;
}
// return immediately if we are not in an angle stabilize flight mode or we are flipping
if (control_mode == ACRO || ap.do_flip) {
inverted_count = 0;
return;
}
// check angles
int32_t lean_max = g.angle_max + CRASH_CHECK_ANGLE_DEVIATION_CD;
if (labs(ahrs.roll_sensor) > lean_max || labs(ahrs.pitch_sensor) > lean_max) {
inverted_count++;
// if we have just become inverted record the baro altitude
if (inverted_count == 1) {
baro_alt_prev = baro_alt;
// exit if baro altitude change indicates we are moving (probably falling)
}else if (labs(baro_alt - baro_alt_prev) > CRASH_CHECK_ALT_CHANGE_LIMIT_CM) {
inverted_count = 0;
return;
// check if inverted for 2 seconds
}else if (inverted_count >= CRASH_CHECK_ITERATIONS_MAX) {
// log an error in the dataflash
Log_Write_Error(ERROR_SUBSYSTEM_CRASH_CHECK, ERROR_CODE_CRASH_CHECK_CRASH);
// send message to gcs
gcs_send_text_P(SEVERITY_HIGH,PSTR("Crash: Disarming"));
// disarm motors
init_disarm_motors();
}
}else{
// we are not inverted so reset counter
inverted_count = 0;
}
}

View File

@ -23,14 +23,14 @@
#define YAW_LOOK_AT_HOME 5 // point towards home (no pilot input accepted) #define YAW_LOOK_AT_HOME 5 // point towards home (no pilot input accepted)
#define YAW_LOOK_AT_HEADING 6 // point towards a particular angle (not pilot input accepted) #define YAW_LOOK_AT_HEADING 6 // point towards a particular angle (not pilot input accepted)
#define YAW_LOOK_AHEAD 7 // WARNING! CODE IN DEVELOPMENT NOT PROVEN #define YAW_LOOK_AHEAD 7 // WARNING! CODE IN DEVELOPMENT NOT PROVEN
#define YAW_TOY 8 // THOR This is the Yaw mode #define YAW_DRIFT 8 //
#define YAW_RESETTOARMEDYAW 9 // point towards heading at time motors were armed #define YAW_RESETTOARMEDYAW 9 // point towards heading at time motors were armed
#define ROLL_PITCH_STABLE 0 // pilot input roll, pitch angles #define ROLL_PITCH_STABLE 0 // pilot input roll, pitch angles
#define ROLL_PITCH_ACRO 1 // pilot inputs roll, pitch rotation rates in body frame #define ROLL_PITCH_ACRO 1 // pilot inputs roll, pitch rotation rates in body frame
#define ROLL_PITCH_AUTO 2 // no pilot input. autopilot roll, pitch is sent to stabilize controller inputs #define ROLL_PITCH_AUTO 2 // no pilot input. autopilot roll, pitch is sent to stabilize controller inputs
#define ROLL_PITCH_STABLE_OF 3 // pilot inputs roll, pitch angles which are mixed with optical flow based position controller lean anbles #define ROLL_PITCH_STABLE_OF 3 // pilot inputs roll, pitch angles which are mixed with optical flow based position controller lean anbles
#define ROLL_PITCH_TOY 4 // THOR This is the Roll and Pitch mode #define ROLL_PITCH_DRIFT 4 //
#define ROLL_PITCH_LOITER 5 // pilot inputs the desired horizontal velocities #define ROLL_PITCH_LOITER 5 // pilot inputs the desired horizontal velocities
#define ROLL_PITCH_SPORT 6 // pilot inputs roll, pitch rotation rates in earth frame #define ROLL_PITCH_SPORT 6 // pilot inputs roll, pitch rotation rates in earth frame
#define ROLL_PITCH_AUTOTUNE 7 // description of new roll-pitch mode #define ROLL_PITCH_AUTOTUNE 7 // description of new roll-pitch mode
@ -40,6 +40,7 @@
#define THROTTLE_HOLD 2 // alt hold plus pilot input of climb rate #define THROTTLE_HOLD 2 // alt hold plus pilot input of climb rate
#define THROTTLE_AUTO 3 // auto pilot altitude controller with target altitude held in next_WP.alt #define THROTTLE_AUTO 3 // auto pilot altitude controller with target altitude held in next_WP.alt
#define THROTTLE_LAND 4 // landing throttle controller #define THROTTLE_LAND 4 // landing throttle controller
#define THROTTLE_MANUAL_HELI 5 // pilot manually controlled throttle for traditional helicopters
// sonar - for use with CONFIG_SONAR_SOURCE // sonar - for use with CONFIG_SONAR_SOURCE
@ -86,6 +87,7 @@
#define OCTA_FRAME 5 #define OCTA_FRAME 5
#define HELI_FRAME 6 #define HELI_FRAME 6
#define OCTA_QUAD_FRAME 7 #define OCTA_QUAD_FRAME 7
#define SINGLE_FRAME 8
#define PLUS_FRAME 0 #define PLUS_FRAME 0
#define X_FRAME 1 #define X_FRAME 1
@ -144,11 +146,11 @@
#define POSITION 8 // AUTO control #define POSITION 8 // AUTO control
#define LAND 9 // AUTO control #define LAND 9 // AUTO control
#define OF_LOITER 10 // Hold a single location using optical flow sensor #define OF_LOITER 10 // Hold a single location using optical flow sensor
#define TOY_A 11 // THOR Enum for Toy mode #define DRIFT 11 // DRIFT mode (Note: 12 is no longer used)
#define TOY_M 12 // THOR Enum for Toy mode
#define SPORT 13 // earth frame rate control #define SPORT 13 // earth frame rate control
#define NUM_MODES 14 #define NUM_MODES 14
// CH_6 Tuning // CH_6 Tuning
// ----------- // -----------
#define CH6_NONE 0 // no tuning performed #define CH6_NONE 0 // no tuning performed
@ -208,11 +210,6 @@
#define WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL 2 // auto pilot will face next waypoint except when doing RTL at which time it will stay in it's last #define WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL 2 // auto pilot will face next waypoint except when doing RTL at which time it will stay in it's last
#define WP_YAW_BEHAVIOR_LOOK_AHEAD 3 // auto pilot will look ahead during missions and rtl (primarily meant for traditional helicotpers) #define WP_YAW_BEHAVIOR_LOOK_AHEAD 3 // auto pilot will look ahead during missions and rtl (primarily meant for traditional helicotpers)
// TOY mixing options
#define TOY_LOOKUP_TABLE 0
#define TOY_LINEAR_MIXER 1
#define TOY_EXTERNAL_MIXER 2
// Waypoint options // Waypoint options
#define MASK_OPTIONS_RELATIVE_ALT 1 #define MASK_OPTIONS_RELATIVE_ALT 1
@ -259,6 +256,7 @@ enum ap_message {
MSG_RAW_IMU2, MSG_RAW_IMU2,
MSG_RAW_IMU3, MSG_RAW_IMU3,
MSG_GPS_RAW, MSG_GPS_RAW,
MSG_SYSTEM_TIME,
MSG_SERVO_OUT, MSG_SERVO_OUT,
MSG_NEXT_WAYPOINT, MSG_NEXT_WAYPOINT,
MSG_NEXT_PARAM, MSG_NEXT_PARAM,
@ -345,6 +343,14 @@ enum ap_message {
#define DATA_AUTOTUNE_REACHED_LIMIT 35 #define DATA_AUTOTUNE_REACHED_LIMIT 35
#define DATA_AUTOTUNE_TESTING 36 #define DATA_AUTOTUNE_TESTING 36
#define DATA_AUTOTUNE_SAVEDGAINS 37 #define DATA_AUTOTUNE_SAVEDGAINS 37
#define DATA_SAVE_TRIM 38
#define DATA_SAVEWP_ADD_WP 39
#define DATA_SAVEWP_CLEAR_MISSION_RTL 40
#define DATA_FENCE_ENABLE 41
#define DATA_FENCE_DISABLE 42
#define DATA_ACRO_TRAINER_DISABLED 43
#define DATA_ACRO_TRAINER_LEVELING 44
#define DATA_ACRO_TRAINER_LIMITED 45
@ -444,6 +450,7 @@ enum ap_message {
#define ERROR_SUBSYSTEM_FAILSAFE_FENCE 9 #define ERROR_SUBSYSTEM_FAILSAFE_FENCE 9
#define ERROR_SUBSYSTEM_FLIGHT_MODE 10 #define ERROR_SUBSYSTEM_FLIGHT_MODE 10
#define ERROR_SUBSYSTEM_GPS 11 #define ERROR_SUBSYSTEM_GPS 11
#define ERROR_SUBSYSTEM_CRASH_CHECK 12
// general error codes // general error codes
#define ERROR_CODE_ERROR_RESOLVED 0 #define ERROR_CODE_ERROR_RESOLVED 0
#define ERROR_CODE_FAILED_TO_INITIALISE 1 #define ERROR_CODE_FAILED_TO_INITIALISE 1
@ -457,8 +464,36 @@ enum ap_message {
// subsystem specific error codes -- gps // subsystem specific error codes -- gps
#define ERROR_CODE_GPS_GLITCH 2 #define ERROR_CODE_GPS_GLITCH 2
// subsystem specific error codes -- main // subsystem specific error codes -- main
#define ERROR_CODE_INS_DELAY 1 #define ERROR_CODE_MAIN_INS_DELAY 1
// subsystem specific error codes -- crash checker
#define ERROR_CODE_CRASH_CHECK_CRASH 1
// Arming Check Enable/Disable bits
#define ARMING_CHECK_NONE 0x00
#define ARMING_CHECK_ALL 0x01
#define ARMING_CHECK_BARO 0x02
#define ARMING_CHECK_COMPASS 0x04
#define ARMING_CHECK_GPS 0x08
#define ARMING_CHECK_INS 0x10
#define ARMING_CHECK_PARAMETERS 0x20
#define ARMING_CHECK_RC 0x40
#define ARMING_CHECK_VOLTAGE 0x80
// Radio failsafe definitions (FS_THR parameter)
#define FS_THR_DISABLED 0
#define FS_THR_ENABLED_ALWAYS_RTL 1
#define FS_THR_ENABLED_CONTINUE_MISSION 2
#define FS_THR_ENABLED_ALWAYS_LAND 3
// Battery failsafe definitions (FS_BATT_ENABLE parameter)
#define FS_BATT_DISABLED 0 // battery failsafe disabled
#define FS_BATT_LAND 1 // switch to LAND mode on battery failsafe
#define FS_BATT_RTL 2 // switch to RTL mode on battery failsafe
// GPS Failsafe definitions (FS_GPS_ENABLE parameter)
#define FS_GPS_DISABLED 0 // GPS failsafe disabled
#define FS_GPS_LAND 1 // switch to LAND mode on GPS Failsafe
#define FS_GPS_ALTHOLD 2 // switch to ALTHOLD mode on GPS failsafe
#define FS_GPS_LAND_EVEN_STABILIZE 3 // switch to LAND mode on GPS failsafe even if in a manual flight mode like Stabilize
#endif // _DEFINES_H #endif // _DEFINES_H

52
ArduCopter/drift.pde Normal file
View File

@ -0,0 +1,52 @@
////////////////////////////////////////////////////////////////////////////////
// Drift Mode
////////////////////////////////////////////////////////////////////////////////
#define SPEEDGAIN 14.0
// The function call for managing the flight mode drift
static void
get_roll_pitch_drift()
{
}
static void
get_yaw_drift()
{
static float breaker = 0.0;
// convert pilot input to lean angles
// moved to Yaw since it is called before get_roll_pitch_drift();
get_pilot_desired_lean_angles(g.rc_1.control_in, g.rc_2.control_in, control_roll, control_pitch);
// Grab inertial velocity
Vector3f vel = inertial_nav.get_velocity();
// rotate roll, pitch input from north facing to vehicle's perspective
float roll_vel = vel.y * cos_yaw - vel.x * sin_yaw; // body roll vel
float pitch_vel = vel.y * sin_yaw + vel.x * cos_yaw; // body pitch vel
float pitch_vel2 = min(fabs(pitch_vel), 800);
// simple gain scheduling for yaw input
get_yaw_rate_stabilized_ef((float)(control_roll/2) * (1.0 - (pitch_vel2 / 2400.0)));
roll_vel = constrain_float(roll_vel, -322, 322);
pitch_vel = constrain_float(pitch_vel, -322, 322);
// always limit roll
get_stabilize_roll(roll_vel * -SPEEDGAIN);
if(control_pitch == 0){
// .14/ (.03 * 100) = 4.6 seconds till full breaking
breaker+= .03;
breaker = min(breaker, SPEEDGAIN);
// If we let go of sticks, bring us to a stop
get_stabilize_pitch(pitch_vel * breaker);
}else{
breaker = 0.0;
get_stabilize_pitch(control_pitch);
}
}

View File

@ -22,7 +22,7 @@ static void failsafe_radio_on_event()
}else if(g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_LAND) { }else if(g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_LAND) {
// if failsafe_throttle is 3 (i.e. FS_THR_ENABLED_ALWAYS_LAND) land immediately // if failsafe_throttle is 3 (i.e. FS_THR_ENABLED_ALWAYS_LAND) land immediately
set_mode(LAND); set_mode(LAND);
}else if(GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { }else if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }
@ -34,7 +34,7 @@ static void failsafe_radio_on_event()
case AUTO: case AUTO:
// failsafe_throttle is 1 do RTL, 2 means continue with the mission // failsafe_throttle is 1 do RTL, 2 means continue with the mission
if (g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_RTL) { if (g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_RTL) {
if(GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }
@ -48,16 +48,33 @@ static void failsafe_radio_on_event()
} }
// if failsafe_throttle is 2 (i.e. FS_THR_ENABLED_CONTINUE_MISSION) no need to do anything // if failsafe_throttle is 2 (i.e. FS_THR_ENABLED_CONTINUE_MISSION) no need to do anything
break; break;
case LOITER:
case ALT_HOLD:
// if landed with throttle at zero disarm, otherwise do the regular thing
if (g.rc_3.control_in == 0 && ap.land_complete) {
init_disarm_motors();
}else if(g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_LAND) {
// if failsafe_throttle is 3 (i.e. FS_THR_ENABLED_ALWAYS_LAND) land immediately
set_mode(LAND);
}else if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) {
set_mode(LAND);
}
}else{
// We have no GPS or are very close to home so we will land
set_mode(LAND);
}
break;
case LAND: case LAND:
// continue to land if battery failsafe is also active otherwise fall through to default handling // continue to land if battery failsafe is also active otherwise fall through to default handling
if (g.failsafe_battery_enabled && failsafe.battery) { if (g.failsafe_battery_enabled == FS_BATT_LAND && failsafe.battery) {
break; break;
} }
default: default:
if(g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_LAND) { if(g.failsafe_throttle == FS_THR_ENABLED_ALWAYS_LAND) {
// if failsafe_throttle is 3 (i.e. FS_THR_ENABLED_ALWAYS_LAND) land immediately // if failsafe_throttle is 3 (i.e. FS_THR_ENABLED_ALWAYS_LAND) land immediately
set_mode(LAND); set_mode(LAND);
}else if(GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { }else if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)){ if (!set_mode(RTL)){
set_mode(LAND); set_mode(LAND);
} }
@ -91,7 +108,7 @@ static void failsafe_battery_event(void)
} }
// failsafe check // failsafe check
if (g.failsafe_battery_enabled && motors.armed()) { if (g.failsafe_battery_enabled != FS_BATT_DISABLED && motors.armed()) {
switch(control_mode) { switch(control_mode) {
case STABILIZE: case STABILIZE:
case ACRO: case ACRO:
@ -100,22 +117,42 @@ static void failsafe_battery_event(void)
if (g.rc_3.control_in == 0) { if (g.rc_3.control_in == 0) {
init_disarm_motors(); init_disarm_motors();
}else{ }else{
set_mode(LAND); // set mode to RTL or LAND
} if (g.failsafe_battery_enabled == FS_BATT_RTL && home_distance > wp_nav.get_waypoint_radius()) {
break; if (!set_mode(RTL)) {
case AUTO: set_mode(LAND);
// set_mode to RTL or LAND }
if (GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { }else{
set_mode(LAND);
}
}
break;
case AUTO:
// set mode to RTL or LAND
if (home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }
}else{ }else{
// We have no GPS or are very close to home so we will land
set_mode(LAND); set_mode(LAND);
} }
break; break;
case LOITER:
case ALT_HOLD:
// if landed with throttle at zero disarm, otherwise fall through to default handling
if (g.rc_3.control_in == 0 && ap.land_complete) {
init_disarm_motors();
break;
}
default: default:
// set mode to RTL or LAND
if (g.failsafe_battery_enabled == FS_BATT_RTL && home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
}
}else{
set_mode(LAND);
}
break; break;
} }
} }
@ -137,8 +174,13 @@ static void failsafe_gps_check()
{ {
uint32_t last_gps_update_ms; uint32_t last_gps_update_ms;
// return immediately if gps failsafe is disabled // return immediately if gps failsafe is disabled or we have never had GPS lock
if( !g.failsafe_gps_enabled ) { if (g.failsafe_gps_enabled == FS_GPS_DISABLED || !ap.home_is_set) {
// if we have just disabled the gps failsafe, ensure the gps failsafe event is cleared
if (failsafe.gps) {
failsafe_gps_off_event();
set_failsafe_gps(false);
}
return; return;
} }
@ -166,16 +208,14 @@ static void failsafe_gps_check()
gcs_send_text_P(SEVERITY_LOW,PSTR("Lost GPS!")); gcs_send_text_P(SEVERITY_LOW,PSTR("Lost GPS!"));
Log_Write_Error(ERROR_SUBSYSTEM_FAILSAFE_GPS, ERROR_CODE_FAILSAFE_OCCURRED); Log_Write_Error(ERROR_SUBSYSTEM_FAILSAFE_GPS, ERROR_CODE_FAILSAFE_OCCURRED);
// take action based on flight mode // take action based on flight mode and FS_GPS_ENABLED parameter
if(mode_requires_GPS(control_mode)) if (mode_requires_GPS(control_mode) || g.failsafe_gps_enabled == FS_GPS_LAND_EVEN_STABILIZE) {
set_mode(LAND); if (g.failsafe_gps_enabled == FS_GPS_ALTHOLD && !failsafe.radio) {
set_mode(ALT_HOLD);
// land if circular fence is enabled }else{
#if AC_FENCE == ENABLED
if((fence.get_enabled_fences() & AC_FENCE_TYPE_CIRCLE) != 0) {
set_mode(LAND); set_mode(LAND);
} }
#endif }
} }
// failsafe_gps_off_event - actions to take when GPS contact is restored // failsafe_gps_off_event - actions to take when GPS contact is restored
@ -227,7 +267,7 @@ static void failsafe_gcs_check()
// if throttle is zero disarm motors // if throttle is zero disarm motors
if (g.rc_3.control_in == 0) { if (g.rc_3.control_in == 0) {
init_disarm_motors(); init_disarm_motors();
}else if(GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { }else if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }
@ -239,7 +279,7 @@ static void failsafe_gcs_check()
case AUTO: case AUTO:
// if g.failsafe_gcs is 1 do RTL, 2 means continue with the mission // if g.failsafe_gcs is 1 do RTL, 2 means continue with the mission
if (g.failsafe_gcs == FS_GCS_ENABLED_ALWAYS_RTL) { if (g.failsafe_gcs == FS_GCS_ENABLED_ALWAYS_RTL) {
if (GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { if (home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }
@ -251,7 +291,7 @@ static void failsafe_gcs_check()
// if failsafe_throttle is 2 (i.e. FS_THR_ENABLED_CONTINUE_MISSION) no need to do anything // if failsafe_throttle is 2 (i.e. FS_THR_ENABLED_CONTINUE_MISSION) no need to do anything
break; break;
default: default:
if(GPS_ok() && home_distance > wp_nav.get_waypoint_radius()) { if(home_distance > wp_nav.get_waypoint_radius()) {
if (!set_mode(RTL)) { if (!set_mode(RTL)) {
set_mode(LAND); set_mode(LAND);
} }

View File

@ -35,26 +35,16 @@ void fence_check()
if(manual_flight_mode(control_mode) && g.rc_3.control_in == 0 && !failsafe.radio && ((fence.get_breaches() & AC_FENCE_TYPE_ALT_MAX)== 0)){ if(manual_flight_mode(control_mode) && g.rc_3.control_in == 0 && !failsafe.radio && ((fence.get_breaches() & AC_FENCE_TYPE_ALT_MAX)== 0)){
init_disarm_motors(); init_disarm_motors();
}else{ }else{
// if we have a GPS
if (GPS_ok()) {
// if we are within 100m of the fence, RTL // if we are within 100m of the fence, RTL
if( fence.get_breach_distance(new_breaches) <= AC_FENCE_GIVE_UP_DISTANCE) { if (fence.get_breach_distance(new_breaches) <= AC_FENCE_GIVE_UP_DISTANCE) {
if(control_mode != RTL) { if (!set_mode(RTL)) {
set_mode(RTL); set_mode(LAND);
} }
}else{ }else{
// if more than 100m outside the fence just force a land // if more than 100m outside the fence just force a land
if(control_mode != LAND) {
set_mode(LAND); set_mode(LAND);
} }
} }
}else{
// we have no GPS so LAND
if(control_mode != LAND) {
set_mode(LAND);
}
}
}
} }
// log an error in the dataflash // log an error in the dataflash

View File

@ -35,7 +35,7 @@ void roll_flip()
if (roll < 4500) { if (roll < 4500) {
// Roll control // Roll control
roll_rate_target_bf = 40000 * flip_dir; roll_rate_target_bf = 40000 * flip_dir;
if(throttle_mode == THROTTLE_MANUAL || throttle_mode == THROTTLE_MANUAL_TILT_COMPENSATED){ if (throttle_mode_manual(throttle_mode)){
// increase throttle right before flip // increase throttle right before flip
set_throttle_out(g.rc_3.control_in + AAP_THR_INC, false); set_throttle_out(g.rc_3.control_in + AAP_THR_INC, false);
} }
@ -52,7 +52,7 @@ void roll_flip()
roll_rate_target_bf = 40000 * flip_dir; roll_rate_target_bf = 40000 * flip_dir;
#endif #endif
// decrease throttle while inverted // decrease throttle while inverted
if(throttle_mode == THROTTLE_MANUAL || throttle_mode == THROTTLE_MANUAL_TILT_COMPENSATED){ if (throttle_mode_manual(throttle_mode)){
set_throttle_out(g.rc_3.control_in - AAP_THR_DEC, false); set_throttle_out(g.rc_3.control_in - AAP_THR_DEC, false);
} }
}else{ }else{
@ -68,7 +68,7 @@ void roll_flip()
// It will be handled by normal flight control loops // It will be handled by normal flight control loops
// increase throttle to gain any lost alitude // increase throttle to gain any lost alitude
if(throttle_mode == THROTTLE_MANUAL || throttle_mode == THROTTLE_MANUAL_TILT_COMPENSATED){ if (throttle_mode_manual(throttle_mode)){
set_throttle_out(g.rc_3.control_in + AAP_THR_INC, false); set_throttle_out(g.rc_3.control_in + AAP_THR_INC, false);
} }
flip_timer++; flip_timer++;

347
ArduCopter/heli.pde Normal file
View File

@ -0,0 +1,347 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
// Traditional helicopter variables and functions
#if FRAME_CONFIG == HELI_FRAME
#ifndef HELI_DYNAMIC_FLIGHT_SPEED_MIN
#define HELI_DYNAMIC_FLIGHT_SPEED_MIN 500 // we are in "dynamic flight" when the speed is over 1m/s for 2 seconds
#endif
// counter to control dynamic flight profile
static int8_t heli_dynamic_flight_counter;
// Tradheli flags
static struct {
uint8_t dynamic_flight : 1; // 0 // true if we are moving at a significant speed (used to turn on/off leaky I terms)
} heli_flags;
#if HELI_CC_COMP == ENABLED
static LowPassFilterFloat rate_dynamics_filter; // Rate Dynamics filter
#endif
// heli_init - perform any special initialisation required for the tradheli
static void heli_init()
{
#if HELI_CC_COMP == ENABLED
rate_dynamics_filter.set_cutoff_frequency(0.01f, 4.0f);
#endif
}
// get_pilot_desired_collective - converts pilot input (from 0 ~ 1000) to a value that can be fed into the g.rc_3.servo_out function
static int16_t get_pilot_desired_collective(int16_t control_in)
{
// return immediately if reduce collective range for manual flight has not been configured
if (g.heli_stab_col_min == 0 && g.heli_stab_col_max == 1000) {
return control_in;
}
// scale pilot input to reduced collective range
float scalar = ((float)(g.heli_stab_col_max - g.heli_stab_col_min))/1000.0f;
int16_t collective_out = g.heli_stab_col_min + control_in * scalar;
collective_out = constrain_int16(collective_out, 0, 1000);
return collective_out;
}
// heli_check_dynamic_flight - updates the dynamic_flight flag based on our horizontal velocity
// should be called at 50hz
static void check_dynamic_flight(void)
{
if (!motors.armed() || throttle_mode == THROTTLE_LAND || !motors.motor_runup_complete()) {
heli_dynamic_flight_counter = 0;
heli_flags.dynamic_flight = false;
return;
}
bool moving = false;
// with GPS lock use inertial nav to determine if we are moving
if (GPS_ok()) {
// get horizontal velocity
float velocity = inertial_nav.get_velocity_xy();
moving = (velocity >= HELI_DYNAMIC_FLIGHT_SPEED_MIN);
}else{
// with no GPS lock base it on throttle and forward lean angle
moving = (g.rc_3.servo_out > 800 || ahrs.pitch_sensor < -1500);
}
if (moving) {
// if moving for 2 seconds, set the dynamic flight flag
if (!heli_flags.dynamic_flight) {
heli_dynamic_flight_counter++;
if (heli_dynamic_flight_counter >= 100) {
heli_flags.dynamic_flight = true;
heli_dynamic_flight_counter = 100;
}
}
}else{
// if not moving for 2 seconds, clear the dynamic flight flag
if (heli_flags.dynamic_flight) {
if (heli_dynamic_flight_counter > 0) {
heli_dynamic_flight_counter--;
}else{
heli_flags.dynamic_flight = false;
}
}
}
}
// heli_integrated_swash_controller - convert desired roll and pitch rate to roll and pitch swash angles
// should be called at 100hz
// output placed directly into g.rc_1.servo_out and g.rc_2.servo_out
static void heli_integrated_swash_controller(int32_t target_roll_rate, int32_t target_pitch_rate)
{
int32_t roll_p, roll_i, roll_d, roll_ff; // used to capture pid values for logging
int32_t pitch_p, pitch_i, pitch_d, pitch_ff;
int32_t current_roll_rate, current_pitch_rate; // this iteration's rate
int32_t roll_rate_error, pitch_rate_error; // simply target_rate - current_rate
int32_t roll_output, pitch_output; // output from pid controller
static bool roll_pid_saturated, pitch_pid_saturated; // tracker from last loop if the PID was saturated
current_roll_rate = (omega.x * DEGX100); // get current roll rate
current_pitch_rate = (omega.y * DEGX100); // get current pitch rate
roll_rate_error = target_roll_rate - current_roll_rate;
pitch_rate_error = target_pitch_rate - current_pitch_rate;
roll_p = g.pid_rate_roll.get_p(roll_rate_error);
pitch_p = g.pid_rate_pitch.get_p(pitch_rate_error);
if (roll_pid_saturated){
roll_i = g.pid_rate_roll.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
if (motors.has_flybar()) { // Mechanical Flybars get regular integral for rate auto trim
if (target_roll_rate > -50 && target_roll_rate < 50){ // Frozen at high rates
roll_i = g.pid_rate_roll.get_i(roll_rate_error, G_Dt);
} else {
roll_i = g.pid_rate_roll.get_integrator();
}
} else {
if (heli_flags.dynamic_flight){
roll_i = g.pid_rate_roll.get_i(roll_rate_error, G_Dt);
} else {
roll_i = g.pid_rate_roll.get_leaky_i(roll_rate_error, G_Dt, RATE_INTEGRATOR_LEAK_RATE);
}
}
}
if (pitch_pid_saturated){
pitch_i = g.pid_rate_pitch.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
if (motors.has_flybar()) { // Mechanical Flybars get regular integral for rate auto trim
if (target_pitch_rate > -50 && target_pitch_rate < 50){ // Frozen at high rates
pitch_i = g.pid_rate_pitch.get_i(pitch_rate_error, G_Dt);
} else {
pitch_i = g.pid_rate_pitch.get_integrator();
}
} else {
if (heli_flags.dynamic_flight){
pitch_i = g.pid_rate_pitch.get_i(pitch_rate_error, G_Dt);
} else {
pitch_i = g.pid_rate_pitch.get_leaky_i(pitch_rate_error, G_Dt, RATE_INTEGRATOR_LEAK_RATE);
}
}
}
roll_d = g.pid_rate_roll.get_d(target_roll_rate, G_Dt);
pitch_d = g.pid_rate_pitch.get_d(target_pitch_rate, G_Dt);
roll_ff = g.heli_roll_ff * target_roll_rate;
pitch_ff = g.heli_pitch_ff * target_pitch_rate;
roll_output = roll_p + roll_i + roll_d + roll_ff;
pitch_output = pitch_p + pitch_i + pitch_d + pitch_ff;
#if HELI_CC_COMP == ENABLED
// Do cross-coupling compensation for low rpm helis
// Credit: Jolyon Saunders
// Note: This is not widely tested at this time. Will not be used by default yet.
float cc_axis_ratio = 2.0f; // Ratio of compensation on pitch vs roll axes. Number >1 means pitch is affected more than roll
float cc_kp = 0.0002f; // Compensation p term. Setting this to zero gives h_phang only, while increasing it will increase the p term of correction
float cc_kd = 0.127f; // Compensation d term, scaled. This accounts for flexing of the blades, dampers etc. Originally was (motors.ext_gyro_gain * 0.0001)
float cc_angle, cc_total_output;
uint32_t cc_roll_d, cc_pitch_d, cc_sum_d;
int32_t cc_scaled_roll;
int32_t cc_roll_output; // Used to temporarily hold output while rotation is being calculated
int32_t cc_pitch_output; // Used to temporarily hold output while rotation is being calculated
static int32_t last_roll_output = 0;
static int32_t last_pitch_output = 0;
cc_scaled_roll = roll_output / cc_axis_ratio; // apply axis ratio to roll
cc_total_output = safe_sqrt(cc_scaled_roll * cc_scaled_roll + pitch_output * pitch_output) * cc_kp;
// find the delta component
cc_roll_d = (roll_output - last_roll_output) / cc_axis_ratio;
cc_pitch_d = pitch_output - last_pitch_output;
cc_sum_d = safe_sqrt(cc_roll_d * cc_roll_d + cc_pitch_d * cc_pitch_d);
// do the magic.
cc_angle = cc_kd * cc_sum_d * cc_total_output - cc_total_output * motors.get_phase_angle();
// smooth angle variations, apply constraints
cc_angle = rate_dynamics_filter.apply(cc_angle);
cc_angle = constrain_float(cc_angle, -90.0f, 0.0f);
cc_angle = radians(cc_angle);
// Make swash rate vector
Vector2f swashratevector;
swashratevector.x = cosf(cc_angle);
swashratevector.y = sinf(cc_angle);
swashratevector.normalize();
// rotate the output
cc_roll_output = roll_output;
cc_pitch_output = pitch_output;
roll_output = - (cc_pitch_output * swashratevector.y - cc_roll_output * swashratevector.x);
pitch_output = cc_pitch_output * swashratevector.x + cc_roll_output * swashratevector.y;
// make current outputs old, for next iteration
last_roll_output = cc_roll_output;
last_pitch_output = cc_pitch_output;
# endif // HELI_CC_COMP
#if HELI_PIRO_COMP == ENABLED
if (control_mode <= ACRO){
int32_t piro_roll_i, piro_pitch_i; // used to hold i term while doing prio comp
piro_roll_i = roll_i;
piro_pitch_i = pitch_i;
Vector2f yawratevector;
yawratevector.x = cos(-omega.z/100);
yawratevector.y = sin(-omega.z/100);
yawratevector.normalize();
roll_i = piro_roll_i * yawratevector.x - piro_pitch_i * yawratevector.y;
pitch_i = piro_pitch_i * yawratevector.x + piro_roll_i * yawratevector.y;
g.pid_rate_pitch.set_integrator(pitch_i);
g.pid_rate_roll.set_integrator(roll_i);
}
#endif //HELI_PIRO_COMP
if (labs(roll_output) > 4500){
roll_output = constrain_int32(roll_output, -4500, 4500); // constrain output
roll_pid_saturated = true; // freeze integrator next cycle
} else {
roll_pid_saturated = false; // unfreeze integrator
}
if (labs(pitch_output) > 4500){
pitch_output = constrain_int32(pitch_output, -4500, 4500); // constrain output
pitch_pid_saturated = true; // freeze integrator next cycle
} else {
pitch_pid_saturated = false; // unfreeze integrator
}
g.rc_1.servo_out = roll_output;
g.rc_2.servo_out = pitch_output;
}
static int16_t
get_heli_rate_yaw(int32_t target_rate)
{
int32_t p,i,d,ff; // used to capture pid values for logging
int32_t current_rate; // this iteration's rate
int32_t rate_error;
int32_t output;
static bool pid_saturated; // tracker from last loop if the PID was saturated
current_rate = (omega.z * DEGX100); // get current rate
// rate control
rate_error = target_rate - current_rate;
// separately calculate p, i, d values for logging
p = g.pid_rate_yaw.get_p(rate_error);
if (pid_saturated){
i = g.pid_rate_yaw.get_integrator(); // Locked Integrator due to PID saturation on previous cycle
} else {
if (motors.motor_runup_complete()){
i = g.pid_rate_yaw.get_i(rate_error, G_Dt);
} else {
i = g.pid_rate_yaw.get_leaky_i(rate_error, G_Dt, RATE_INTEGRATOR_LEAK_RATE); // If motor is not running use leaky I-term to avoid excessive build-up
}
}
d = g.pid_rate_yaw.get_d(rate_error, G_Dt);
ff = g.heli_yaw_ff*target_rate;
output = p + i + d + ff;
if (labs(output) > 4500){
output = constrain_int32(output, -4500, 4500); // constrain output
pid_saturated = true; // freeze integrator next cycle
} else {
pid_saturated = false; // unfreeze integrator
}
#if LOGGING_ENABLED == ENABLED
// log output if PID loggins is on and we are tuning the yaw
if( g.log_bitmask & MASK_LOG_PID && (g.radio_tuning == CH6_YAW_RATE_KP || g.radio_tuning == CH6_YAW_RATE_KD) ) {
pid_log_counter++;
if( pid_log_counter >= 10 ) { // (update rate / desired output rate) = (100hz / 10hz) = 10
pid_log_counter = 0;
Log_Write_PID(CH6_YAW_RATE_KP, rate_error, p, i, d, output, tuning_value);
}
}
#endif
return output; // output control
}
// heli_update_landing_swash - sets swash plate flag so higher minimum is used when landed or landing
// should be called soon after update_land_detector in main code
static void heli_update_landing_swash()
{
switch(throttle_mode) {
case THROTTLE_MANUAL:
case THROTTLE_MANUAL_TILT_COMPENSATED:
case THROTTLE_MANUAL_HELI:
// manual modes always uses full swash range
motors.set_collective_for_landing(false);
break;
case THROTTLE_LAND:
// landing always uses limit swash range
motors.set_collective_for_landing(true);
break;
case THROTTLE_HOLD:
case THROTTLE_AUTO:
default:
// auto and hold use limited swash when landed
motors.set_collective_for_landing(!heli_flags.dynamic_flight || ap.land_complete || !ap.auto_armed);
break;
}
}
// heli_update_rotor_speed_targets - reads pilot input and passes new rotor speed targets to heli motors object
static void heli_update_rotor_speed_targets()
{
// get rotor control method
uint8_t rsc_control_mode = motors.get_rsc_mode();
switch (rsc_control_mode) {
case AP_MOTORS_HELI_RSC_MODE_NONE:
// even though pilot passes rotors speed directly to rotor ESC via receiver, motor lib needs to know if
// rotor is spinning in case we are using direct drive tailrotor which must be spun up at same time
case AP_MOTORS_HELI_RSC_MODE_CH8_PASSTHROUGH:
// pass through pilot desired rotor speed
motors.set_desired_rotor_speed(g.rc_8.control_in);
break;
case AP_MOTORS_HELI_RSC_MODE_SETPOINT:
// pass setpoint through as desired rotor speed
if (g.rc_8.control_in > 0) {
motors.set_desired_rotor_speed(motors.get_rsc_setpoint());
}else{
motors.set_desired_rotor_speed(0);
}
break;
}
}
#endif // FRAME_CONFIG == HELI_FRAME

View File

@ -3,7 +3,7 @@
#define ARM_DELAY 20 // called at 10hz so 2 seconds #define ARM_DELAY 20 // called at 10hz so 2 seconds
#define DISARM_DELAY 20 // called at 10hz so 2 seconds #define DISARM_DELAY 20 // called at 10hz so 2 seconds
#define AUTO_TRIM_DELAY 100 // called at 10hz so 10 seconds #define AUTO_TRIM_DELAY 100 // called at 10hz so 10 seconds
#define AUTO_DISARMING_DELAY 25 // called at 1hz so 25 seconds #define AUTO_DISARMING_DELAY 15 // called at 1hz so 15 seconds
// arm_motors_check - checks for pilot input to arm or disarm the copter // arm_motors_check - checks for pilot input to arm or disarm the copter
// called at 10hz // called at 10hz
@ -18,7 +18,7 @@ static void arm_motors_check()
return; return;
} }
// allow arming/disarming in fully manual flight modes ACRO, STABILIZE, SPORT and TOY // allow arming/disarming in fully manual flight modes ACRO, STABILIZE, SPORT and DRIFT
if (manual_flight_mode(control_mode)) { if (manual_flight_mode(control_mode)) {
allow_arming = true; allow_arming = true;
} }
@ -35,17 +35,14 @@ static void arm_motors_check()
} }
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
if ((motors.rsc_mode > 0) && (g.rc_8.control_in >= 10)){ // heli specific arming check
if (!motors.allow_arming()){
arming_counter = 0; arming_counter = 0;
return; return;
} }
#endif // HELI_FRAME #endif // HELI_FRAME
#if TOY_EDF == ENABLED
int16_t tmp = g.rc_1.control_in;
#else
int16_t tmp = g.rc_4.control_in; int16_t tmp = g.rc_4.control_in;
#endif
// full right // full right
if (tmp > 4000) { if (tmp > 4000) {
@ -91,19 +88,25 @@ static void arm_motors_check()
} }
} }
// auto_disarm_check - disarms the copter if it has been sitting on the ground in manual mode with throttle low for at least 25 seconds // auto_disarm_check - disarms the copter if it has been sitting on the ground in manual mode with throttle low for at least 15 seconds
// called at 1hz // called at 1hz
static void auto_disarm_check() static void auto_disarm_check()
{ {
static uint8_t auto_disarming_counter; static uint8_t auto_disarming_counter;
if(manual_flight_mode(control_mode) && (g.rc_3.control_in == 0) && motors.armed()) { // exit immediately if we are already disarmed or throttle is not zero
if (!motors.armed() || g.rc_3.control_in > 0) {
auto_disarming_counter = 0;
return;
}
// allow auto disarm in manual flight modes or Loiter/AltHold if we're landed
if(manual_flight_mode(control_mode) || (ap.land_complete && (control_mode == LOITER || control_mode == ALT_HOLD))) {
auto_disarming_counter++; auto_disarming_counter++;
if(auto_disarming_counter == AUTO_DISARMING_DELAY) { if(auto_disarming_counter >= AUTO_DISARMING_DELAY) {
init_disarm_motors(); init_disarm_motors();
}else if (auto_disarming_counter > AUTO_DISARMING_DELAY) { auto_disarming_counter = 0;
auto_disarming_counter = AUTO_DISARMING_DELAY + 1;
} }
}else{ }else{
auto_disarming_counter = 0; auto_disarming_counter = 0;
@ -122,6 +125,9 @@ static void init_arm_motors()
// disable cpu failsafe because initialising everything takes a while // disable cpu failsafe because initialising everything takes a while
failsafe_disable(); failsafe_disable();
// disable inertial nav errors temporarily
inertial_nav.ignore_next_error();
#if LOGGING_ENABLED == ENABLED #if LOGGING_ENABLED == ENABLED
// start dataflash // start dataflash
start_logging(); start_logging();
@ -135,8 +141,9 @@ static void init_arm_motors()
// mid-flight, so set the serial ports non-blocking once we arm // mid-flight, so set the serial ports non-blocking once we arm
// the motors // the motors
hal.uartA->set_blocking_writes(false); hal.uartA->set_blocking_writes(false);
if (gcs3.initialised) {
hal.uartC->set_blocking_writes(false); hal.uartC->set_blocking_writes(false);
if (hal.uartD != NULL) {
hal.uartD->set_blocking_writes(false);
} }
#if COPTER_LEDS == ENABLED #if COPTER_LEDS == ENABLED
@ -151,8 +158,10 @@ static void init_arm_motors()
// Reset home position // Reset home position
// ------------------- // -------------------
if(ap.home_is_set) if (ap.home_is_set) {
init_home(); init_home();
calc_distance_and_bearing();
}
// all I terms are invalid // all I terms are invalid
// ----------------------- // -----------------------
@ -160,7 +169,7 @@ static void init_arm_motors()
if(did_ground_start == false) { if(did_ground_start == false) {
did_ground_start = true; did_ground_start = true;
startup_ground(); startup_ground(true);
} }
#if HIL_MODE != HIL_MODE_ATTITUDE #if HIL_MODE != HIL_MODE_ATTITUDE
@ -213,13 +222,14 @@ static void init_arm_motors()
static void pre_arm_checks(bool display_failure) static void pre_arm_checks(bool display_failure)
{ {
// exit immediately if we've already successfully performed the pre-arm check // exit immediately if we've already successfully performed the pre-arm check
if( ap.pre_arm_check ) { if (ap.pre_arm_check) {
return; return;
} }
// succeed if pre arm checks are disabled // succeed if pre arm checks are disabled
if(!g.arming_check_enabled) { if(g.arming_check_enabled == ARMING_CHECK_NONE) {
set_pre_arm_check(true); set_pre_arm_check(true);
set_pre_arm_rc_check(true);
return; return;
} }
@ -232,22 +242,19 @@ static void pre_arm_checks(bool display_failure)
return; return;
} }
// pre-arm check to ensure ch7 and ch8 have different functions // check Baro
if ((g.ch7_option != 0 || g.ch8_option != 0) && g.ch7_option == g.ch8_option) { if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_BARO)) {
// barometer health check
if(!barometer.healthy) {
if (display_failure) { if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Ch7&Ch8 Opt cannot be same")); gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Baro not healthy"));
} }
return; return;
} }
// check accelerometers have been calibrated
if(!ins.calibrated()) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: INS not calibrated"));
}
return;
} }
// check Compass
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_COMPASS)) {
// check the compass is healthy // check the compass is healthy
if(!compass.healthy) { if(!compass.healthy) {
if (display_failure) { if (display_failure) {
@ -281,35 +288,65 @@ static void pre_arm_checks(bool display_failure)
} }
return; return;
} }
// barometer health check
if(!barometer.healthy) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Baro not healthy"));
} }
// check GPS
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_GPS)) {
// check gps is ok if required - note this same check is repeated again in arm_checks
if ((mode_requires_GPS(control_mode) || g.failsafe_gps_enabled == FS_GPS_LAND_EVEN_STABILIZE) && !pre_arm_gps_checks(display_failure)) {
return; return;
} }
#if AC_FENCE == ENABLED #if AC_FENCE == ENABLED
// check fence is initialised // check fence is initialised
if(!fence.pre_arm_check() || (((fence.get_enabled_fences() & AC_FENCE_TYPE_CIRCLE) != 0) && !pre_arm_gps_checks())) { if(!fence.pre_arm_check() || (((fence.get_enabled_fences() & AC_FENCE_TYPE_CIRCLE) != 0) && !pre_arm_gps_checks(display_failure))) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Bad GPS Pos"));
}
return; return;
} }
#endif #endif
}
// check INS
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_INS)) {
// check accelerometers have been calibrated
if(!ins.calibrated()) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: INS not calibrated"));
}
return;
}
// check accels and gyros are healthy
if(!ins.healthy()) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: INS not healthy"));
}
return;
}
}
#ifndef CONFIG_ARCH_BOARD_PX4FMU_V1 #ifndef CONFIG_ARCH_BOARD_PX4FMU_V1
// check board voltage // check board voltage
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_VOLTAGE)) {
if(board_voltage() < BOARD_VOLTAGE_MIN || board_voltage() > BOARD_VOLTAGE_MAX) { if(board_voltage() < BOARD_VOLTAGE_MIN || board_voltage() > BOARD_VOLTAGE_MAX) {
if (display_failure) { if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Check Board Voltage")); gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Check Board Voltage"));
} }
return; return;
} }
}
#endif #endif
// check various parameter values
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_PARAMETERS)) {
// ensure ch7 and ch8 have different functions
if ((g.ch7_option != 0 || g.ch8_option != 0) && g.ch7_option == g.ch8_option) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Ch7&Ch8 Opt cannot be same"));
}
return;
}
// failsafe parameter checks // failsafe parameter checks
if (g.failsafe_throttle) { if (g.failsafe_throttle) {
// check throttle min is above throttle failsafe trigger and that the trigger is above ppm encoder's loss-of-signal value of 900 // check throttle min is above throttle failsafe trigger and that the trigger is above ppm encoder's loss-of-signal value of 900
@ -329,13 +366,14 @@ static void pre_arm_checks(bool display_failure)
return; return;
} }
// check gps is ok if required - note this same check is repeated again in arm_checks // acro balance parameter check
if (mode_requires_GPS(control_mode) && !pre_arm_gps_checks()) { if ((g.acro_balance_roll > g.pi_stabilize_roll.kP()) || (g.acro_balance_pitch > g.pi_stabilize_pitch.kP())) {
if (display_failure) { if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Bad GPS Pos")); gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: ACRO_BAL_ROLL/PITCH"));
} }
return; return;
} }
}
// if we've gotten this far then pre arm checks have completed // if we've gotten this far then pre arm checks have completed
set_pre_arm_check(true); set_pre_arm_check(true);
@ -349,6 +387,12 @@ static void pre_arm_rc_checks()
return; return;
} }
// set rc-checks to success if RC checks are disabled
if ((g.arming_check_enabled != ARMING_CHECK_ALL) && !(g.arming_check_enabled & ARMING_CHECK_RC)) {
set_pre_arm_rc_check(true);
return;
}
// check if radio has been calibrated // check if radio has been calibrated
if(!g.rc_3.radio_min.load() && !g.rc_3.radio_max.load()) { if(!g.rc_3.radio_min.load() && !g.rc_3.radio_max.load()) {
return; return;
@ -365,16 +409,19 @@ static void pre_arm_rc_checks()
} }
// if we've gotten this far rc is ok // if we've gotten this far rc is ok
ap.pre_arm_rc_check = true; set_pre_arm_rc_check(true);
} }
// performs pre_arm gps related checks and returns true if passed // performs pre_arm gps related checks and returns true if passed
static bool pre_arm_gps_checks() static bool pre_arm_gps_checks(bool display_failure)
{ {
float speed_cms = inertial_nav.get_velocity().length(); // speed according to inertial nav in cm/s float speed_cms = inertial_nav.get_velocity().length(); // speed according to inertial nav in cm/s
// ensure GPS is ok and our speed is below 50cm/s // ensure GPS is ok and our speed is below 50cm/s
if (!GPS_ok() || g_gps->hdop > g.gps_hdop_good || gps_glitch.glitching() || speed_cms == 0 || speed_cms > PREARM_MAX_VELOCITY_CMS) { if (!GPS_ok() || g_gps->hdop > g.gps_hdop_good || gps_glitch.glitching() || speed_cms == 0 || speed_cms > PREARM_MAX_VELOCITY_CMS) {
if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Bad GPS Pos"));
}
return false; return false;
} }
@ -387,17 +434,27 @@ static bool pre_arm_gps_checks()
static bool arm_checks(bool display_failure) static bool arm_checks(bool display_failure)
{ {
// succeed if arming checks are disabled // succeed if arming checks are disabled
if(!g.arming_check_enabled) { if (g.arming_check_enabled == ARMING_CHECK_NONE) {
return true; return true;
} }
// check gps is ok if required - note this same check is also done in pre-arm checks // check gps is ok if required - note this same check is also done in pre-arm checks
if (mode_requires_GPS(control_mode) && !pre_arm_gps_checks()) { if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_GPS)) {
if ((mode_requires_GPS(control_mode) || g.failsafe_gps_enabled == FS_GPS_LAND_EVEN_STABILIZE) && !pre_arm_gps_checks(display_failure)) {
return false;
}
}
// check parameters
if ((g.arming_check_enabled == ARMING_CHECK_ALL) || (g.arming_check_enabled & ARMING_CHECK_PARAMETERS)) {
// check throttle is above failsafe throttle
if (g.failsafe_throttle != FS_THR_DISABLED && g.rc_3.radio_in < g.failsafe_throttle_value) {
if (display_failure) { if (display_failure) {
gcs_send_text_P(SEVERITY_HIGH,PSTR("Arm: Bad GPS Pos")); gcs_send_text_P(SEVERITY_HIGH,PSTR("Arm: Thr below FS"));
} }
return false; return false;
} }
}
// check if safety switch has been pushed // check if safety switch has been pushed
if (hal.util->safety_switch_state() == AP_HAL::Util::SAFETY_DISARMED) { if (hal.util->safety_switch_state() == AP_HAL::Util::SAFETY_DISARMED) {
@ -411,14 +468,23 @@ static bool arm_checks(bool display_failure)
return true; return true;
} }
// init_disarm_motors - disarm motors
static void init_disarm_motors() static void init_disarm_motors()
{ {
// return immediately if we are already disarmed
if (!motors.armed()) {
return;
}
#if HIL_MODE != HIL_MODE_DISABLED || CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL #if HIL_MODE != HIL_MODE_DISABLED || CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
gcs_send_text_P(SEVERITY_HIGH, PSTR("DISARMING MOTORS")); gcs_send_text_P(SEVERITY_HIGH, PSTR("DISARMING MOTORS"));
#endif #endif
motors.armed(false); motors.armed(false);
// disable inertial nav errors temporarily
inertial_nav.ignore_next_error();
compass.save_offsets(); compass.save_offsets();
g.throttle_cruise.save(); g.throttle_cruise.save();

View File

@ -42,15 +42,12 @@ static void calc_distance_and_bearing()
} }
// calculate home distance and bearing // calculate home distance and bearing
if( ap.home_is_set && (g_gps->status() == GPS::GPS_OK_FIX_3D || g_gps->status() == GPS::GPS_OK_FIX_2D)) { if(GPS_ok()) {
home_distance = pythagorous2(curr.x, curr.y); home_distance = pythagorous2(curr.x, curr.y);
home_bearing = pv_get_bearing_cd(curr,Vector3f(0,0,0)); home_bearing = pv_get_bearing_cd(curr,Vector3f(0,0,0));
// update super simple bearing (if required) because it relies on home_bearing // update super simple bearing (if required) because it relies on home_bearing
update_super_simple_bearing(false); update_super_simple_bearing(false);
}else{
home_distance = 0;
home_bearing = 0;
} }
} }
@ -164,16 +161,6 @@ static void update_nav_mode()
log_counter = 0; log_counter = 0;
Log_Write_Nav_Tuning(); Log_Write_Nav_Tuning();
} }
/*
// To-Do: check that we haven't broken toy mode
case TOY_A:
case TOY_M:
set_nav_mode(NAV_NONE);
update_nav_wp();
break;
}
*/
} }
// Keeps old data out of our calculation / logs // Keeps old data out of our calculation / logs

View File

@ -8,39 +8,39 @@
// .z = altitude above home in cm // .z = altitude above home in cm
// pv_latlon_to_vector - convert lat/lon coordinates to a position vector // pv_latlon_to_vector - convert lat/lon coordinates to a position vector
const Vector3f pv_latlon_to_vector(int32_t lat, int32_t lon, int32_t alt) Vector3f pv_latlon_to_vector(int32_t lat, int32_t lon, int32_t alt)
{ {
Vector3f tmp((lat-home.lat) * LATLON_TO_CM, (lon-home.lng) * LATLON_TO_CM * scaleLongDown, alt); Vector3f tmp((lat-home.lat) * LATLON_TO_CM, (lon-home.lng) * LATLON_TO_CM * scaleLongDown, alt);
return tmp; return tmp;
} }
// pv_latlon_to_vector - convert lat/lon coordinates to a position vector // pv_latlon_to_vector - convert lat/lon coordinates to a position vector
const Vector3f pv_location_to_vector(Location loc) Vector3f pv_location_to_vector(Location loc)
{ {
Vector3f tmp((loc.lat-home.lat) * LATLON_TO_CM, (loc.lng-home.lng) * LATLON_TO_CM * scaleLongDown, loc.alt); Vector3f tmp((loc.lat-home.lat) * LATLON_TO_CM, (loc.lng-home.lng) * LATLON_TO_CM * scaleLongDown, loc.alt);
return tmp; return tmp;
} }
// pv_get_lon - extract latitude from position vector // pv_get_lon - extract latitude from position vector
const int32_t pv_get_lat(const Vector3f pos_vec) int32_t pv_get_lat(const Vector3f pos_vec)
{ {
return home.lat + (int32_t)(pos_vec.x / LATLON_TO_CM); return home.lat + (int32_t)(pos_vec.x / LATLON_TO_CM);
} }
// pv_get_lon - extract longitude from position vector // pv_get_lon - extract longitude from position vector
const int32_t pv_get_lon(const Vector3f &pos_vec) int32_t pv_get_lon(const Vector3f &pos_vec)
{ {
return home.lng + (int32_t)(pos_vec.y / LATLON_TO_CM * scaleLongUp); return home.lng + (int32_t)(pos_vec.y / LATLON_TO_CM * scaleLongUp);
} }
// pv_get_horizontal_distance_cm - return distance between two positions in cm // pv_get_horizontal_distance_cm - return distance between two positions in cm
const float pv_get_horizontal_distance_cm(const Vector3f &origin, const Vector3f &destination) float pv_get_horizontal_distance_cm(const Vector3f &origin, const Vector3f &destination)
{ {
return pythagorous2(destination.x-origin.x,destination.y-origin.y); return pythagorous2(destination.x-origin.x,destination.y-origin.y);
} }
// pv_get_bearing_cd - return bearing in centi-degrees between two positions // pv_get_bearing_cd - return bearing in centi-degrees between two positions
const float pv_get_bearing_cd(const Vector3f &origin, const Vector3f &destination) float pv_get_bearing_cd(const Vector3f &origin, const Vector3f &destination)
{ {
float bearing = 9000 + atan2f(-(destination.x-origin.x), destination.y-origin.y) * DEGX100; float bearing = 9000 + atan2f(-(destination.x-origin.x), destination.y-origin.y) * DEGX100;
if (bearing < 0) { if (bearing < 0) {

View File

@ -10,6 +10,7 @@ static void default_dead_zones()
#if FRAME_CONFIG == HELI_FRAME #if FRAME_CONFIG == HELI_FRAME
g.rc_3.set_default_dead_zone(10); g.rc_3.set_default_dead_zone(10);
g.rc_4.set_default_dead_zone(15); g.rc_4.set_default_dead_zone(15);
g.rc_8.set_default_dead_zone(10);
#else #else
g.rc_3.set_default_dead_zone(30); g.rc_3.set_default_dead_zone(30);
g.rc_4.set_default_dead_zone(40); g.rc_4.set_default_dead_zone(40);
@ -22,29 +23,32 @@ static void init_rc_in()
// set rc channel ranges // set rc channel ranges
g.rc_1.set_angle(ROLL_PITCH_INPUT_MAX); g.rc_1.set_angle(ROLL_PITCH_INPUT_MAX);
g.rc_2.set_angle(ROLL_PITCH_INPUT_MAX); g.rc_2.set_angle(ROLL_PITCH_INPUT_MAX);
#if FRAME_CONFIG == HELI_FRAME
// we do not want to limit the movment of the heli's swash plate
g.rc_3.set_range(0, 1000);
#else
g.rc_3.set_range(g.throttle_min, g.throttle_max); g.rc_3.set_range(g.throttle_min, g.throttle_max);
#endif
g.rc_4.set_angle(4500); g.rc_4.set_angle(4500);
g.rc_1.set_type(RC_CHANNEL_TYPE_ANGLE_RAW); g.rc_1.set_type(RC_CHANNEL_TYPE_ANGLE_RAW);
g.rc_2.set_type(RC_CHANNEL_TYPE_ANGLE_RAW); g.rc_2.set_type(RC_CHANNEL_TYPE_ANGLE_RAW);
g.rc_4.set_type(RC_CHANNEL_TYPE_ANGLE_RAW); g.rc_4.set_type(RC_CHANNEL_TYPE_ANGLE_RAW);
#if FRAME_CONFIG == SINGLE_FRAME
// we set four servos to angle
g.single_servo_1.set_type(RC_CHANNEL_TYPE_ANGLE);
g.single_servo_2.set_type(RC_CHANNEL_TYPE_ANGLE);
g.single_servo_3.set_type(RC_CHANNEL_TYPE_ANGLE);
g.single_servo_4.set_type(RC_CHANNEL_TYPE_ANGLE);
g.single_servo_1.set_angle(DEFAULT_ANGLE_MAX);
g.single_servo_2.set_angle(DEFAULT_ANGLE_MAX);
g.single_servo_3.set_angle(DEFAULT_ANGLE_MAX);
g.single_servo_4.set_angle(DEFAULT_ANGLE_MAX);
#endif
//set auxiliary ranges //set auxiliary servo ranges
g.rc_5.set_range(0,1000); g.rc_5.set_range(0,1000);
g.rc_6.set_range(0,1000); g.rc_6.set_range(0,1000);
g.rc_7.set_range(0,1000); g.rc_7.set_range(0,1000);
g.rc_8.set_range(0,1000); g.rc_8.set_range(0,1000);
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 // update assigned functions for auxiliary servos
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12); aux_servos_update_fn();
#elif MOUNT == ENABLED
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_10, &g.rc_11);
#endif
// set default dead zones // set default dead zones
default_dead_zones(); default_dead_zones();
@ -95,12 +99,6 @@ static void init_rc_out()
if (ap.pre_arm_rc_check) { if (ap.pre_arm_rc_check) {
output_min(); output_min();
} }
#if TOY_EDF == ENABLED
// add access to CH8 and CH6
APM_RC.enable_out(CH_8);
APM_RC.enable_out(CH_6);
#endif
} }
// output_min - enable and output lowest possible value to motors // output_min - enable and output lowest possible value to motors
@ -130,6 +128,11 @@ static void read_radio()
g.rc_6.set_pwm(periods[5]); g.rc_6.set_pwm(periods[5]);
g.rc_7.set_pwm(periods[6]); g.rc_7.set_pwm(periods[6]);
g.rc_8.set_pwm(periods[7]); g.rc_8.set_pwm(periods[7]);
// flag we must have an rc receiver attached
if (!failsafe.rc_override_active) {
ap.rc_receiver_present = true;
}
}else{ }else{
uint32_t elapsed = millis() - last_update; uint32_t elapsed = millis() - last_update;
// turn on throttle failsafe if no update from ppm encoder for 2 seconds // turn on throttle failsafe if no update from ppm encoder for 2 seconds
@ -183,6 +186,55 @@ static void set_throttle_and_failsafe(uint16_t throttle_pwm)
} }
} }
// aux_servos_update - update auxiliary servos assigned functions in case the user has changed them
void aux_servos_update_fn()
{
// Quads can use RC5 and higher as auxiliary channels
#if (FRAME_CONFIG == QUAD_FRAME)
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12);
#else // APM1, APM2, SITL
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_8, &g.rc_10, &g.rc_11);
#endif
// Tri's and Singles can use RC5, RC6, RC8 and higher
#elif (FRAME_CONFIG == TRI_FRAME || FRAME_CONFIG == SINGLE_FRAME)
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_8, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12);
#else // APM1, APM2, SITL
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_8, &g.rc_10, &g.rc_11);
#endif
// Hexa and Y6 can use RC7 and higher
#elif (FRAME_CONFIG == HEXA_FRAME || FRAME_CONFIG == Y6_FRAME)
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
update_aux_servo_function(&g.rc_7, &g.rc_8, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12);
#else
update_aux_servo_function(&g.rc_7, &g.rc_8, &g.rc_10, &g.rc_11);
#endif
// Octa and X8 can use RC9 and higher
#elif (FRAME_CONFIG == OCTA_FRAME || FRAME_CONFIG == OCTA_QUAD_FRAME)
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
update_aux_servo_function(&g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12);
#else
update_aux_servo_function(&g.rc_10, &g.rc_11);
#endif
// Heli's can use RC5, RC6, RC7, not RC8, and higher
#elif (FRAME_CONFIG == HELI_FRAME)
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_9, &g.rc_10, &g.rc_11, &g.rc_12);
#else // APM1, APM2, SITL
update_aux_servo_function(&g.rc_5, &g.rc_6, &g.rc_7, &g.rc_10, &g.rc_11);
#endif
// throw compile error if frame type is unrecognise
#else
#error Unrecognised frame type
#endif
}
static void trim_radio() static void trim_radio()
{ {
for (uint8_t i = 0; i < 30; i++) { for (uint8_t i = 0; i < 30; i++) {

View File

@ -8,10 +8,6 @@ static int8_t setup_compass (uint8_t argc, const Menu::arg *argv);
static int8_t setup_compassmot (uint8_t argc, const Menu::arg *argv); static int8_t setup_compassmot (uint8_t argc, const Menu::arg *argv);
static int8_t setup_erase (uint8_t argc, const Menu::arg *argv); static int8_t setup_erase (uint8_t argc, const Menu::arg *argv);
static int8_t setup_frame (uint8_t argc, const Menu::arg *argv); static int8_t setup_frame (uint8_t argc, const Menu::arg *argv);
#if FRAME_CONFIG == HELI_FRAME
static int8_t setup_gyro (uint8_t argc, const Menu::arg *argv);
static int8_t setup_heli (uint8_t argc, const Menu::arg *argv);
#endif
static int8_t setup_flightmodes (uint8_t argc, const Menu::arg *argv); static int8_t setup_flightmodes (uint8_t argc, const Menu::arg *argv);
static int8_t setup_optflow (uint8_t argc, const Menu::arg *argv); static int8_t setup_optflow (uint8_t argc, const Menu::arg *argv);
static int8_t setup_radio (uint8_t argc, const Menu::arg *argv); static int8_t setup_radio (uint8_t argc, const Menu::arg *argv);
@ -31,10 +27,6 @@ const struct Menu::command setup_menu_commands[] PROGMEM = {
{"compassmot", setup_compassmot}, {"compassmot", setup_compassmot},
{"erase", setup_erase}, {"erase", setup_erase},
{"frame", setup_frame}, {"frame", setup_frame},
#if FRAME_CONFIG == HELI_FRAME
{"gyro", setup_gyro},
{"heli", setup_heli},
#endif
{"modes", setup_flightmodes}, {"modes", setup_flightmodes},
{"optflow", setup_optflow}, {"optflow", setup_optflow},
{"radio", setup_radio}, {"radio", setup_radio},
@ -172,7 +164,7 @@ setup_compassmot(uint8_t argc, const Menu::arg *argv)
// disable throttle and battery failsafe // disable throttle and battery failsafe
g.failsafe_throttle = FS_THR_DISABLED; g.failsafe_throttle = FS_THR_DISABLED;
g.failsafe_battery_enabled = false; g.failsafe_battery_enabled = FS_BATT_DISABLED;
// read radio // read radio
read_radio(); read_radio();
@ -365,253 +357,6 @@ setup_frame(uint8_t argc, const Menu::arg *argv)
return 0; return 0;
} }
#if FRAME_CONFIG == HELI_FRAME
// setup for external tail gyro (for heli only)
static int8_t
setup_gyro(uint8_t argc, const Menu::arg *argv)
{
if (!strcmp_P(argv[1].str, PSTR("on"))) {
motors.ext_gyro_enabled.set_and_save(true);
// optionally capture the gain
if( argc >= 2 && argv[2].i >= 1000 && argv[2].i <= 2000 ) {
motors.ext_gyro_gain = argv[2].i;
motors.ext_gyro_gain.save();
}
} else if (!strcmp_P(argv[1].str, PSTR("off"))) {
motors.ext_gyro_enabled.set_and_save(false);
// capture gain if user simply provides a number
} else if( argv[1].i >= 1000 && argv[1].i <= 2000 ) {
motors.ext_gyro_enabled.set_and_save(true);
motors.ext_gyro_gain = argv[1].i;
motors.ext_gyro_gain.save();
}else{
cliSerial->printf_P(PSTR("\nOp:[on, off] gain\n"));
}
report_gyro();
return 0;
}
// Perform heli setup.
// Called by the setup menu 'radio' command.
static int8_t
setup_heli(uint8_t argc, const Menu::arg *argv)
{
uint8_t active_servo = 0;
int16_t value = 0;
int16_t temp;
int16_t state = 0; // 0 = set rev+pos, 1 = capture min/max
int16_t max_roll=0, max_pitch=0, min_collective=0, max_collective=0, min_tail=0, max_tail=0;
// initialise swash plate
motors.init_swash();
// source swash plate movements directly from radio
motors.servo_manual = true;
// display initial settings
report_heli();
// display help
cliSerial->printf_P(PSTR("Instructions:"));
print_divider();
cliSerial->printf_P(PSTR("\td\t\tdisplay settings\n"));
cliSerial->printf_P(PSTR("\t1~4\t\tselect servo\n"));
cliSerial->printf_P(PSTR("\ta or z\t\tmove mid up/down\n"));
cliSerial->printf_P(PSTR("\tc\t\tset coll when blade pitch zero\n"));
cliSerial->printf_P(PSTR("\tm\t\tset roll, pitch, coll min/max\n"));
cliSerial->printf_P(PSTR("\tp<angle>\tset pos (i.e. p0 = front, p90 = right)\n"));
cliSerial->printf_P(PSTR("\tr\t\treverse servo\n"));
cliSerial->printf_P(PSTR("\tu a|d\t\tupdate rate (a=analog servo, d=digital)\n"));
cliSerial->printf_P(PSTR("\tt<angle>\tset trim (-500 ~ 500)\n"));
cliSerial->printf_P(PSTR("\tx\t\texit & save\n"));
// start capturing
while( value != 'x' ) {
// read radio although we don't use it yet
read_radio();
// allow swash plate to move
motors.output_armed();
// record min/max
if( state == 1 ) {
if( abs(g.rc_1.control_in) > max_roll )
max_roll = abs(g.rc_1.control_in);
if( abs(g.rc_2.control_in) > max_pitch )
max_pitch = abs(g.rc_2.control_in);
if( g.rc_3.radio_out < min_collective )
min_collective = g.rc_3.radio_out;
if( g.rc_3.radio_out > max_collective )
max_collective = g.rc_3.radio_out;
min_tail = min(g.rc_4.radio_out, min_tail);
max_tail = max(g.rc_4.radio_out, max_tail);
}
if( cliSerial->available() ) {
value = cliSerial->read();
// process the user's input
switch( value ) {
case '1':
active_servo = CH_1;
break;
case '2':
active_servo = CH_2;
break;
case '3':
active_servo = CH_3;
break;
case '4':
active_servo = CH_4;
break;
case 'a':
case 'A':
heli_get_servo(active_servo)->radio_trim += 10;
break;
case 'c':
case 'C':
if( g.rc_3.radio_out >= 900 && g.rc_3.radio_out <= 2100 ) {
motors.collective_mid = g.rc_3.radio_out;
cliSerial->printf_P(PSTR("Collective when blade pitch at zero: %d\n"),(int)motors.collective_mid);
}
break;
case 'd':
case 'D':
// display settings
report_heli();
break;
case 'm':
case 'M':
if( state == 0 ) {
state = 1; // switch to capture min/max mode
cliSerial->printf_P(PSTR("Move coll, roll, pitch and tail to extremes, press 'm' when done\n"));
// reset servo ranges
motors.roll_max = motors.pitch_max = 4500;
motors.collective_min = 1000;
motors.collective_max = 2000;
motors._servo_4->radio_min = 1000;
motors._servo_4->radio_max = 2000;
// set sensible values in temp variables
max_roll = abs(g.rc_1.control_in);
max_pitch = abs(g.rc_2.control_in);
min_collective = 2000;
max_collective = 1000;
min_tail = max_tail = abs(g.rc_4.radio_out);
}else{
state = 0; // switch back to normal mode
// double check values aren't totally terrible
if( max_roll <= 1000 || max_pitch <= 1000 || (max_collective - min_collective < 200) || (max_tail - min_tail < 200) || min_tail < 1000 || max_tail > 2000 )
cliSerial->printf_P(PSTR("Invalid min/max captured roll:%d, pitch:%d, collective min: %d max: %d, tail min:%d max:%d\n"),max_roll,max_pitch,min_collective,max_collective,min_tail,max_tail);
else{
motors.roll_max = max_roll;
motors.pitch_max = max_pitch;
motors.collective_min = min_collective;
motors.collective_max = max_collective;
motors._servo_4->radio_min = min_tail;
motors._servo_4->radio_max = max_tail;
// reinitialise swash
motors.init_swash();
// display settings
report_heli();
}
}
break;
case 'p':
case 'P':
temp = read_num_from_serial();
if( temp >= -360 && temp <= 360 ) {
if( active_servo == CH_1 )
motors.servo1_pos = temp;
if( active_servo == CH_2 )
motors.servo2_pos = temp;
if( active_servo == CH_3 )
motors.servo3_pos = temp;
motors.init_swash();
cliSerial->printf_P(PSTR("Servo %d\t\tpos:%d\n"),active_servo+1, temp);
}
break;
case 'r':
case 'R':
heli_get_servo(active_servo)->set_reverse(!heli_get_servo(active_servo)->get_reverse());
break;
case 't':
case 'T':
temp = read_num_from_serial();
if( temp > 1000 )
temp -= 1500;
if( temp > -500 && temp < 500 ) {
heli_get_servo(active_servo)->radio_trim = 1500 + temp;
motors.init_swash();
cliSerial->printf_P(PSTR("Servo %d\t\ttrim:%d\n"),active_servo+1, 1500 + temp);
}
break;
case 'u':
case 'U':
temp = 0;
// delay up to 2 seconds for servo type from user
while( !cliSerial->available() && temp < 20 ) {
temp++;
delay(100);
}
if( cliSerial->available() ) {
value = cliSerial->read();
if( value == 'a' || value == 'A' ) {
g.rc_speed.set_and_save(AP_MOTORS_HELI_SPEED_ANALOG_SERVOS);
//motors._speed_hz = AP_MOTORS_HELI_SPEED_ANALOG_SERVOS; // need to force this update to take effect immediately
cliSerial->printf_P(PSTR("Analog Servo %dhz\n"),(int)g.rc_speed);
}
if( value == 'd' || value == 'D' ) {
g.rc_speed.set_and_save(AP_MOTORS_HELI_SPEED_ANALOG_SERVOS);
//motors._speed_hz = AP_MOTORS_HELI_SPEED_ANALOG_SERVOS; // need to force this update to take effect immediately
cliSerial->printf_P(PSTR("Digital Servo %dhz\n"),(int)g.rc_speed);
}
}
break;
case 'z':
case 'Z':
heli_get_servo(active_servo)->radio_trim -= 10;
break;
}
}
delay(20);
}
// display final settings
report_heli();
// save to eeprom
motors._servo_1->save_eeprom();
motors._servo_2->save_eeprom();
motors._servo_3->save_eeprom();
motors._servo_4->save_eeprom();
motors.servo1_pos.save();
motors.servo2_pos.save();
motors.servo3_pos.save();
motors.roll_max.save();
motors.pitch_max.save();
motors.collective_min.save();
motors.collective_max.save();
motors.collective_mid.save();
// return swash plate movements to attitude controller
motors.servo_manual = false;
return(0);
}
#endif // FRAME_CONFIG == HELI
static int8_t static int8_t
setup_flightmodes(uint8_t argc, const Menu::arg *argv) setup_flightmodes(uint8_t argc, const Menu::arg *argv)
{ {
@ -926,11 +671,6 @@ setup_show(uint8_t argc, const Menu::arg *argv)
report_compass(); report_compass();
report_optflow(); report_optflow();
#if FRAME_CONFIG == HELI_FRAME
report_heli();
report_gyro();
#endif
AP_Param::show_all(cliSerial); AP_Param::show_all(cliSerial);
return(0); return(0);
@ -1094,44 +834,6 @@ void report_optflow()
#endif // OPTFLOW == ENABLED #endif // OPTFLOW == ENABLED
} }
#if FRAME_CONFIG == HELI_FRAME
static void report_heli()
{
cliSerial->printf_P(PSTR("Heli\n"));
print_divider();
// main servo settings
cliSerial->printf_P(PSTR("Servo \tpos \tmin \tmax \trev\n"));
cliSerial->printf_P(PSTR("1:\t%d \t%d \t%d \t%d\n"),(int)motors.servo1_pos, (int)motors._servo_1->radio_min, (int)motors._servo_1->radio_max, (int)motors._servo_1->get_reverse());
cliSerial->printf_P(PSTR("2:\t%d \t%d \t%d \t%d\n"),(int)motors.servo2_pos, (int)motors._servo_2->radio_min, (int)motors._servo_2->radio_max, (int)motors._servo_2->get_reverse());
cliSerial->printf_P(PSTR("3:\t%d \t%d \t%d \t%d\n"),(int)motors.servo3_pos, (int)motors._servo_3->radio_min, (int)motors._servo_3->radio_max, (int)motors._servo_3->get_reverse());
cliSerial->printf_P(PSTR("tail:\t\t%d \t%d \t%d\n"), (int)motors._servo_4->radio_min, (int)motors._servo_4->radio_max, (int)motors._servo_4->get_reverse());
cliSerial->printf_P(PSTR("roll max: \t%d\n"), (int)motors.roll_max);
cliSerial->printf_P(PSTR("pitch max: \t%d\n"), (int)motors.pitch_max);
cliSerial->printf_P(PSTR("coll min:\t%d\t mid:%d\t max:%d\n"),(int)motors.collective_min, (int)motors.collective_mid, (int)motors.collective_max);
// calculate and print servo rate
cliSerial->printf_P(PSTR("servo rate:\t%d hz\n"),(int)g.rc_speed);
print_blanks(2);
}
static void report_gyro()
{
cliSerial->printf_P(PSTR("Gyro:\n"));
print_divider();
print_enabled( motors.ext_gyro_enabled );
if( motors.ext_gyro_enabled )
cliSerial->printf_P(PSTR("gain: %d"),(int)motors.ext_gyro_gain);
print_blanks(2);
}
#endif // FRAME_CONFIG == HELI_FRAME
/***************************************************************************/ /***************************************************************************/
// CLI utilities // CLI utilities
/***************************************************************************/ /***************************************************************************/
@ -1182,8 +884,8 @@ static void zero_eeprom(void)
static void static void
print_accel_offsets_and_scaling(void) print_accel_offsets_and_scaling(void)
{ {
Vector3f accel_offsets = ins.get_accel_offsets(); const Vector3f &accel_offsets = ins.get_accel_offsets();
Vector3f accel_scale = ins.get_accel_scale(); const Vector3f &accel_scale = ins.get_accel_scale();
cliSerial->printf_P(PSTR("A_off: %4.2f, %4.2f, %4.2f\nA_scale: %4.2f, %4.2f, %4.2f\n"), cliSerial->printf_P(PSTR("A_off: %4.2f, %4.2f, %4.2f\nA_scale: %4.2f, %4.2f, %4.2f\n"),
(float)accel_offsets.x, // Pitch (float)accel_offsets.x, // Pitch
(float)accel_offsets.y, // Roll (float)accel_offsets.y, // Roll
@ -1196,49 +898,13 @@ print_accel_offsets_and_scaling(void)
static void static void
print_gyro_offsets(void) print_gyro_offsets(void)
{ {
Vector3f gyro_offsets = ins.get_gyro_offsets(); const Vector3f &gyro_offsets = ins.get_gyro_offsets();
cliSerial->printf_P(PSTR("G_off: %4.2f, %4.2f, %4.2f\n"), cliSerial->printf_P(PSTR("G_off: %4.2f, %4.2f, %4.2f\n"),
(float)gyro_offsets.x, (float)gyro_offsets.x,
(float)gyro_offsets.y, (float)gyro_offsets.y,
(float)gyro_offsets.z); (float)gyro_offsets.z);
} }
#if FRAME_CONFIG == HELI_FRAME
static RC_Channel *
heli_get_servo(int16_t servo_num){
if( servo_num == CH_1 )
return motors._servo_1;
if( servo_num == CH_2 )
return motors._servo_2;
if( servo_num == CH_3 )
return motors._servo_3;
if( servo_num == CH_4 )
return motors._servo_4;
return NULL;
}
// Used to read integer values from the serial port
static int16_t read_num_from_serial() {
uint8_t index = 0;
uint8_t timeout = 0;
char data[5] = "";
do {
if (cliSerial->available() == 0) {
delay(10);
timeout++;
}else{
data[index] = cliSerial->read();
timeout = 0;
index++;
}
} while (timeout < 5 && index < 5);
return atoi(data);
}
#endif
#endif // CLI_ENABLED #endif // CLI_ENABLED
static void static void

View File

@ -103,7 +103,7 @@ static void init_ardupilot()
hal.uartB->begin(38400, 256, 16); hal.uartB->begin(38400, 256, 16);
#endif #endif
cliSerial->printf_P(PSTR("\n\nInit " THISFIRMWARE cliSerial->printf_P(PSTR("\n\nInit " FIRMWARE_STRING
"\n\nFree RAM: %u\n"), "\n\nFree RAM: %u\n"),
memcheck_available_memory()); memcheck_available_memory());
@ -134,7 +134,7 @@ static void init_ardupilot()
#endif #endif
// init the GCS // init the GCS
gcs0.init(hal.uartA); gcs[0].init(hal.uartA);
// Register the mavlink service callback. This will run // Register the mavlink service callback. This will run
// anytime there are more than 5ms remaining in a call to // anytime there are more than 5ms remaining in a call to
@ -150,8 +150,14 @@ static void init_ardupilot()
// we have a 2nd serial port for telemetry on all boards except // we have a 2nd serial port for telemetry on all boards except
// APM2. We actually do have one on APM2 but it isn't necessary as // APM2. We actually do have one on APM2 but it isn't necessary as
// a MUX is used // a MUX is used
hal.uartC->begin(map_baudrate(g.serial3_baud, SERIAL3_BAUD), 128, 128); hal.uartC->begin(map_baudrate(g.serial1_baud, SERIAL1_BAUD), 128, 128);
gcs3.init(hal.uartC); gcs[1].init(hal.uartC);
#endif
#if MAVLINK_COMM_NUM_BUFFERS > 2
if (hal.uartD != NULL) {
hal.uartD->begin(map_baudrate(g.serial2_baud, SERIAL2_BAUD), 128, 128);
gcs[2].init(hal.uartD);
}
#endif #endif
// identify ourselves correctly with the ground station // identify ourselves correctly with the ground station
@ -166,15 +172,10 @@ static void init_ardupilot()
} else if (DataFlash.NeedErase()) { } else if (DataFlash.NeedErase()) {
gcs_send_text_P(SEVERITY_LOW, PSTR("ERASING LOGS")); gcs_send_text_P(SEVERITY_LOW, PSTR("ERASING LOGS"));
do_erase_logs(); do_erase_logs();
gcs0.reset_cli_timeout(); gcs[0].reset_cli_timeout();
} }
#endif #endif
#if FRAME_CONFIG == HELI_FRAME
motors.servo_manual = false;
motors.init_swash(); // heli initialisation
#endif
init_rc_in(); // sets up rc channels from radio init_rc_in(); // sets up rc channels from radio
init_rc_out(); // sets up motors and output to escs init_rc_out(); // sets up motors and output to escs
@ -214,9 +215,12 @@ static void init_ardupilot()
#if CLI_ENABLED == ENABLED #if CLI_ENABLED == ENABLED
const prog_char_t *msg = PSTR("\nPress ENTER 3 times to start interactive setup\n"); const prog_char_t *msg = PSTR("\nPress ENTER 3 times to start interactive setup\n");
cliSerial->println_P(msg); cliSerial->println_P(msg);
if (gcs3.initialised) { if (gcs[1].initialised) {
hal.uartC->println_P(msg); hal.uartC->println_P(msg);
} }
if (num_gcs > 2 && gcs[2].initialised) {
hal.uartD->println_P(msg);
}
#endif // CLI_ENABLED #endif // CLI_ENABLED
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
@ -239,11 +243,6 @@ static void init_ardupilot()
init_sonar(); init_sonar();
#endif #endif
#if FRAME_CONFIG == HELI_FRAME
// initialise controller filters
init_rate_controllers();
#endif // HELI_FRAME
// initialize commands // initialize commands
// ------------------- // -------------------
init_commands(); init_commands();
@ -253,7 +252,12 @@ static void init_ardupilot()
reset_control_switch(); reset_control_switch();
init_aux_switches(); init_aux_switches();
startup_ground(); #if FRAME_CONFIG == HELI_FRAME
// trad heli specific initialisation
heli_init();
#endif
startup_ground(true);
#if LOGGING_ENABLED == ENABLED #if LOGGING_ENABLED == ENABLED
Log_Write_Startup(); Log_Write_Startup();
@ -266,7 +270,7 @@ static void init_ardupilot()
//****************************************************************************** //******************************************************************************
//This function does all the calibrations, etc. that we need during a ground start //This function does all the calibrations, etc. that we need during a ground start
//****************************************************************************** //******************************************************************************
static void startup_ground(void) static void startup_ground(bool force_gyro_cal)
{ {
gcs_send_text_P(SEVERITY_LOW,PSTR("GROUND START")); gcs_send_text_P(SEVERITY_LOW,PSTR("GROUND START"));
@ -275,7 +279,7 @@ static void startup_ground(void)
// Warm up and read Gyro offsets // Warm up and read Gyro offsets
// ----------------------------- // -----------------------------
ins.init(AP_InertialSensor::COLD_START, ins.init(force_gyro_cal?AP_InertialSensor::COLD_START:AP_InertialSensor::WARM_START,
ins_sample_rate); ins_sample_rate);
#if CLI_ENABLED == ENABLED #if CLI_ENABLED == ENABLED
report_ins(); report_ins();
@ -291,7 +295,7 @@ static void startup_ground(void)
// returns true if the GPS is ok and home position is set // returns true if the GPS is ok and home position is set
static bool GPS_ok() static bool GPS_ok()
{ {
if (g_gps != NULL && ap.home_is_set && g_gps->status() == GPS::GPS_OK_FIX_3D) { if (g_gps != NULL && ap.home_is_set && g_gps->status() == GPS::GPS_OK_FIX_3D && !gps_glitch.glitching() && !failsafe.gps) {
return true; return true;
}else{ }else{
return false; return false;
@ -307,6 +311,7 @@ static bool mode_requires_GPS(uint8_t mode) {
case RTL: case RTL:
case CIRCLE: case CIRCLE:
case POSITION: case POSITION:
case DRIFT:
return true; return true;
default: default:
return false; return false;
@ -320,8 +325,7 @@ static bool manual_flight_mode(uint8_t mode) {
switch(mode) { switch(mode) {
case ACRO: case ACRO:
case STABILIZE: case STABILIZE:
case TOY_A: case DRIFT:
case TOY_M:
case SPORT: case SPORT:
return true; return true;
default: default:
@ -332,8 +336,9 @@ static bool manual_flight_mode(uint8_t mode) {
} }
// set_mode - change flight mode and perform any necessary initialisation // set_mode - change flight mode and perform any necessary initialisation
// optional force parameter used to force the flight mode change (used only first time mode is set)
// returns true if mode was succesfully set // returns true if mode was succesfully set
// STABILIZE, ACRO, SPORT and LAND can always be set successfully but the return state of other flight modes should be checked and the caller should deal with failures appropriately // ACRO, STABILIZE, ALTHOLD, LAND, DRIFT and SPORT can always be set successfully but the return state of other flight modes should be checked and the caller should deal with failures appropriately
static bool set_mode(uint8_t mode) static bool set_mode(uint8_t mode)
{ {
// boolean to record if flight mode could be set // boolean to record if flight mode could be set
@ -356,9 +361,9 @@ static bool set_mode(uint8_t mode)
case STABILIZE: case STABILIZE:
success = true; success = true;
set_yaw_mode(YAW_HOLD); set_yaw_mode(STABILIZE_YAW);
set_roll_pitch_mode(ROLL_PITCH_STABLE); set_roll_pitch_mode(STABILIZE_RP);
set_throttle_mode(THROTTLE_MANUAL_TILT_COMPENSATED); set_throttle_mode(STABILIZE_THR);
set_nav_mode(NAV_NONE); set_nav_mode(NAV_NONE);
break; break;
@ -441,26 +446,12 @@ static bool set_mode(uint8_t mode)
} }
break; break;
// THOR case DRIFT:
// These are the flight modes for Toy mode
// See the defines for the enumerated values
case TOY_A:
success = true; success = true;
set_yaw_mode(YAW_TOY); set_yaw_mode(YAW_DRIFT);
set_roll_pitch_mode(ROLL_PITCH_TOY); set_roll_pitch_mode(ROLL_PITCH_DRIFT);
set_throttle_mode(THROTTLE_AUTO);
set_nav_mode(NAV_NONE); set_nav_mode(NAV_NONE);
set_throttle_mode(DRIFT_THR);
// save throttle for fast exit of Alt hold
saved_toy_throttle = g.rc_3.control_in;
break;
case TOY_M:
success = true;
set_yaw_mode(YAW_TOY);
set_roll_pitch_mode(ROLL_PITCH_TOY);
set_nav_mode(NAV_NONE);
set_throttle_mode(THROTTLE_HOLD);
break; break;
case SPORT: case SPORT:
@ -509,10 +500,18 @@ static void update_auto_armed()
} }
}else{ }else{
// arm checks // arm checks
#if FRAME_CONFIG == HELI_FRAME
// for tradheli if motors are armed and throttle is above zero and the motor is started, auto_armed should be true
if(motors.armed() && g.rc_3.control_in != 0 && motors.motor_runup_complete()) {
set_auto_armed(true);
}
#else
// if motors are armed and throttle is above zero auto_armed should be true // if motors are armed and throttle is above zero auto_armed should be true
if(motors.armed() && g.rc_3.control_in != 0) { if(motors.armed() && g.rc_3.control_in != 0) {
set_auto_armed(true); set_auto_armed(true);
} }
#endif // HELI_FRAME
} }
} }
@ -532,7 +531,7 @@ static uint32_t map_baudrate(int8_t rate, uint32_t default_baud)
case 111: return 111100; case 111: return 111100;
case 115: return 115200; case 115: return 115200;
} }
//cliSerial->println_P(PSTR("Invalid SERIAL3_BAUD")); //cliSerial->println_P(PSTR("Invalid baudrate"));
return default_baud; return default_baud;
} }
@ -550,11 +549,11 @@ static void check_usb_mux(void)
// the APM2 has a MUX setup where the first serial port switches // the APM2 has a MUX setup where the first serial port switches
// between USB and a TTL serial connection. When on USB we use // between USB and a TTL serial connection. When on USB we use
// SERIAL0_BAUD, but when connected as a TTL serial port we run it // SERIAL0_BAUD, but when connected as a TTL serial port we run it
// at SERIAL3_BAUD. // at SERIAL1_BAUD.
if (ap.usb_connected) { if (ap.usb_connected) {
hal.uartA->begin(SERIAL0_BAUD); hal.uartA->begin(SERIAL0_BAUD);
} else { } else {
hal.uartA->begin(map_baudrate(g.serial3_baud, SERIAL3_BAUD)); hal.uartA->begin(map_baudrate(g.serial1_baud, SERIAL1_BAUD));
} }
#endif #endif
} }
@ -607,11 +606,8 @@ print_flight_mode(AP_HAL::BetterStream *port, uint8_t mode)
case OF_LOITER: case OF_LOITER:
port->print_P(PSTR("OF_LOITER")); port->print_P(PSTR("OF_LOITER"));
break; break;
case TOY_M: case DRIFT:
port->print_P(PSTR("TOY_M")); port->print_P(PSTR("DRIFT"));
break;
case TOY_A:
port->print_P(PSTR("TOY_A"));
break; break;
case SPORT: case SPORT:
port->print_P(PSTR("SPORT")); port->print_P(PSTR("SPORT"));

View File

@ -284,8 +284,7 @@ test_optflow(uint8_t argc, const Menu::arg *argv)
while(1) { while(1) {
delay(200); delay(200);
optflow.update(millis()); optflow.update();
Log_Write_Optflow();
cliSerial->printf_P(PSTR("x/dx: %d/%d\t y/dy %d/%d\t squal:%d\n"), cliSerial->printf_P(PSTR("x/dx: %d/%d\t y/dy %d/%d\t squal:%d\n"),
optflow.x, optflow.x,
optflow.dx, optflow.dx,

View File

@ -1,175 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// Toy Mode - THOR
////////////////////////////////////////////////////////////////////////////////
static bool CH7_toy_flag;
#if TOY_MIXER == TOY_LOOKUP_TABLE
static const int16_t toy_lookup[] = {
186, 373, 558, 745,
372, 745, 1117, 1490,
558, 1118, 1675, 2235,
743, 1490, 2233, 2980,
929, 1863, 2792, 3725,
1115, 2235, 3350, 4470,
1301, 2608, 3908, 4500,
1487, 2980, 4467, 4500,
1673, 3353, 4500, 4500
};
#endif
//called at 10hz
void update_toy_throttle()
{
if(control_mode == TOY_A) {
// look for a change in throttle position to exit throttle hold
if(abs(g.rc_3.control_in - saved_toy_throttle) > 40) {
throttle_mode = THROTTLE_MANUAL;
}
if(throttle_mode == THROTTLE_AUTO) {
update_toy_altitude();
}
}
}
#define TOY_ALT_SMALL 25
#define TOY_ALT_LARGE 100
//called at 10hz
void update_toy_altitude()
{
int16_t input = g.rc_3.radio_in; // throttle
float current_target_alt = wp_nav.get_desired_alt();
//int16_t input = g.rc_7.radio_in;
// Trigger upward alt change
if(false == CH7_toy_flag && input > 1666) {
CH7_toy_flag = true;
// go up
if(current_target_alt >= 400) {
wp_nav.set_desired_alt(current_target_alt + TOY_ALT_LARGE);
}else{
wp_nav.set_desired_alt(current_target_alt + TOY_ALT_SMALL);
}
// Trigger downward alt change
}else if(false == CH7_toy_flag && input < 1333) {
CH7_toy_flag = true;
// go down
if(current_target_alt >= (400 + TOY_ALT_LARGE)) {
wp_nav.set_desired_alt(current_target_alt - TOY_ALT_LARGE);
}else if(current_target_alt >= TOY_ALT_SMALL) {
wp_nav.set_desired_alt(current_target_alt - TOY_ALT_SMALL);
}else if(current_target_alt < TOY_ALT_SMALL) {
wp_nav.set_desired_alt(0);
}
// clear flag
}else if (CH7_toy_flag && ((input < 1666) && (input > 1333))) {
CH7_toy_flag = false;
}
}
// called at 50 hz from all flight modes
#if TOY_EDF == ENABLED
void edf_toy()
{
// EDF control:
g.rc_8.radio_out = 1000 + ((abs(g.rc_2.control_in) << 1) / 9);
if(g.rc_8.radio_out < 1050)
g.rc_8.radio_out = 1000;
// output throttle to EDF
if(motors.armed()) {
APM_RC.OutputCh(CH_8, g.rc_8.radio_out);
}else{
APM_RC.OutputCh(CH_8, 1000);
}
// output Servo direction
if(g.rc_2.control_in > 0) {
APM_RC.OutputCh(CH_6, 1000); // 1000 : 2000
}else{
APM_RC.OutputCh(CH_6, 2000); // less than 1450
}
}
#endif
// The function call for managing the flight mode Toy
void roll_pitch_toy()
{
#if TOY_MIXER == TOY_LOOKUP_TABLE || TOY_MIXER == TOY_LINEAR_MIXER
int16_t yaw_rate = g.rc_1.control_in / g.toy_yaw_rate;
if(g.rc_1.control_in != 0) { // roll
get_acro_yaw(yaw_rate/2);
ap.yaw_stopped = false;
yaw_timer = 150;
}else if (!ap.yaw_stopped) {
get_acro_yaw(0);
yaw_timer--;
if((yaw_timer == 0) || (fabsf(omega.z) < 0.17f)) {
ap.yaw_stopped = true;
nav_yaw = ahrs.yaw_sensor;
}
}else{
if(motors.armed() == false || g.rc_3.control_in == 0)
nav_yaw = ahrs.yaw_sensor;
get_stabilize_yaw(nav_yaw);
}
#endif
// roll_rate is the outcome of the linear equation or lookup table
// based on speed and Yaw rate
int16_t roll_rate = 0;
#if TOY_MIXER == TOY_LOOKUP_TABLE
uint8_t xx, yy;
// Lookup value
//xx = g_gps->ground_speed / 200;
xx = abs(g.rc_2.control_in / 1000);
yy = abs(yaw_rate / 500);
// constrain to lookup Array range
xx = constrain_int16(xx, 0, 3);
yy = constrain_int16(yy, 0, 8);
roll_rate = toy_lookup[yy * 4 + xx];
if(yaw_rate == 0) {
roll_rate = 0;
}else if(yaw_rate < 0) {
roll_rate = -roll_rate;
}
int16_t roll_limit = 4500 / g.toy_yaw_rate;
roll_rate = constrain_int16(roll_rate, -roll_limit, roll_limit);
#elif TOY_MIXER == TOY_LINEAR_MIXER
roll_rate = -((int32_t)g.rc_2.control_in * (yaw_rate/100)) /30;
roll_rate = constrain_int32(roll_rate, -2000, 2000);
#elif TOY_MIXER == TOY_EXTERNAL_MIXER
// JKR update to allow external roll/yaw mixing
roll_rate = g.rc_1.control_in;
#endif
#if TOY_EDF == ENABLED
// Output the attitude
//g.rc_1.servo_out = get_stabilize_roll(roll_rate);
//g.rc_2.servo_out = get_stabilize_pitch(g.rc_6.control_in); // use CH6 to trim pitch
get_stabilize_roll(roll_rate);
get_stabilize_pitch(g.rc_6.control_in); // use CH6 to trim pitch
#else
// Output the attitude
//g.rc_1.servo_out = get_stabilize_roll(roll_rate);
//g.rc_2.servo_out = get_stabilize_pitch(g.rc_2.control_in);
get_stabilize_roll(roll_rate);
get_stabilize_pitch(g.rc_2.control_in);
#endif
}

View File

@ -1,6 +1,6 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- /// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
#define THISFIRMWARE "ArduPlane V2.75beta4" #define THISFIRMWARE "ArduPlane V2.76"
/* /*
Lead developer: Andrew Tridgell Lead developer: Andrew Tridgell
@ -147,11 +147,12 @@ static void print_flight_mode(AP_HAL::BetterStream *port, uint8_t mode);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#if LOGGING_ENABLED == ENABLED #if LOGGING_ENABLED == ENABLED
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 #if CONFIG_HAL_BOARD == HAL_BOARD_APM1
DataFlash_APM1 DataFlash; static DataFlash_APM1 DataFlash;
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM2 #elif CONFIG_HAL_BOARD == HAL_BOARD_APM2
DataFlash_APM2 DataFlash; static DataFlash_APM2 DataFlash;
#elif CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL #elif CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
DataFlash_SITL DataFlash; //static DataFlash_File DataFlash("logs");
static DataFlash_SITL DataFlash;
#elif CONFIG_HAL_BOARD == HAL_BOARD_PX4 #elif CONFIG_HAL_BOARD == HAL_BOARD_PX4
static DataFlash_File DataFlash("/fs/microsd/APM/logs"); static DataFlash_File DataFlash("/fs/microsd/APM/logs");
#elif CONFIG_HAL_BOARD == HAL_BOARD_LINUX #elif CONFIG_HAL_BOARD == HAL_BOARD_LINUX
@ -162,6 +163,10 @@ DataFlash_Empty DataFlash;
#endif #endif
#endif #endif
// scaled roll limit based on pitch
static int32_t roll_limit_cd;
static int32_t pitch_limit_min_cd;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Sensors // Sensors
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -258,7 +263,7 @@ AP_InertialSensor_L3G4200D ins;
#error Unrecognised CONFIG_INS_TYPE setting. #error Unrecognised CONFIG_INS_TYPE setting.
#endif // CONFIG_INS_TYPE #endif // CONFIG_INS_TYPE
AP_AHRS_DCM ahrs(&ins, g_gps); AP_AHRS_DCM ahrs(ins, g_gps);
static AP_L1_Control L1_controller(ahrs); static AP_L1_Control L1_controller(ahrs);
static AP_TECS TECS_controller(ahrs, aparm); static AP_TECS TECS_controller(ahrs, aparm);
@ -774,6 +779,9 @@ void loop()
G_Dt = delta_us_fast_loop * 1.0e-6f; G_Dt = delta_us_fast_loop * 1.0e-6f;
fast_loopTimer_us = timer; fast_loopTimer_us = timer;
if (delta_us_fast_loop > G_Dt_max)
G_Dt_max = delta_us_fast_loop;
mainLoop_count++; mainLoop_count++;
// tell the scheduler one tick has passed // tell the scheduler one tick has passed
@ -794,9 +802,6 @@ void loop()
// update AHRS system // update AHRS system
static void ahrs_update() static void ahrs_update()
{ {
if (delta_us_fast_loop > G_Dt_max)
G_Dt_max = delta_us_fast_loop;
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
// update hil before AHRS update // update hil before AHRS update
gcs_update(); gcs_update();
@ -809,6 +814,10 @@ static void ahrs_update()
if (g.log_bitmask & MASK_LOG_IMU) if (g.log_bitmask & MASK_LOG_IMU)
Log_Write_IMU(); Log_Write_IMU();
// calculate a scaled roll limit based on current pitch
roll_limit_cd = g.roll_limit_cd * cosf(ahrs.pitch);
pitch_limit_min_cd = aparm.pitch_limit_min_cd * fabsf(cosf(ahrs.roll));
} }
/* /*
@ -885,6 +894,9 @@ static void update_logging(void)
if ((g.log_bitmask & MASK_LOG_ATTITUDE_MED) && !(g.log_bitmask & MASK_LOG_ATTITUDE_FAST)) if ((g.log_bitmask & MASK_LOG_ATTITUDE_MED) && !(g.log_bitmask & MASK_LOG_ATTITUDE_FAST))
Log_Write_Attitude(); Log_Write_Attitude();
if ((g.log_bitmask & MASK_LOG_ATTITUDE_MED) && !(g.log_bitmask & MASK_LOG_IMU))
Log_Write_IMU();
if (g.log_bitmask & MASK_LOG_CTUN) if (g.log_bitmask & MASK_LOG_CTUN)
Log_Write_Control_Tuning(); Log_Write_Control_Tuning();
@ -950,9 +962,13 @@ static void one_second_loop()
static uint8_t counter; static uint8_t counter;
counter++; counter++;
if (counter == 20) { if (counter % 10 == 0) {
if (scheduler.debug() != 0) {
hal.console->printf_P(PSTR("G_Dt_max=%lu\n"), (unsigned long)G_Dt_max);
}
if (g.log_bitmask & MASK_LOG_PM) if (g.log_bitmask & MASK_LOG_PM)
Log_Write_Performance(); Log_Write_Performance();
G_Dt_max = 0;
resetPerfData(); resetPerfData();
} }
@ -976,9 +992,9 @@ static void airspeed_ratio_update(void)
// don't calibrate when not moving // don't calibrate when not moving
return; return;
} }
if (abs(ahrs.roll_sensor) > g.roll_limit_cd || if (abs(ahrs.roll_sensor) > roll_limit_cd ||
ahrs.pitch_sensor > aparm.pitch_limit_max_cd || ahrs.pitch_sensor > aparm.pitch_limit_max_cd ||
ahrs.pitch_sensor < aparm.pitch_limit_min_cd) { ahrs.pitch_sensor < pitch_limit_min_cd) {
// don't calibrate when going beyond normal flight envelope // don't calibrate when going beyond normal flight envelope
return; return;
} }
@ -1027,6 +1043,9 @@ static void update_GPS(void)
} else { } else {
init_home(); init_home();
// set system clock for log timestamps
hal.util->set_system_clock(g_gps->time_epoch_usec());
if (g.compass_enabled) { if (g.compass_enabled) {
// Set compass declination automatically // Set compass declination automatically
compass.set_initial_location(g_gps->latitude, g_gps->longitude); compass.set_initial_location(g_gps->latitude, g_gps->longitude);
@ -1157,10 +1176,10 @@ static void update_flight_mode(void)
// if the roll is past the set roll limit, then // if the roll is past the set roll limit, then
// we set target roll to the limit // we set target roll to the limit
if (ahrs.roll_sensor >= g.roll_limit_cd) { if (ahrs.roll_sensor >= roll_limit_cd) {
nav_roll_cd = g.roll_limit_cd; nav_roll_cd = roll_limit_cd;
} else if (ahrs.roll_sensor <= -g.roll_limit_cd) { } else if (ahrs.roll_sensor <= -roll_limit_cd) {
nav_roll_cd = -g.roll_limit_cd; nav_roll_cd = -roll_limit_cd;
} else { } else {
training_manual_roll = true; training_manual_roll = true;
nav_roll_cd = 0; nav_roll_cd = 0;
@ -1170,8 +1189,8 @@ static void update_flight_mode(void)
// we set target pitch to the limit // we set target pitch to the limit
if (ahrs.pitch_sensor >= aparm.pitch_limit_max_cd) { if (ahrs.pitch_sensor >= aparm.pitch_limit_max_cd) {
nav_pitch_cd = aparm.pitch_limit_max_cd; nav_pitch_cd = aparm.pitch_limit_max_cd;
} else if (ahrs.pitch_sensor <= aparm.pitch_limit_min_cd) { } else if (ahrs.pitch_sensor <= pitch_limit_min_cd) {
nav_pitch_cd = aparm.pitch_limit_min_cd; nav_pitch_cd = pitch_limit_min_cd;
} else { } else {
training_manual_pitch = true; training_manual_pitch = true;
nav_pitch_cd = 0; nav_pitch_cd = 0;
@ -1199,15 +1218,15 @@ static void update_flight_mode(void)
case FLY_BY_WIRE_A: { case FLY_BY_WIRE_A: {
// set nav_roll and nav_pitch using sticks // set nav_roll and nav_pitch using sticks
nav_roll_cd = channel_roll->norm_input() * g.roll_limit_cd; nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
nav_roll_cd = constrain_int32(nav_roll_cd, -g.roll_limit_cd, g.roll_limit_cd); nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
float pitch_input = channel_pitch->norm_input(); float pitch_input = channel_pitch->norm_input();
if (pitch_input > 0) { if (pitch_input > 0) {
nav_pitch_cd = pitch_input * aparm.pitch_limit_max_cd; nav_pitch_cd = pitch_input * aparm.pitch_limit_max_cd;
} else { } else {
nav_pitch_cd = -(pitch_input * aparm.pitch_limit_min_cd); nav_pitch_cd = -(pitch_input * pitch_limit_min_cd);
} }
nav_pitch_cd = constrain_int32(nav_pitch_cd, aparm.pitch_limit_min_cd.get(), aparm.pitch_limit_max_cd.get()); nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
if (inverted_flight) { if (inverted_flight) {
nav_pitch_cd = -nav_pitch_cd; nav_pitch_cd = -nav_pitch_cd;
} }
@ -1221,7 +1240,7 @@ static void update_flight_mode(void)
case FLY_BY_WIRE_B: case FLY_BY_WIRE_B:
// Thanks to Yury MonZon for the altitude limit code! // Thanks to Yury MonZon for the altitude limit code!
nav_roll_cd = channel_roll->norm_input() * g.roll_limit_cd; nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
update_fbwb_speed_height(); update_fbwb_speed_height();
break; break;
@ -1238,7 +1257,7 @@ static void update_flight_mode(void)
} }
if (!cruise_state.locked_heading) { if (!cruise_state.locked_heading) {
nav_roll_cd = channel_roll->norm_input() * g.roll_limit_cd; nav_roll_cd = channel_roll->norm_input() * roll_limit_cd;
} else { } else {
calc_nav_roll(); calc_nav_roll();
} }
@ -1256,7 +1275,7 @@ static void update_flight_mode(void)
// or we just want to fly around in a gentle circle w/o GPS, // or we just want to fly around in a gentle circle w/o GPS,
// holding altitude at the altitude we set when we // holding altitude at the altitude we set when we
// switched into the mode // switched into the mode
nav_roll_cd = g.roll_limit_cd / 3; nav_roll_cd = roll_limit_cd / 3;
calc_nav_pitch(); calc_nav_pitch();
calc_throttle(); calc_throttle();
break; break;
@ -1290,6 +1309,12 @@ static void update_navigation()
case LOITER: case LOITER:
case RTL: case RTL:
case GUIDED: case GUIDED:
// allow loiter direction to be changed in flight
if (g.loiter_radius < 0) {
loiter.direction = -1;
} else {
loiter.direction = 1;
}
update_loiter(); update_loiter();
break; break;

View File

@ -43,8 +43,7 @@ static bool stick_mixing_enabled(void)
if (g.stick_mixing != STICK_MIXING_DISABLED && if (g.stick_mixing != STICK_MIXING_DISABLED &&
geofence_stickmixing() && geofence_stickmixing() &&
failsafe.state == FAILSAFE_NONE && failsafe.state == FAILSAFE_NONE &&
(g.throttle_fs_enabled == 0 || !throttle_failsafe_level()) {
channel_throttle->radio_in >= g.throttle_fs_value)) {
// we're in an auto mode, and haven't triggered failsafe // we're in an auto mode, and haven't triggered failsafe
return true; return true;
} else { } else {
@ -167,8 +166,8 @@ static void stabilize_stick_mixing_fbw()
} else if (roll_input < -0.5f) { } else if (roll_input < -0.5f) {
roll_input = (3*roll_input + 1); roll_input = (3*roll_input + 1);
} }
nav_roll_cd += roll_input * g.roll_limit_cd; nav_roll_cd += roll_input * roll_limit_cd;
nav_roll_cd = constrain_int32(nav_roll_cd, -g.roll_limit_cd.get(), g.roll_limit_cd.get()); nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
float pitch_input = channel_pitch->norm_input(); float pitch_input = channel_pitch->norm_input();
if (fabsf(pitch_input) > 0.5f) { if (fabsf(pitch_input) > 0.5f) {
@ -180,9 +179,9 @@ static void stabilize_stick_mixing_fbw()
if (pitch_input > 0) { if (pitch_input > 0) {
nav_pitch_cd += pitch_input * aparm.pitch_limit_max_cd; nav_pitch_cd += pitch_input * aparm.pitch_limit_max_cd;
} else { } else {
nav_pitch_cd += -(pitch_input * aparm.pitch_limit_min_cd); nav_pitch_cd += -(pitch_input * pitch_limit_min_cd);
} }
nav_pitch_cd = constrain_int32(nav_pitch_cd, aparm.pitch_limit_min_cd.get(), aparm.pitch_limit_max_cd.get()); nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
} }
@ -441,14 +440,14 @@ static void calc_nav_pitch()
// Calculate the Pitch of the plane // Calculate the Pitch of the plane
// -------------------------------- // --------------------------------
nav_pitch_cd = SpdHgt_Controller->get_pitch_demand(); nav_pitch_cd = SpdHgt_Controller->get_pitch_demand();
nav_pitch_cd = constrain_int32(nav_pitch_cd, aparm.pitch_limit_min_cd.get(), aparm.pitch_limit_max_cd.get()); nav_pitch_cd = constrain_int32(nav_pitch_cd, pitch_limit_min_cd, aparm.pitch_limit_max_cd.get());
} }
static void calc_nav_roll() static void calc_nav_roll()
{ {
nav_roll_cd = nav_controller->nav_roll_cd(); nav_roll_cd = nav_controller->nav_roll_cd();
nav_roll_cd = constrain_int32(nav_roll_cd, -g.roll_limit_cd.get(), g.roll_limit_cd.get()); nav_roll_cd = constrain_int32(nav_roll_cd, -roll_limit_cd, roll_limit_cd);
} }

View File

@ -142,7 +142,8 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
if (g.compass_enabled) { if (g.compass_enabled) {
control_sensors_present |= MAV_SYS_STATUS_SENSOR_3D_MAG; // compass present control_sensors_present |= MAV_SYS_STATUS_SENSOR_3D_MAG; // compass present
} }
if (airspeed.enabled() && airspeed.use()) {
if (airspeed.enabled()) {
control_sensors_present |= MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE; control_sensors_present |= MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE;
} }
if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) { if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) {
@ -152,6 +153,10 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
// all present sensors enabled by default except rate control, attitude stabilization, yaw, altitude, position control and motor output which we will set individually // all present sensors enabled by default except rate control, attitude stabilization, yaw, altitude, position control and motor output which we will set individually
control_sensors_enabled = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL & ~MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION & ~MAV_SYS_STATUS_SENSOR_YAW_POSITION & ~MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL & ~MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL & ~MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS); control_sensors_enabled = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL & ~MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION & ~MAV_SYS_STATUS_SENSOR_YAW_POSITION & ~MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL & ~MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL & ~MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS);
if (airspeed.enabled() && airspeed.use()) {
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE;
}
switch (control_mode) { switch (control_mode) {
case MANUAL: case MANUAL:
break; break;
@ -197,14 +202,22 @@ static NOINLINE void send_extended_status1(mavlink_channel_t chan, uint16_t pack
break; break;
} }
// default to all healthy except compass and gps which we set individually // default to all healthy
control_sensors_health = control_sensors_present & (~MAV_SYS_STATUS_SENSOR_3D_MAG & ~MAV_SYS_STATUS_SENSOR_GPS); control_sensors_health = control_sensors_present & ~(MAV_SYS_STATUS_SENSOR_3D_MAG |
MAV_SYS_STATUS_SENSOR_GPS |
MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE);
if (g.compass_enabled && compass.healthy && ahrs.use_compass()) { if (g.compass_enabled && compass.healthy && ahrs.use_compass()) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_3D_MAG; control_sensors_health |= MAV_SYS_STATUS_SENSOR_3D_MAG;
} }
if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) { if (g_gps != NULL && g_gps->status() > GPS::NO_GPS) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS; control_sensors_health |= MAV_SYS_STATUS_SENSOR_GPS;
} }
if (!ins.healthy()) {
control_sensors_health &= ~(MAV_SYS_STATUS_SENSOR_3D_GYRO | MAV_SYS_STATUS_SENSOR_3D_ACCEL);
}
if (airspeed.healthy()) {
control_sensors_health |= MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE;
}
int16_t battery_current = -1; int16_t battery_current = -1;
int8_t battery_remaining = -1; int8_t battery_remaining = -1;
@ -279,6 +292,11 @@ static void NOINLINE send_nav_controller_output(mavlink_channel_t chan)
static void NOINLINE send_gps_raw(mavlink_channel_t chan) static void NOINLINE send_gps_raw(mavlink_channel_t chan)
{ {
static uint32_t last_send_time;
if (last_send_time != 0 && last_send_time == g_gps->last_fix_time) {
return;
}
last_send_time = g_gps->last_fix_time;
mavlink_msg_gps_raw_int_send( mavlink_msg_gps_raw_int_send(
chan, chan,
g_gps->last_fix_time*(uint64_t)1000, g_gps->last_fix_time*(uint64_t)1000,
@ -293,6 +311,14 @@ static void NOINLINE send_gps_raw(mavlink_channel_t chan)
g_gps->num_sats); g_gps->num_sats);
} }
static void NOINLINE send_system_time(mavlink_channel_t chan)
{
mavlink_msg_system_time_send(
chan,
g_gps->time_epoch_usec(),
hal.scheduler->millis());
}
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
static void NOINLINE send_servo_out(mavlink_channel_t chan) static void NOINLINE send_servo_out(mavlink_channel_t chan)
{ {
@ -574,6 +600,11 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id,
send_gps_raw(chan); send_gps_raw(chan);
break; break;
case MSG_SYSTEM_TIME:
CHECK_PAYLOAD_SIZE(SYSTEM_TIME);
send_system_time(chan);
break;
case MSG_SERVO_OUT: case MSG_SERVO_OUT:
#if HIL_MODE != HIL_MODE_DISABLED #if HIL_MODE != HIL_MODE_DISABLED
CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED); CHECK_PAYLOAD_SIZE(RC_CHANNELS_SCALED);
@ -934,7 +965,8 @@ bool GCS_MAVLINK::stream_trigger(enum streams stream_num)
// send at a much lower rate while handling waypoints and // send at a much lower rate while handling waypoints and
// parameter sends // parameter sends
if (waypoint_receiving || _queued_parameter != NULL) { if ((stream_num != STREAM_PARAMS) &&
(waypoint_receiving || _queued_parameter != NULL)) {
rate *= 0.25; rate *= 0.25;
} }
@ -1002,7 +1034,7 @@ GCS_MAVLINK::data_stream_send(void)
send_message(MSG_EXTENDED_STATUS1); send_message(MSG_EXTENDED_STATUS1);
send_message(MSG_EXTENDED_STATUS2); send_message(MSG_EXTENDED_STATUS2);
send_message(MSG_CURRENT_WAYPOINT); send_message(MSG_CURRENT_WAYPOINT);
send_message(MSG_GPS_RAW); // TODO - remove this message after location message is working send_message(MSG_GPS_RAW);
send_message(MSG_NAV_CONTROLLER_OUTPUT); send_message(MSG_NAV_CONTROLLER_OUTPUT);
send_message(MSG_FENCE_STATUS); send_message(MSG_FENCE_STATUS);
} }
@ -1046,6 +1078,7 @@ GCS_MAVLINK::data_stream_send(void)
send_message(MSG_AHRS); send_message(MSG_AHRS);
send_message(MSG_HWSTATUS); send_message(MSG_HWSTATUS);
send_message(MSG_WIND); send_message(MSG_WIND);
send_message(MSG_SYSTEM_TIME);
} }
} }
@ -1428,8 +1461,10 @@ void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
mavlink_msg_param_request_list_decode(msg, &packet); mavlink_msg_param_request_list_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break; if (mavlink_check_target(packet.target_system,packet.target_component)) break;
// Start sending parameters - next call to ::update will kick the first one out // mark the firmware version in the tlog
send_text_P(SEVERITY_LOW, PSTR(FIRMWARE_STRING));
// Start sending parameters - next call to ::update will kick the first one out
_queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type); _queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index = 0; _queued_parameter_index = 0;
_queued_parameter_count = _count_parameters(); _queued_parameter_count = _count_parameters();

View File

@ -162,9 +162,12 @@ process_logs(uint8_t argc, const Menu::arg *argv)
struct PACKED log_Attitude { struct PACKED log_Attitude {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
int16_t roll; int16_t roll;
int16_t pitch; int16_t pitch;
uint16_t yaw; uint16_t yaw;
uint16_t error_rp;
uint16_t error_yaw;
}; };
// Write an attitude packet. Total length : 10 bytes // Write an attitude packet. Total length : 10 bytes
@ -172,9 +175,12 @@ static void Log_Write_Attitude(void)
{ {
struct log_Attitude pkt = { struct log_Attitude pkt = {
LOG_PACKET_HEADER_INIT(LOG_ATTITUDE_MSG), LOG_PACKET_HEADER_INIT(LOG_ATTITUDE_MSG),
time_ms : hal.scheduler->millis(),
roll : (int16_t)ahrs.roll_sensor, roll : (int16_t)ahrs.roll_sensor,
pitch : (int16_t)ahrs.pitch_sensor, pitch : (int16_t)ahrs.pitch_sensor,
yaw : (uint16_t)ahrs.yaw_sensor yaw : (uint16_t)ahrs.yaw_sensor,
error_rp : (uint16_t)(ahrs.get_error_rp() * 100),
error_yaw : (uint16_t)(ahrs.get_error_yaw() * 100)
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
@ -186,11 +192,11 @@ struct PACKED log_Performance {
uint32_t g_dt_max; uint32_t g_dt_max;
uint8_t renorm_count; uint8_t renorm_count;
uint8_t renorm_blowup; uint8_t renorm_blowup;
uint8_t gps_fix_count;
int16_t gyro_drift_x; int16_t gyro_drift_x;
int16_t gyro_drift_y; int16_t gyro_drift_y;
int16_t gyro_drift_z; int16_t gyro_drift_z;
uint8_t i2c_lockup_count; uint8_t i2c_lockup_count;
uint16_t ins_error_count;
}; };
// Write a performance monitoring packet. Total length : 19 bytes // Write a performance monitoring packet. Total length : 19 bytes
@ -203,11 +209,11 @@ static void Log_Write_Performance()
g_dt_max : G_Dt_max, g_dt_max : G_Dt_max,
renorm_count : ahrs.renorm_range_count, renorm_count : ahrs.renorm_range_count,
renorm_blowup : ahrs.renorm_blowup_count, renorm_blowup : ahrs.renorm_blowup_count,
gps_fix_count : gps_fix_count,
gyro_drift_x : (int16_t)(ahrs.get_gyro_drift().x * 1000), gyro_drift_x : (int16_t)(ahrs.get_gyro_drift().x * 1000),
gyro_drift_y : (int16_t)(ahrs.get_gyro_drift().y * 1000), gyro_drift_y : (int16_t)(ahrs.get_gyro_drift().y * 1000),
gyro_drift_z : (int16_t)(ahrs.get_gyro_drift().z * 1000), gyro_drift_z : (int16_t)(ahrs.get_gyro_drift().z * 1000),
i2c_lockup_count: hal.i2c->lockup_count() i2c_lockup_count: hal.i2c->lockup_count(),
ins_error_count : ins.error_count()
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
@ -244,6 +250,7 @@ static void Log_Write_Cmd(uint8_t num, const struct Location *wp)
struct PACKED log_Camera { struct PACKED log_Camera {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t gps_time; uint32_t gps_time;
uint16_t gps_week;
int32_t latitude; int32_t latitude;
int32_t longitude; int32_t longitude;
int32_t altitude; int32_t altitude;
@ -258,7 +265,8 @@ static void Log_Write_Camera()
#if CAMERA == ENABLED #if CAMERA == ENABLED
struct log_Camera pkt = { struct log_Camera pkt = {
LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG), LOG_PACKET_HEADER_INIT(LOG_CAMERA_MSG),
gps_time : g_gps->time, gps_time : g_gps->time_week_ms,
gps_week : g_gps->time_week,
latitude : current_loc.lat, latitude : current_loc.lat,
longitude : current_loc.lng, longitude : current_loc.lng,
altitude : current_loc.alt, altitude : current_loc.alt,
@ -295,6 +303,7 @@ static void Log_Write_Startup(uint8_t type)
struct PACKED log_Control_Tuning { struct PACKED log_Control_Tuning {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
int16_t nav_roll_cd; int16_t nav_roll_cd;
int16_t roll; int16_t roll;
int16_t nav_pitch_cd; int16_t nav_pitch_cd;
@ -310,6 +319,7 @@ static void Log_Write_Control_Tuning()
Vector3f accel = ins.get_accel(); Vector3f accel = ins.get_accel();
struct log_Control_Tuning pkt = { struct log_Control_Tuning pkt = {
LOG_PACKET_HEADER_INIT(LOG_CTUN_MSG), LOG_PACKET_HEADER_INIT(LOG_CTUN_MSG),
time_ms : hal.scheduler->millis(),
nav_roll_cd : (int16_t)nav_roll_cd, nav_roll_cd : (int16_t)nav_roll_cd,
roll : (int16_t)ahrs.roll_sensor, roll : (int16_t)ahrs.roll_sensor,
nav_pitch_cd : (int16_t)nav_pitch_cd, nav_pitch_cd : (int16_t)nav_pitch_cd,
@ -329,31 +339,38 @@ static void Log_Write_TECS_Tuning(void)
struct PACKED log_Nav_Tuning { struct PACKED log_Nav_Tuning {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
uint16_t yaw; uint16_t yaw;
uint32_t wp_distance; uint32_t wp_distance;
uint16_t target_bearing_cd; uint16_t target_bearing_cd;
uint16_t nav_bearing_cd; uint16_t nav_bearing_cd;
int16_t altitude_error_cm; int16_t altitude_error_cm;
int16_t airspeed_cm; int16_t airspeed_cm;
float altitude;
uint32_t groundspeed_cm;
}; };
// Write a navigation tuning packet. Total length : 18 bytes // Write a navigation tuning packe
static void Log_Write_Nav_Tuning() static void Log_Write_Nav_Tuning()
{ {
struct log_Nav_Tuning pkt = { struct log_Nav_Tuning pkt = {
LOG_PACKET_HEADER_INIT(LOG_NTUN_MSG), LOG_PACKET_HEADER_INIT(LOG_NTUN_MSG),
time_ms : hal.scheduler->millis(),
yaw : (uint16_t)ahrs.yaw_sensor, yaw : (uint16_t)ahrs.yaw_sensor,
wp_distance : wp_distance, wp_distance : wp_distance,
target_bearing_cd : (uint16_t)nav_controller->target_bearing_cd(), target_bearing_cd : (uint16_t)nav_controller->target_bearing_cd(),
nav_bearing_cd : (uint16_t)nav_controller->nav_bearing_cd(), nav_bearing_cd : (uint16_t)nav_controller->nav_bearing_cd(),
altitude_error_cm : (int16_t)altitude_error_cm, altitude_error_cm : (int16_t)altitude_error_cm,
airspeed_cm : (int16_t)airspeed.get_airspeed_cm() airspeed_cm : (int16_t)airspeed.get_airspeed_cm(),
altitude : barometer.get_altitude(),
groundspeed_cm : g_gps->ground_speed_cm
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
struct PACKED log_Mode { struct PACKED log_Mode {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
uint8_t mode; uint8_t mode;
uint8_t mode_num; uint8_t mode_num;
}; };
@ -363,6 +380,7 @@ static void Log_Write_Mode(uint8_t mode)
{ {
struct log_Mode pkt = { struct log_Mode pkt = {
LOG_PACKET_HEADER_INIT(LOG_MODE_MSG), LOG_PACKET_HEADER_INIT(LOG_MODE_MSG),
time_ms : hal.scheduler->millis(),
mode : mode, mode : mode,
mode_num : mode mode_num : mode
}; };
@ -371,6 +389,7 @@ static void Log_Write_Mode(uint8_t mode)
struct PACKED log_Current { struct PACKED log_Current {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
int16_t throttle_in; int16_t throttle_in;
int16_t battery_voltage; int16_t battery_voltage;
int16_t current_amps; int16_t current_amps;
@ -382,6 +401,7 @@ static void Log_Write_Current()
{ {
struct log_Current pkt = { struct log_Current pkt = {
LOG_PACKET_HEADER_INIT(LOG_CURRENT_MSG), LOG_PACKET_HEADER_INIT(LOG_CURRENT_MSG),
time_ms : hal.scheduler->millis(),
throttle_in : channel_throttle->control_in, throttle_in : channel_throttle->control_in,
battery_voltage : (int16_t)(battery.voltage() * 100.0), battery_voltage : (int16_t)(battery.voltage() * 100.0),
current_amps : (int16_t)(battery.current_amps() * 100.0), current_amps : (int16_t)(battery.current_amps() * 100.0),
@ -394,33 +414,28 @@ static void Log_Write_Current()
struct PACKED log_Compass { struct PACKED log_Compass {
LOG_PACKET_HEADER; LOG_PACKET_HEADER;
uint32_t time_ms;
int16_t mag_x; int16_t mag_x;
int16_t mag_y; int16_t mag_y;
int16_t mag_z; int16_t mag_z;
int16_t offset_x; int16_t offset_x;
int16_t offset_y; int16_t offset_y;
int16_t offset_z; int16_t offset_z;
int16_t motor_offset_x;
int16_t motor_offset_y;
int16_t motor_offset_z;
}; };
// Write a Compass packet. Total length : 15 bytes // Write a Compass packet. Total length : 15 bytes
static void Log_Write_Compass() static void Log_Write_Compass()
{ {
Vector3f mag_offsets = compass.get_offsets(); Vector3f mag_offsets = compass.get_offsets();
Vector3f mag_motor_offsets = compass.get_motor_offsets();
struct log_Compass pkt = { struct log_Compass pkt = {
LOG_PACKET_HEADER_INIT(LOG_COMPASS_MSG), LOG_PACKET_HEADER_INIT(LOG_COMPASS_MSG),
time_ms : hal.scheduler->millis(),
mag_x : compass.mag_x, mag_x : compass.mag_x,
mag_y : compass.mag_y, mag_y : compass.mag_y,
mag_z : compass.mag_z, mag_z : compass.mag_z,
offset_x : (int16_t)mag_offsets.x, offset_x : (int16_t)mag_offsets.x,
offset_y : (int16_t)mag_offsets.y, offset_y : (int16_t)mag_offsets.y,
offset_z : (int16_t)mag_offsets.z, offset_z : (int16_t)mag_offsets.z
motor_offset_x : (int16_t)mag_motor_offsets.x,
motor_offset_y : (int16_t)mag_motor_offsets.y,
motor_offset_z : (int16_t)mag_motor_offsets.z
}; };
DataFlash.WriteBlock(&pkt, sizeof(pkt)); DataFlash.WriteBlock(&pkt, sizeof(pkt));
} }
@ -432,38 +447,38 @@ static void Log_Write_GPS(void)
static void Log_Write_IMU() static void Log_Write_IMU()
{ {
DataFlash.Log_Write_IMU(&ins); DataFlash.Log_Write_IMU(ins);
} }
static const struct LogStructure log_structure[] PROGMEM = { static const struct LogStructure log_structure[] PROGMEM = {
LOG_COMMON_STRUCTURES, LOG_COMMON_STRUCTURES,
{ LOG_ATTITUDE_MSG, sizeof(log_Attitude), { LOG_ATTITUDE_MSG, sizeof(log_Attitude),
"ATT", "ccC", "Roll,Pitch,Yaw" }, "ATT", "IccCCC", "TimeMS,Roll,Pitch,Yaw,ErrorRP,ErrorYaw" },
{ LOG_PERFORMANCE_MSG, sizeof(log_Performance), { LOG_PERFORMANCE_MSG, sizeof(log_Performance),
"PM", "IHIBBBhhhhB", "LTime,MLC,gDt,RNCnt,RNBl,GPScnt,GDx,GDy,GDz,I2CErr" }, "PM", "IHIBBhhhBH", "LTime,MLC,gDt,RNCnt,RNBl,GDx,GDy,GDz,I2CErr,INSErr" },
{ LOG_CMD_MSG, sizeof(log_Cmd), { LOG_CMD_MSG, sizeof(log_Cmd),
"CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" }, "CMD", "BBBBBeLL", "CTot,CNum,CId,COpt,Prm1,Alt,Lat,Lng" },
{ LOG_CAMERA_MSG, sizeof(log_Camera), { LOG_CAMERA_MSG, sizeof(log_Camera),
"CAM", "ILLeccC", "GPSTime,Lat,Lng,Alt,Roll,Pitch,Yaw" }, "CAM", "IHLLeccC", "GPSTime,GPSWeek,Lat,Lng,Alt,Roll,Pitch,Yaw" },
{ LOG_STARTUP_MSG, sizeof(log_Startup), { LOG_STARTUP_MSG, sizeof(log_Startup),
"STRT", "BB", "SType,CTot" }, "STRT", "BB", "SType,CTot" },
{ LOG_CTUN_MSG, sizeof(log_Control_Tuning), { LOG_CTUN_MSG, sizeof(log_Control_Tuning),
"CTUN", "cccchhf", "NavRoll,Roll,NavPitch,Pitch,ThrOut,RdrOut,AccY" }, "CTUN", "Icccchhf", "TimeMS,NavRoll,Roll,NavPitch,Pitch,ThrOut,RdrOut,AccY" },
{ LOG_NTUN_MSG, sizeof(log_Nav_Tuning), { LOG_NTUN_MSG, sizeof(log_Nav_Tuning),
"NTUN", "CICCcc", "Yaw,WpDist,TargBrg,NavBrg,AltErr,Arspd" }, "NTUN", "ICICCccfI", "TimeMS,Yaw,WpDist,TargBrg,NavBrg,AltErr,Arspd,Alt,GSpdCM" },
{ LOG_MODE_MSG, sizeof(log_Mode), { LOG_MODE_MSG, sizeof(log_Mode),
"MODE", "MB", "Mode,ModeNum" }, "MODE", "IMB", "TimeMS,Mode,ModeNum" },
{ LOG_CURRENT_MSG, sizeof(log_Current), { LOG_CURRENT_MSG, sizeof(log_Current),
"CURR", "hhhHf", "Thr,Volt,Curr,Vcc,CurrTot" }, "CURR", "IhhhHf", "TimeMS,Thr,Volt,Curr,Vcc,CurrTot" },
{ LOG_COMPASS_MSG, sizeof(log_Compass), { LOG_COMPASS_MSG, sizeof(log_Compass),
"MAG", "hhhhhhhhh", "MagX,MagY,MagZ,OfsX,OfsY,OfsZ,MOfsX,MOfsY,MOfsZ" }, "MAG", "Ihhhhhh", "TimeMS,MagX,MagY,MagZ,OfsX,OfsY,OfsZ" },
TECS_LOG_FORMAT(LOG_TECS_MSG), TECS_LOG_FORMAT(LOG_TECS_MSG),
}; };
// Read the DataFlash.log memory : Packet Parser // Read the DataFlash.log memory : Packet Parser
static void Log_Read(uint16_t log_num, int16_t start_page, int16_t end_page) static void Log_Read(uint16_t log_num, int16_t start_page, int16_t end_page)
{ {
cliSerial->printf_P(PSTR("\n" THISFIRMWARE cliSerial->printf_P(PSTR("\n" FIRMWARE_STRING
"\nFree RAM: %u\n"), "\nFree RAM: %u\n"),
(unsigned) memcheck_available_memory()); (unsigned) memcheck_available_memory());
@ -480,6 +495,7 @@ static void Log_Read(uint16_t log_num, int16_t start_page, int16_t end_page)
static void start_logging() static void start_logging()
{ {
DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure); DataFlash.StartNewLog(sizeof(log_structure)/sizeof(log_structure[0]), log_structure);
DataFlash.Log_Write_Message_P(PSTR(FIRMWARE_STRING));
} }
#else // LOGGING_ENABLED #else // LOGGING_ENABLED

View File

@ -149,8 +149,8 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: NAV_CONTROLLER // @Param: NAV_CONTROLLER
// @DisplayName: Navigation controller selection // @DisplayName: Navigation controller selection
// @Description: Which navigation controller to enable // @Description: Which navigation controller to enable. Currently the only navigation controller available is L1. From time to time other experimental conrtrollers will be added which are selected using this parameter.
// @Values: 0:Legacy,1:L1Controller // @Values: 0:Default,1:L1Controller
// @User: Standard // @User: Standard
GSCALAR(nav_controller, "NAV_CONTROLLER", AP_Navigation::CONTROLLER_L1), GSCALAR(nav_controller, "NAV_CONTROLLER", AP_Navigation::CONTROLLER_L1),
@ -165,8 +165,8 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: ALT_CTRL_ALG // @Param: ALT_CTRL_ALG
// @DisplayName: Altitude control algorithm // @DisplayName: Altitude control algorithm
// @Description: This sets what algorithm will be used for altitude control. The default is zero, which selects the most appropriate algorithm for your airframe. Currently the default is to use TECS (total energy control system). If you set it to 1 then you will get the old (deprecated) non-airspeed based algorithm. If you set it to 3 then you will get the old (deprecated) airspeed based algorithm. Setting it to 2 selects the new 'TECS' (total energy control system) altitude control, which currently is equivalent to setting 0. Note that TECS is able to handle aircraft both with and without an airspeed sensor. // @Description: This sets what algorithm will be used for altitude control. The default is zero, which selects the most appropriate algorithm for your airframe. Currently the default is to use TECS (total energy control system). From time to time we will add other experimental altitude control algorithms which will be seleted using this parameter.
// @Values: 0:Automatic,1:non-airspeed(deprecated),2:TECS,3:airspeed(deprecated) // @Values: 0:Automatic
// @User: Advanced // @User: Advanced
GSCALAR(alt_control_algorithm, "ALT_CTRL_ALG", ALT_CONTROL_DEFAULT), GSCALAR(alt_control_algorithm, "ALT_CTRL_ALG", ALT_CONTROL_DEFAULT),
@ -414,15 +414,17 @@ const AP_Param::Info var_info[] PROGMEM = {
// @Param: FS_BATT_VOLTAGE // @Param: FS_BATT_VOLTAGE
// @DisplayName: Failsafe battery voltage // @DisplayName: Failsafe battery voltage
// @Description: Battery voltage to trigger failsafe. Set to 0 to disable battery voltage failsafe. If the battery voltage drops below this voltage then the plane will RTL // @Description: Battery voltage to trigger failsafe. Set to 0 to disable battery voltage failsafe. If the battery voltage drops below this voltage continuously for 10 seconds then the plane will switch to RTL mode
// @Units: Volts // @Units: Volts
// @Increment: 0.1
// @User: Standard // @User: Standard
GSCALAR(fs_batt_voltage, "FS_BATT_VOLTAGE", 0), GSCALAR(fs_batt_voltage, "FS_BATT_VOLTAGE", 0),
// @Param: FS_BATT_MAH // @Param: FS_BATT_MAH
// @DisplayName: Failsafe battery milliAmpHours // @DisplayName: Failsafe battery milliAmpHours
// @Description: Battery capacity remaining to trigger failsafe. Set to 0 to disable battery remaining failsafe. If the battery remaining drops below this level then the plane will RTL // @Description: Battery capacity remaining to trigger failsafe. Set to 0 to disable battery remaining failsafe. If the battery remaining drops below this level then the plane will switch to RTL mode immediately
// @Units: mAh // @Units: mAh
// @Increment: 50
// @User: Standard // @User: Standard
GSCALAR(fs_batt_mah, "FS_BATT_MAH", 0), GSCALAR(fs_batt_mah, "FS_BATT_MAH", 0),

View File

@ -529,3 +529,12 @@
# define SERIAL2_BUFSIZE 256 # define SERIAL2_BUFSIZE 256
#endif #endif
/*
build a firmware version string.
GIT_VERSION comes from Makefile builds
*/
#ifndef GIT_VERSION
#define FIRMWARE_STRING THISFIRMWARE
#else
#define FIRMWARE_STRING THISFIRMWARE " (" GIT_VERSION ")"
#endif

View File

@ -130,6 +130,7 @@ enum ap_message {
MSG_RAW_IMU2, MSG_RAW_IMU2,
MSG_RAW_IMU3, MSG_RAW_IMU3,
MSG_GPS_RAW, MSG_GPS_RAW,
MSG_SYSTEM_TIME,
MSG_SERVO_OUT, MSG_SERVO_OUT,
MSG_NEXT_WAYPOINT, MSG_NEXT_WAYPOINT,
MSG_NEXT_PARAM, MSG_NEXT_PARAM,

View File

@ -129,7 +129,7 @@ static void control_failsafe(uint16_t pwm)
//Check for failsafe and debounce funky reads //Check for failsafe and debounce funky reads
} else if (g.throttle_fs_enabled) { } else if (g.throttle_fs_enabled) {
if (pwm < (unsigned)g.throttle_fs_value) { if (throttle_failsafe_level()) {
// we detect a failsafe from radio // we detect a failsafe from radio
// throttle has dropped below the mark // throttle has dropped below the mark
failsafe.ch3_counter++; failsafe.ch3_counter++;
@ -221,3 +221,17 @@ static void trim_radio()
trim_control_surfaces(); trim_control_surfaces();
} }
/*
return true if throttle level is below throttle failsafe threshold
*/
static bool throttle_failsafe_level(void)
{
if (!g.throttle_fs_enabled) {
return false;
}
if (channel_throttle->get_reverse()) {
return channel_throttle->radio_in >= g.throttle_fs_value;
}
return channel_throttle->radio_in <= g.throttle_fs_value;
}

View File

@ -82,7 +82,7 @@ static void init_ardupilot()
// standard gps running // standard gps running
hal.uartB->begin(38400, 256, 16); hal.uartB->begin(38400, 256, 16);
cliSerial->printf_P(PSTR("\n\nInit " THISFIRMWARE cliSerial->printf_P(PSTR("\n\nInit " FIRMWARE_STRING
"\n\nFree RAM: %u\n"), "\n\nFree RAM: %u\n"),
memcheck_available_memory()); memcheck_available_memory());
@ -419,15 +419,8 @@ static void startup_INS_ground(bool do_accel_init)
} }
if (style == AP_InertialSensor::COLD_START) { if (style == AP_InertialSensor::COLD_START) {
gcs_send_text_P(SEVERITY_MEDIUM, PSTR("Warming up ADC..."));
mavlink_delay(500);
// Makes the servos wiggle twice - about to begin INS calibration - HOLD LEVEL AND STILL!!
// -----------------------
demo_servos(2);
gcs_send_text_P(SEVERITY_MEDIUM, PSTR("Beginning INS calibration; do not move plane")); gcs_send_text_P(SEVERITY_MEDIUM, PSTR("Beginning INS calibration; do not move plane"));
mavlink_delay(1000); mavlink_delay(100);
} }
ahrs.init(); ahrs.init();

View File

@ -4,7 +4,7 @@ You can find lots of development information at the [ArduPilot development site]
#### To compile APM2.x Ardupilot after version 3.1 please follow the instructions found at #### To compile APM2.x Ardupilot after version 3.1 please follow the instructions found at
[Arduino Tools] (http://firmware.diydrones.com/Tools/Arduino/) [Dev.Ardupilot] (http://dev.ardupilot.com/wiki/building-ardupilot-with-arduino-windows/)
## Getting the source ## Getting the source

View File

@ -0,0 +1,5 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
// This file is just a placeholder for your configuration file. If
// you wish to change any of the setup parameters from their default
// values, place the appropriate #define statements here.

View File

@ -0,0 +1,271 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
#define THISFIRMWARE "AntennaTracker V0.1"
/*
Lead developers: Matthew Ridley and Andrew Tridgell
Please contribute your ideas! See http://dev.ardupilot.com for details
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// Header includes
////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <AP_Common.h>
#include <AP_Progmem.h>
#include <AP_HAL.h>
#include <AP_Param.h>
#include <AP_GPS.h> // ArduPilot GPS library
#include <AP_Baro.h> // ArduPilot barometer library
#include <AP_Compass.h> // ArduPilot Mega Magnetometer Library
#include <AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
#include <AP_ADC.h> // ArduPilot Mega Analog to Digital Converter Library
#include <AP_ADC_AnalogSource.h>
#include <AP_InertialSensor.h> // Inertial Sensor Library
#include <AP_AHRS.h> // ArduPilot Mega DCM Library
#include <Filter.h> // Filter library
#include <AP_Buffer.h> // APM FIFO Buffer
#include <memcheck.h>
#include <GCS_MAVLink.h> // MAVLink GCS definitions
#include <AP_Declination.h> // ArduPilot Mega Declination Helper Library
#include <DataFlash.h>
#include <SITL.h>
#include <PID.h>
#include <AP_Scheduler.h> // main loop scheduler
#include <AP_Vehicle.h>
#include <AP_Notify.h> // Notify library
#include <AP_BattMonitor.h> // Battery monitor library
#include <AP_Airspeed.h>
#include <RC_Channel.h>
// Configuration
#include "config.h"
// Local modules
#include "defines.h"
#include "Parameters.h"
#include "GCS.h"
#include <AP_HAL_AVR.h>
#include <AP_HAL_AVR_SITL.h>
#include <AP_HAL_PX4.h>
#include <AP_HAL_FLYMAPLE.h>
#include <AP_HAL_Linux.h>
#include <AP_HAL_Empty.h>
AP_HAL::BetterStream* cliSerial;
const AP_HAL::HAL& hal = AP_HAL_BOARD_DRIVER;
////////////////////////////////////////////////////////////////////////////////
// the rate we run the main loop at
////////////////////////////////////////////////////////////////////////////////
static const AP_InertialSensor::Sample_rate ins_sample_rate = AP_InertialSensor::RATE_50HZ;
////////////////////////////////////////////////////////////////////////////////
// Parameters
////////////////////////////////////////////////////////////////////////////////
//
// Global parameters are all contained within the 'g' class.
//
static Parameters g;
// main loop scheduler
static AP_Scheduler scheduler;
// notification object for LEDs, buzzers etc
static AP_Notify notify;
// tracking status for MAVLink
static struct {
float bearing;
float distance;
float pitch;
} nav_status;
////////////////////////////////////////////////////////////////////////////////
// prototypes
void gcs_send_text_fmt(const prog_char_t *fmt, ...);
////////////////////////////////////////////////////////////////////////////////
// Sensors
////////////////////////////////////////////////////////////////////////////////
// All GPS access should be through this pointer.
static GPS *g_gps;
#if CONFIG_BARO == AP_BARO_BMP085
static AP_Baro_BMP085 barometer;
#elif CONFIG_BARO == AP_BARO_PX4
static AP_Baro_PX4 barometer;
#elif CONFIG_BARO == AP_BARO_HIL
static AP_Baro_HIL barometer;
#elif CONFIG_BARO == AP_BARO_MS5611
#if CONFIG_MS5611_SERIAL == AP_BARO_MS5611_SPI
static AP_Baro_MS5611 barometer(&AP_Baro_MS5611::spi);
#elif CONFIG_MS5611_SERIAL == AP_BARO_MS5611_I2C
static AP_Baro_MS5611 barometer(&AP_Baro_MS5611::i2c);
#else
#error Unrecognized CONFIG_MS5611_SERIAL setting.
#endif
#else
#error Unrecognized CONFIG_BARO setting
#endif
#if CONFIG_COMPASS == AP_COMPASS_PX4
static AP_Compass_PX4 compass;
#elif CONFIG_COMPASS == AP_COMPASS_HMC5843
static AP_Compass_HMC5843 compass;
#elif CONFIG_COMPASS == AP_COMPASS_HIL
static AP_Compass_HIL compass;
#else
#error Unrecognized CONFIG_COMPASS setting
#endif
// GPS selection
AP_GPS_Auto g_gps_driver(&g_gps);
#if CONFIG_INS_TYPE == CONFIG_INS_MPU6000
AP_InertialSensor_MPU6000 ins;
#elif CONFIG_INS_TYPE == CONFIG_INS_PX4
AP_InertialSensor_PX4 ins;
#elif CONFIG_INS_TYPE == CONFIG_INS_HIL
AP_InertialSensor_HIL ins;
#elif CONFIG_INS_TYPE == CONFIG_INS_OILPAN
AP_InertialSensor_Oilpan ins( &apm1_adc );
#elif CONFIG_INS_TYPE == CONFIG_INS_FLYMAPLE
AP_InertialSensor_Flymaple ins;
#elif CONFIG_INS_TYPE == CONFIG_INS_L3G4200D
AP_InertialSensor_L3G4200D ins;
#else
#error Unrecognised CONFIG_INS_TYPE setting.
#endif // CONFIG_INS_TYPE
AP_AHRS_DCM ahrs(&ins, g_gps);
#if CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
SITL sitl;
#endif
/**
antenna control channels
*/
static RC_Channel channel_yaw(CH_1);
static RC_Channel channel_pitch(CH_2);
////////////////////////////////////////////////////////////////////////////////
// GCS selection
////////////////////////////////////////////////////////////////////////////////
static GCS_MAVLINK gcs0;
static GCS_MAVLINK gcs3;
/*
scheduler table - all regular tasks apart from the fast_loop()
should be listed here, along with how often they should be called
(in 20ms units) and the maximum time they are expected to take (in
microseconds)
*/
static const AP_Scheduler::Task scheduler_tasks[] PROGMEM = {
{ update_ahrs, 1, 1000 },
{ update_tracking, 1, 1000 },
{ update_GPS, 5, 4000 },
{ update_compass, 5, 1500 },
{ update_barometer, 5, 1500 },
{ update_tracking, 1, 1000 },
{ gcs_update, 1, 1700 },
{ gcs_data_stream_send, 1, 3000 },
{ compass_accumulate, 1, 1500 },
{ barometer_accumulate, 1, 900 },
{ update_notify, 1, 100 },
{ one_second_loop, 50, 3900 }
};
// setup the var_info table
AP_Param param_loader(var_info, EEPROM_MAX_ADDR);
/**
setup the sketch - called once on startup
*/
void setup()
{
// this needs to be the first call, as it fills memory with
// sentinel values
memcheck_init();
cliSerial = hal.console;
// load the default values of variables listed in var_info[]
AP_Param::setup_sketch_defaults();
// arduplane does not use arming nor pre-arm checks
AP_Notify::flags.armed = true;
AP_Notify::flags.pre_arm_check = true;
AP_Notify::flags.failsafe_battery = false;
notify.init();
init_tracker();
// initialise the main loop scheduler
scheduler.init(&scheduler_tasks[0], sizeof(scheduler_tasks)/sizeof(scheduler_tasks[0]));
}
/**
loop() is called continuously
*/
void loop()
{
// wait for an INS sample
if (!ins.wait_for_sample(1000)) {
return;
}
// tell the scheduler one tick has passed
scheduler.tick();
scheduler.run(19900UL);
}
static void one_second_loop()
{
// send a heartbeat
gcs_send_message(MSG_HEARTBEAT);
// make it possible to change orientation at runtime
ahrs.set_orientation();
// sync MAVLink system ID
mavlink_system.sysid = g.sysid_this_mav;
static uint8_t counter;
counter++;
if (counter >= 60) {
if(g.compass_enabled) {
compass.save_offsets();
}
counter = 0;
}
}
AP_HAL_MAIN();

187
Tools/AntennaTracker/GCS.h Normal file
View File

@ -0,0 +1,187 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/// @file GCS.h
/// @brief Interface definition for the various Ground Control System
// protocols.
#ifndef __GCS_H
#define __GCS_H
#include <AP_HAL.h>
#include <AP_Common.h>
#include <GPS.h>
#include <stdint.h>
///
/// @class GCS
/// @brief Class describing the interface between the APM code
/// proper and the GCS implementation.
///
/// GCS' are currently implemented inside the sketch and as such have
/// access to all global state. The sketch should not, however, call GCS
/// internal functions - all calls to the GCS should be routed through
/// this interface (or functions explicitly exposed by a subclass).
///
class GCS_Class
{
public:
/// Startup initialisation.
///
/// This routine performs any one-off initialisation required before
/// GCS messages are exchanged.
///
/// @note The stream is expected to be set up and configured for the
/// correct bitrate before ::init is called.
///
/// @note The stream is currently BetterStream so that we can use the _P
/// methods; this may change if Arduino adds them to Print.
///
/// @param port The stream over which messages are exchanged.
///
void init(AP_HAL::UARTDriver *port) {
_port = port;
initialised = true;
}
/// Update GCS state.
///
/// This may involve checking for received bytes on the stream,
/// or sending additional periodic messages.
void update(void) {
}
/// Send a message with a single numeric parameter.
///
/// This may be a standalone message, or the GCS driver may
/// have its own way of locating additional parameters to send.
///
/// @param id ID of the message to send.
/// @param param Explicit message parameter.
///
void send_message(enum ap_message id) {
}
/// Send a text message.
///
/// @param severity A value describing the importance of the message.
/// @param str The text to be sent.
///
void send_text(gcs_severity severity, const char *str) {
}
/// Send a text message with a PSTR()
///
/// @param severity A value describing the importance of the message.
/// @param str The text to be sent.
///
void send_text_P(gcs_severity severity, const prog_char_t *str) {
}
// send streams which match frequency range
void data_stream_send(void);
// set to true if this GCS link is active
bool initialised;
protected:
/// The stream we are communicating over
AP_HAL::UARTDriver *_port;
};
//
// GCS class definitions.
//
// These are here so that we can declare the GCS object early in the sketch
// and then reference it statically rather than via a pointer.
//
///
/// @class GCS_MAVLINK
/// @brief The mavlink protocol for qgroundcontrol
///
class GCS_MAVLINK : public GCS_Class
{
public:
GCS_MAVLINK();
void update(void);
void init(AP_HAL::UARTDriver *port);
void send_message(enum ap_message id);
void send_text(gcs_severity severity, const char *str);
void send_text_P(gcs_severity severity, const prog_char_t *str);
void data_stream_send(void);
void queued_param_send();
static const struct AP_Param::GroupInfo var_info[];
// NOTE! The streams enum below and the
// set of AP_Int16 stream rates _must_ be
// kept in the same order
enum streams {STREAM_RAW_SENSORS,
STREAM_EXTENDED_STATUS,
STREAM_RC_CHANNELS,
STREAM_RAW_CONTROLLER,
STREAM_POSITION,
STREAM_EXTRA1,
STREAM_EXTRA2,
STREAM_EXTRA3,
STREAM_PARAMS,
NUM_STREAMS};
// see if we should send a stream now. Called at 50Hz
bool stream_trigger(enum streams stream_num);
// this costs us 51 bytes per instance, but means that low priority
// messages don't block the CPU
mavlink_statustext_t pending_status;
// call to reset the timeout window for entering the cli
void reset_cli_timeout();
private:
void handleMessage(mavlink_message_t * msg);
/// Perform queued sending operations
///
AP_Param * _queued_parameter; ///< next parameter to
// be sent in queue
enum ap_var_type _queued_parameter_type; ///< type of the next
// parameter
AP_Param::ParamToken _queued_parameter_token; ///AP_Param token for
// next() call
uint16_t _queued_parameter_index; ///< next queued
// parameter's index
uint16_t _queued_parameter_count; ///< saved count of
// parameters for
// queued send
uint32_t _queued_parameter_send_time_ms;
/// Count the number of reportable parameters.
///
/// Not all parameters can be reported via MAVlink. We count the number
// that are
/// so that we can report to a GCS the number of parameters it should
// expect when it
/// requests the full set.
///
/// @return The number of reportable parameters.
///
uint16_t _count_parameters(); ///< count reportable
// parameters
uint16_t _parameter_count; ///< cache of reportable
// parameters
mavlink_channel_t chan;
uint16_t packet_drops;
// saveable rate of each stream
AP_Int16 streamRates[NUM_STREAMS];
// number of 50Hz ticks until we next send this stream
uint8_t stream_ticks[NUM_STREAMS];
// number of extra ticks to add to slow things down for the radio
uint8_t stream_slowdown;
};
#endif // __GCS_H

View File

@ -0,0 +1,981 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
// default sensors are present and healthy: gyro, accelerometer, barometer, rate_control, attitude_stabilization, yaw_position, altitude control, x/y position control, motor_control
#define MAVLINK_SENSOR_PRESENT_DEFAULT (MAV_SYS_STATUS_SENSOR_3D_GYRO | MAV_SYS_STATUS_SENSOR_3D_ACCEL | MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE | MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL | MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION | MAV_SYS_STATUS_SENSOR_YAW_POSITION | MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL | MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL | MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS)
// use this to prevent recursion during sensor init
static bool in_mavlink_delay;
// true when we have received at least 1 MAVLink packet
static bool mavlink_active;
// check if a message will fit in the payload space available
#define CHECK_PAYLOAD_SIZE(id) if (payload_space < MAVLINK_MSG_ID_ ## id ## _LEN) return false
/*
* !!NOTE!!
*
* the use of NOINLINE separate functions for each message type avoids
* a compiler bug in gcc that would cause it to use far more stack
* space than is needed. Without the NOINLINE we use the sum of the
* stack needed for each message type. Please be careful to follow the
* pattern below when adding any new messages
*/
static NOINLINE void send_heartbeat(mavlink_channel_t chan)
{
mavlink_msg_heartbeat_send(
chan,
MAV_TYPE_ANTENNA_TRACKER,
MAV_AUTOPILOT_ARDUPILOTMEGA,
0,
0,
0);
}
static NOINLINE void send_attitude(mavlink_channel_t chan)
{
Vector3f omega = ahrs.get_gyro();
mavlink_msg_attitude_send(
chan,
hal.scheduler->millis(),
ahrs.roll,
ahrs.pitch,
ahrs.yaw,
omega.x,
omega.y,
omega.z);
}
static void NOINLINE send_location(mavlink_channel_t chan)
{
uint32_t fix_time;
if (g_gps->status() >= GPS::GPS_OK_FIX_2D) {
fix_time = g_gps->last_fix_time;
} else {
fix_time = hal.scheduler->millis();
}
Location loc;
ahrs.get_position(loc);
mavlink_msg_global_position_int_send(
chan,
fix_time,
loc.lat, // in 1E7 degrees
loc.lng, // in 1E7 degrees
g_gps->altitude_cm * 10, // millimeters above sea level
0,
g_gps->velocity_north() * 100, // X speed cm/s (+ve North)
g_gps->velocity_east() * 100, // Y speed cm/s (+ve East)
g_gps->velocity_down() * -100, // Z speed cm/s (+ve up)
ahrs.yaw_sensor);
}
static void NOINLINE send_gps_raw(mavlink_channel_t chan)
{
mavlink_msg_gps_raw_int_send(
chan,
g_gps->last_fix_time*(uint64_t)1000,
g_gps->status(),
g_gps->latitude, // in 1E7 degrees
g_gps->longitude, // in 1E7 degrees
g_gps->altitude_cm * 10, // in mm
g_gps->hdop,
65535,
g_gps->ground_speed_cm, // cm/s
g_gps->ground_course_cd, // 1/100 degrees,
g_gps->num_sats);
}
static void NOINLINE send_radio_out(mavlink_channel_t chan)
{
mavlink_msg_servo_output_raw_send(
chan,
hal.scheduler->micros(),
0, // port
hal.rcout->read(0),
hal.rcout->read(1),
hal.rcout->read(2),
hal.rcout->read(3),
hal.rcout->read(4),
hal.rcout->read(5),
hal.rcout->read(6),
hal.rcout->read(7));
}
static void NOINLINE send_raw_imu1(mavlink_channel_t chan)
{
Vector3f accel = ins.get_accel();
Vector3f gyro = ins.get_gyro();
mavlink_msg_raw_imu_send(
chan,
hal.scheduler->micros(),
accel.x * 1000.0 / GRAVITY_MSS,
accel.y * 1000.0 / GRAVITY_MSS,
accel.z * 1000.0 / GRAVITY_MSS,
gyro.x * 1000.0,
gyro.y * 1000.0,
gyro.z * 1000.0,
compass.mag_x,
compass.mag_y,
compass.mag_z);
}
static void NOINLINE send_raw_imu2(mavlink_channel_t chan)
{
float pressure = barometer.get_pressure();
mavlink_msg_scaled_pressure_send(
chan,
hal.scheduler->millis(),
pressure*0.01f, // hectopascal
(pressure - barometer.get_ground_pressure())*0.01f, // hectopascal
barometer.get_temperature()*100); // 0.01 degrees C
}
static void NOINLINE send_raw_imu3(mavlink_channel_t chan)
{
// run this message at a much lower rate - otherwise it
// pointlessly wastes quite a lot of bandwidth
static uint8_t counter;
if (counter++ < 10) {
return;
}
counter = 0;
Vector3f mag_offsets = compass.get_offsets();
Vector3f accel_offsets = ins.get_accel_offsets();
Vector3f gyro_offsets = ins.get_gyro_offsets();
mavlink_msg_sensor_offsets_send(chan,
mag_offsets.x,
mag_offsets.y,
mag_offsets.z,
compass.get_declination(),
barometer.get_pressure(),
barometer.get_temperature()*100,
gyro_offsets.x,
gyro_offsets.y,
gyro_offsets.z,
accel_offsets.x,
accel_offsets.y,
accel_offsets.z);
}
static void NOINLINE send_ahrs(mavlink_channel_t chan)
{
Vector3f omega_I = ahrs.get_gyro_drift();
mavlink_msg_ahrs_send(
chan,
omega_I.x,
omega_I.y,
omega_I.z,
0,
0,
ahrs.get_error_rp(),
ahrs.get_error_yaw());
}
static void NOINLINE send_hwstatus(mavlink_channel_t chan)
{
mavlink_msg_hwstatus_send(
chan,
0,
hal.i2c->lockup_count());
}
static void NOINLINE send_statustext(mavlink_channel_t chan)
{
mavlink_statustext_t *s = (chan == MAVLINK_COMM_0?&gcs0.pending_status:&gcs3.pending_status);
mavlink_msg_statustext_send(
chan,
s->severity,
s->text);
}
static void NOINLINE send_nav_controller_output(mavlink_channel_t chan)
{
mavlink_msg_nav_controller_output_send(
chan,
0,
nav_status.pitch,
nav_status.bearing,
nav_status.bearing,
nav_status.distance,
0,
0,
0);
}
// try to send a message, return false if it won't fit in the serial tx buffer
static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id, uint16_t packet_drops)
{
int16_t payload_space = comm_get_txspace(chan) - MAVLINK_NUM_NON_PAYLOAD_BYTES;
switch (id) {
case MSG_HEARTBEAT:
CHECK_PAYLOAD_SIZE(HEARTBEAT);
send_heartbeat(chan);
return true;
case MSG_ATTITUDE:
CHECK_PAYLOAD_SIZE(ATTITUDE);
send_attitude(chan);
break;
case MSG_LOCATION:
CHECK_PAYLOAD_SIZE(GLOBAL_POSITION_INT);
send_location(chan);
break;
case MSG_NAV_CONTROLLER_OUTPUT:
CHECK_PAYLOAD_SIZE(NAV_CONTROLLER_OUTPUT);
send_nav_controller_output(chan);
break;
case MSG_GPS_RAW:
CHECK_PAYLOAD_SIZE(GPS_RAW_INT);
send_gps_raw(chan);
break;
case MSG_RADIO_OUT:
CHECK_PAYLOAD_SIZE(SERVO_OUTPUT_RAW);
send_radio_out(chan);
break;
case MSG_RAW_IMU1:
CHECK_PAYLOAD_SIZE(RAW_IMU);
send_raw_imu1(chan);
break;
case MSG_RAW_IMU2:
CHECK_PAYLOAD_SIZE(SCALED_PRESSURE);
send_raw_imu2(chan);
break;
case MSG_RAW_IMU3:
CHECK_PAYLOAD_SIZE(SENSOR_OFFSETS);
send_raw_imu3(chan);
break;
case MSG_NEXT_PARAM:
CHECK_PAYLOAD_SIZE(PARAM_VALUE);
if (chan == MAVLINK_COMM_0) {
gcs0.queued_param_send();
} else if (gcs3.initialised) {
gcs3.queued_param_send();
}
break;
case MSG_STATUSTEXT:
CHECK_PAYLOAD_SIZE(STATUSTEXT);
send_statustext(chan);
break;
case MSG_AHRS:
CHECK_PAYLOAD_SIZE(AHRS);
send_ahrs(chan);
break;
case MSG_HWSTATUS:
CHECK_PAYLOAD_SIZE(HWSTATUS);
send_hwstatus(chan);
break;
case MSG_SERVO_OUT:
case MSG_EXTENDED_STATUS1:
case MSG_EXTENDED_STATUS2:
case MSG_RETRY_DEFERRED:
break; // just here to prevent a warning
}
return true;
}
#define MAX_DEFERRED_MESSAGES MSG_RETRY_DEFERRED
static struct mavlink_queue {
enum ap_message deferred_messages[MAX_DEFERRED_MESSAGES];
uint8_t next_deferred_message;
uint8_t num_deferred_messages;
} mavlink_queue[2];
// send a message using mavlink
static void mavlink_send_message(mavlink_channel_t chan, enum ap_message id, uint16_t packet_drops)
{
uint8_t i, nextid;
struct mavlink_queue *q = &mavlink_queue[(uint8_t)chan];
// see if we can send the deferred messages, if any
while (q->num_deferred_messages != 0) {
if (!mavlink_try_send_message(chan,
q->deferred_messages[q->next_deferred_message],
packet_drops)) {
break;
}
q->next_deferred_message++;
if (q->next_deferred_message == MAX_DEFERRED_MESSAGES) {
q->next_deferred_message = 0;
}
q->num_deferred_messages--;
}
if (id == MSG_RETRY_DEFERRED) {
return;
}
// this message id might already be deferred
for (i=0, nextid = q->next_deferred_message; i < q->num_deferred_messages; i++) {
if (q->deferred_messages[nextid] == id) {
// its already deferred, discard
return;
}
nextid++;
if (nextid == MAX_DEFERRED_MESSAGES) {
nextid = 0;
}
}
if (q->num_deferred_messages != 0 ||
!mavlink_try_send_message(chan, id, packet_drops)) {
// can't send it now, so defer it
if (q->num_deferred_messages == MAX_DEFERRED_MESSAGES) {
// the defer buffer is full, discard
return;
}
nextid = q->next_deferred_message + q->num_deferred_messages;
if (nextid >= MAX_DEFERRED_MESSAGES) {
nextid -= MAX_DEFERRED_MESSAGES;
}
q->deferred_messages[nextid] = id;
q->num_deferred_messages++;
}
}
void mavlink_send_text(mavlink_channel_t chan, gcs_severity severity, const char *str)
{
if (severity == SEVERITY_LOW) {
// send via the deferred queuing system
mavlink_statustext_t *s = (chan == MAVLINK_COMM_0?&gcs0.pending_status:&gcs3.pending_status);
s->severity = (uint8_t)severity;
strncpy((char *)s->text, str, sizeof(s->text));
mavlink_send_message(chan, MSG_STATUSTEXT, 0);
} else {
// send immediately
mavlink_msg_statustext_send(chan, severity, str);
}
}
/*
default stream rates to 1Hz
*/
const AP_Param::GroupInfo GCS_MAVLINK::var_info[] PROGMEM = {
// @Param: RAW_SENS
// @DisplayName: Raw sensor stream rate
// @Description: Raw sensor stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("RAW_SENS", 0, GCS_MAVLINK, streamRates[0], 1),
// @Param: EXT_STAT
// @DisplayName: Extended status stream rate to ground station
// @Description: Extended status stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("EXT_STAT", 1, GCS_MAVLINK, streamRates[1], 1),
// @Param: RC_CHAN
// @DisplayName: RC Channel stream rate to ground station
// @Description: RC Channel stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("RC_CHAN", 2, GCS_MAVLINK, streamRates[2], 1),
// @Param: RAW_CTRL
// @DisplayName: Raw Control stream rate to ground station
// @Description: Raw Control stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("RAW_CTRL", 3, GCS_MAVLINK, streamRates[3], 1),
// @Param: POSITION
// @DisplayName: Position stream rate to ground station
// @Description: Position stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("POSITION", 4, GCS_MAVLINK, streamRates[4], 1),
// @Param: EXTRA1
// @DisplayName: Extra data type 1 stream rate to ground station
// @Description: Extra data type 1 stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("EXTRA1", 5, GCS_MAVLINK, streamRates[5], 1),
// @Param: EXTRA2
// @DisplayName: Extra data type 2 stream rate to ground station
// @Description: Extra data type 2 stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("EXTRA2", 6, GCS_MAVLINK, streamRates[6], 1),
// @Param: EXTRA3
// @DisplayName: Extra data type 3 stream rate to ground station
// @Description: Extra data type 3 stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("EXTRA3", 7, GCS_MAVLINK, streamRates[7], 1),
// @Param: PARAMS
// @DisplayName: Parameter stream rate to ground station
// @Description: Parameter stream rate to ground station
// @Units: Hz
// @Range: 0 10
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("PARAMS", 8, GCS_MAVLINK, streamRates[8], 10),
AP_GROUPEND
};
GCS_MAVLINK::GCS_MAVLINK() :
packet_drops(0)
{
AP_Param::setup_object_defaults(this, var_info);
}
void
GCS_MAVLINK::init(AP_HAL::UARTDriver *port)
{
GCS_Class::init(port);
if (port == (AP_HAL::BetterStream*)hal.uartA) {
mavlink_comm_0_port = port;
chan = MAVLINK_COMM_0;
}else{
mavlink_comm_1_port = port;
chan = MAVLINK_COMM_1;
}
_queued_parameter = NULL;
}
void
GCS_MAVLINK::update(void)
{
// receive new packets
mavlink_message_t msg;
mavlink_status_t status;
status.packet_rx_drop_count = 0;
// process received bytes
uint16_t nbytes = comm_get_available(chan);
for (uint16_t i=0; i<nbytes; i++)
{
uint8_t c = comm_receive_ch(chan);
// Try to get a new message
if (mavlink_parse_char(chan, c, &msg, &status)) {
// we exclude radio packets to make it possible to use the
// CLI over the radio
if (msg.msgid != MAVLINK_MSG_ID_RADIO && msg.msgid != MAVLINK_MSG_ID_RADIO_STATUS) {
mavlink_active = true;
}
handleMessage(&msg);
}
}
// Update packet drops counter
packet_drops += status.packet_rx_drop_count;
}
// see if we should send a stream now. Called at 50Hz
bool GCS_MAVLINK::stream_trigger(enum streams stream_num)
{
if (stream_num >= NUM_STREAMS) {
return false;
}
float rate = (uint8_t)streamRates[stream_num].get();
// send at a much lower rate during parameter sends
if (_queued_parameter != NULL) {
rate *= 0.25;
}
if (rate <= 0) {
return false;
}
if (stream_ticks[stream_num] == 0) {
// we're triggering now, setup the next trigger point
if (rate > 50) {
rate = 50;
}
stream_ticks[stream_num] = (50 / rate) + stream_slowdown;
return true;
}
// count down at 50Hz
stream_ticks[stream_num]--;
return false;
}
void
GCS_MAVLINK::data_stream_send(void)
{
if (_queued_parameter != NULL) {
if (streamRates[STREAM_PARAMS].get() <= 0) {
streamRates[STREAM_PARAMS].set(10);
}
if (stream_trigger(STREAM_PARAMS)) {
send_message(MSG_NEXT_PARAM);
}
}
if (in_mavlink_delay) {
// don't send any other stream types while in the delay callback
return;
}
if (stream_trigger(STREAM_RAW_SENSORS)) {
send_message(MSG_RAW_IMU1);
send_message(MSG_RAW_IMU2);
send_message(MSG_RAW_IMU3);
}
if (stream_trigger(STREAM_EXTENDED_STATUS)) {
send_message(MSG_EXTENDED_STATUS1);
send_message(MSG_EXTENDED_STATUS2);
send_message(MSG_NAV_CONTROLLER_OUTPUT);
send_message(MSG_GPS_RAW);
}
if (stream_trigger(STREAM_POSITION)) {
send_message(MSG_LOCATION);
}
if (stream_trigger(STREAM_RAW_CONTROLLER)) {
send_message(MSG_SERVO_OUT);
}
if (stream_trigger(STREAM_RC_CHANNELS)) {
send_message(MSG_RADIO_OUT);
}
if (stream_trigger(STREAM_EXTRA1)) {
send_message(MSG_ATTITUDE);
}
if (stream_trigger(STREAM_EXTRA3)) {
send_message(MSG_AHRS);
send_message(MSG_HWSTATUS);
}
}
void
GCS_MAVLINK::send_message(enum ap_message id)
{
mavlink_send_message(chan,id, packet_drops);
}
void
GCS_MAVLINK::send_text_P(gcs_severity severity, const prog_char_t *str)
{
mavlink_statustext_t m;
uint8_t i;
for (i=0; i<sizeof(m.text); i++) {
m.text[i] = pgm_read_byte((const prog_char *)(str++));
if (m.text[i] == '\0') {
break;
}
}
if (i < sizeof(m.text)) m.text[i] = 0;
mavlink_send_text(chan, severity, (const char *)m.text);
}
void GCS_MAVLINK::handleMessage(mavlink_message_t* msg)
{
switch (msg->msgid) {
case MAVLINK_MSG_ID_REQUEST_DATA_STREAM:
{
// decode
mavlink_request_data_stream_t packet;
mavlink_msg_request_data_stream_decode(msg, &packet);
if (mavlink_check_target(packet.target_system, packet.target_component))
break;
int16_t freq = 0; // packet frequency
if (packet.start_stop == 0)
freq = 0; // stop sending
else if (packet.start_stop == 1)
freq = packet.req_message_rate; // start sending
else
break;
switch (packet.req_stream_id) {
case MAV_DATA_STREAM_ALL:
// note that we don't set STREAM_PARAMS - that is internal only
for (uint8_t i=0; i<STREAM_PARAMS; i++) {
streamRates[i].set_and_save_ifchanged(freq);
}
break;
case MAV_DATA_STREAM_RAW_SENSORS:
streamRates[STREAM_RAW_SENSORS].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_EXTENDED_STATUS:
streamRates[STREAM_EXTENDED_STATUS].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_RC_CHANNELS:
streamRates[STREAM_RC_CHANNELS].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_RAW_CONTROLLER:
streamRates[STREAM_RAW_CONTROLLER].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_POSITION:
streamRates[STREAM_POSITION].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_EXTRA1:
streamRates[STREAM_EXTRA1].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_EXTRA2:
streamRates[STREAM_EXTRA2].set_and_save_ifchanged(freq);
break;
case MAV_DATA_STREAM_EXTRA3:
streamRates[STREAM_EXTRA3].set_and_save_ifchanged(freq);
break;
}
break;
}
case MAVLINK_MSG_ID_PARAM_REQUEST_LIST:
{
// decode
mavlink_param_request_list_t packet;
mavlink_msg_param_request_list_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break;
// Start sending parameters - next call to ::update will kick the first one out
_queued_parameter = AP_Param::first(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index = 0;
_queued_parameter_count = _count_parameters();
break;
}
case MAVLINK_MSG_ID_PARAM_REQUEST_READ:
{
// decode
mavlink_param_request_read_t packet;
mavlink_msg_param_request_read_decode(msg, &packet);
if (mavlink_check_target(packet.target_system,packet.target_component)) break;
enum ap_var_type p_type;
AP_Param *vp;
char param_name[AP_MAX_NAME_SIZE+1];
if (packet.param_index != -1) {
AP_Param::ParamToken token;
vp = AP_Param::find_by_index(packet.param_index, &p_type, &token);
if (vp == NULL) {
gcs_send_text_fmt(PSTR("Unknown parameter index %d"), packet.param_index);
break;
}
vp->copy_name_token(token, param_name, AP_MAX_NAME_SIZE, true);
param_name[AP_MAX_NAME_SIZE] = 0;
} else {
strncpy(param_name, packet.param_id, AP_MAX_NAME_SIZE);
param_name[AP_MAX_NAME_SIZE] = 0;
vp = AP_Param::find(param_name, &p_type);
if (vp == NULL) {
gcs_send_text_fmt(PSTR("Unknown parameter %.16s"), packet.param_id);
break;
}
}
float value = vp->cast_to_float(p_type);
mavlink_msg_param_value_send(
chan,
param_name,
value,
mav_var_type(p_type),
_count_parameters(),
packet.param_index);
break;
}
case MAVLINK_MSG_ID_PARAM_SET:
{
AP_Param *vp;
enum ap_var_type var_type;
// decode
mavlink_param_set_t packet;
mavlink_msg_param_set_decode(msg, &packet);
if (mavlink_check_target(packet.target_system, packet.target_component))
break;
// set parameter
char key[AP_MAX_NAME_SIZE+1];
strncpy(key, (char *)packet.param_id, AP_MAX_NAME_SIZE);
key[AP_MAX_NAME_SIZE] = 0;
// find the requested parameter
vp = AP_Param::find(key, &var_type);
if ((NULL != vp) && // exists
!isnan(packet.param_value) && // not nan
!isinf(packet.param_value)) { // not inf
// add a small amount before casting parameter values
// from float to integer to avoid truncating to the
// next lower integer value.
float rounding_addition = 0.01;
// handle variables with standard type IDs
if (var_type == AP_PARAM_FLOAT) {
((AP_Float *)vp)->set_and_save(packet.param_value);
} else if (var_type == AP_PARAM_INT32) {
if (packet.param_value < 0) rounding_addition = -rounding_addition;
float v = packet.param_value+rounding_addition;
v = constrain_float(v, -2147483648.0, 2147483647.0);
((AP_Int32 *)vp)->set_and_save(v);
} else if (var_type == AP_PARAM_INT16) {
if (packet.param_value < 0) rounding_addition = -rounding_addition;
float v = packet.param_value+rounding_addition;
v = constrain_float(v, -32768, 32767);
((AP_Int16 *)vp)->set_and_save(v);
} else if (var_type == AP_PARAM_INT8) {
if (packet.param_value < 0) rounding_addition = -rounding_addition;
float v = packet.param_value+rounding_addition;
v = constrain_float(v, -128, 127);
((AP_Int8 *)vp)->set_and_save(v);
} else {
// we don't support mavlink set on this parameter
break;
}
// Report back the new value if we accepted the change
// we send the value we actually set, which could be
// different from the value sent, in case someone sent
// a fractional value to an integer type
mavlink_msg_param_value_send(
chan,
key,
vp->cast_to_float(var_type),
mav_var_type(var_type),
_count_parameters(),
-1); // XXX we don't actually know what its index is...
#if LOGGING_ENABLED == ENABLED
DataFlash.Log_Write_Parameter(key, vp->cast_to_float(var_type));
#endif
}
break;
} // end case
case MAVLINK_MSG_ID_HEARTBEAT:
{
if (msg->sysid != g.sysid_my_gcs) break;
break;
}
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT: {
// decode
mavlink_global_position_int_t packet;
mavlink_msg_global_position_int_decode(msg, &packet);
tracking_update_position(packet);
break;
}
default:
break;
} // end switch
} // end handle mavlink
uint16_t
GCS_MAVLINK::_count_parameters()
{
// if we haven't cached the parameter count yet...
if (0 == _parameter_count) {
AP_Param *vp;
AP_Param::ParamToken token;
vp = AP_Param::first(&token, NULL);
do {
_parameter_count++;
} while (NULL != (vp = AP_Param::next_scalar(&token, NULL)));
}
return _parameter_count;
}
/**
* @brief Send the next pending parameter, called from deferred message
* handling code
*/
void
GCS_MAVLINK::queued_param_send()
{
if (_queued_parameter == NULL) {
return;
}
uint16_t bytes_allowed;
uint8_t count;
uint32_t tnow = hal.scheduler->millis();
// use at most 30% of bandwidth on parameters. The constant 26 is
// 1/(1000 * 1/8 * 0.001 * 0.3)
bytes_allowed = g.serial3_baud * (tnow - _queued_parameter_send_time_ms) * 26;
if (bytes_allowed > comm_get_txspace(chan)) {
bytes_allowed = comm_get_txspace(chan);
}
count = bytes_allowed / (MAVLINK_MSG_ID_PARAM_VALUE_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES);
while (_queued_parameter != NULL && count--) {
AP_Param *vp;
float value;
// copy the current parameter and prepare to move to the next
vp = _queued_parameter;
// if the parameter can be cast to float, report it here and break out of the loop
value = vp->cast_to_float(_queued_parameter_type);
char param_name[AP_MAX_NAME_SIZE];
vp->copy_name_token(_queued_parameter_token, param_name, sizeof(param_name), true);
mavlink_msg_param_value_send(
chan,
param_name,
value,
mav_var_type(_queued_parameter_type),
_queued_parameter_count,
_queued_parameter_index);
_queued_parameter = AP_Param::next_scalar(&_queued_parameter_token, &_queued_parameter_type);
_queued_parameter_index++;
}
_queued_parameter_send_time_ms = tnow;
}
/*
* a delay() callback that processes MAVLink packets. We set this as the
* callback in long running library initialisation routines to allow
* MAVLink to process packets while waiting for the initialisation to
* complete
*/
static void mavlink_delay_cb()
{
static uint32_t last_1hz, last_50hz, last_5s;
if (!gcs0.initialised) return;
in_mavlink_delay = true;
uint32_t tnow = hal.scheduler->millis();
if (tnow - last_1hz > 1000) {
last_1hz = tnow;
gcs_send_message(MSG_HEARTBEAT);
gcs_send_message(MSG_EXTENDED_STATUS1);
}
if (tnow - last_50hz > 20) {
last_50hz = tnow;
gcs_update();
gcs_data_stream_send();
notify.update();
}
if (tnow - last_5s > 5000) {
last_5s = tnow;
gcs_send_text_P(SEVERITY_LOW, PSTR("Initialising APM..."));
}
in_mavlink_delay = false;
}
/*
* send a message on both GCS links
*/
static void gcs_send_message(enum ap_message id)
{
gcs0.send_message(id);
if (gcs3.initialised) {
gcs3.send_message(id);
}
}
/*
* send data streams in the given rate range on both links
*/
static void gcs_data_stream_send(void)
{
gcs0.data_stream_send();
if (gcs3.initialised) {
gcs3.data_stream_send();
}
}
/*
* look for incoming commands on the GCS links
*/
static void gcs_update(void)
{
gcs0.update();
if (gcs3.initialised) {
gcs3.update();
}
}
static void gcs_send_text_P(gcs_severity severity, const prog_char_t *str)
{
gcs0.send_text_P(severity, str);
if (gcs3.initialised) {
gcs3.send_text_P(severity, str);
}
#if LOGGING_ENABLED == ENABLED
DataFlash.Log_Write_Message_P(str);
#endif
}
/*
* send a low priority formatted message to the GCS
* only one fits in the queue, so if you send more than one before the
* last one gets into the serial buffer then the old one will be lost
*/
void gcs_send_text_fmt(const prog_char_t *fmt, ...)
{
va_list arg_list;
gcs0.pending_status.severity = (uint8_t)SEVERITY_LOW;
va_start(arg_list, fmt);
hal.util->vsnprintf_P((char *)gcs0.pending_status.text,
sizeof(gcs0.pending_status.text), fmt, arg_list);
va_end(arg_list);
#if LOGGING_ENABLED == ENABLED
DataFlash.Log_Write_Message(gcs0.pending_status.text);
#endif
gcs3.pending_status = gcs0.pending_status;
mavlink_send_message(MAVLINK_COMM_0, MSG_STATUSTEXT, 0);
if (gcs3.initialised) {
mavlink_send_message(MAVLINK_COMM_1, MSG_STATUSTEXT, 0);
}
}

View File

@ -0,0 +1 @@
include ../../mk/apm.mk

View File

@ -0,0 +1,101 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
#ifndef PARAMETERS_H
#define PARAMETERS_H
#include <AP_Common.h>
// Global parameter class.
//
class Parameters {
public:
/*
* The value of k_format_version determines whether the existing
* eeprom data is considered valid. You should only change this
* value under the following circumstances:
*
* 1) the meaning of an existing eeprom parameter changes
*
* 2) the value of an existing k_param_* enum value changes
*
* Adding a new parameter should _not_ require a change to
* k_format_version except under special circumstances. If you
* change it anyway then all ArduPlane users will need to reload all
* their parameters. We want that to be an extremely rare
* thing. Please do not just change it "just in case".
*
* To determine if a k_param_* value has changed, use the rules of
* C++ enums to work out the value of the neighboring enum
* values. If you don't know the C++ enum rules then please ask for
* help.
*/
//////////////////////////////////////////////////////////////////
// STOP!!! DO NOT CHANGE THIS VALUE UNTIL YOU FULLY UNDERSTAND THE
// COMMENTS ABOVE. IF UNSURE, ASK ANOTHER DEVELOPER!!!
static const uint16_t k_format_version = 1;
//////////////////////////////////////////////////////////////////
// The parameter software_type is set up solely for ground station use
// and identifies the software type (eg ArduPilotMega versus ArduCopterMega)
// GCS will interpret values 0-9 as ArduPilotMega. Developers may use
// values within that range to identify different branches.
//
static const uint16_t k_software_type = 4;
enum {
// Layout version number, always key zero.
//
k_param_format_version = 0,
k_param_software_type,
k_param_gcs0 = 100, // stream rates for port0
k_param_gcs3, // stream rates for port3
k_param_sysid_this_mav,
k_param_sysid_my_gcs,
k_param_serial0_baud,
k_param_serial3_baud,
k_param_imu,
k_param_compass_enabled,
k_param_compass,
k_param_ahrs, // AHRS group
k_param_barometer,
k_param_scheduler,
k_param_ins,
k_param_sitl,
k_param_pidPitch2Srv,
k_param_pidYaw2Srv,
k_param_channel_yaw = 200,
k_param_channel_pitch
// 254,255: reserved
};
AP_Int16 format_version;
AP_Int8 software_type;
// Telemetry control
//
AP_Int16 sysid_this_mav;
AP_Int16 sysid_my_gcs;
AP_Int8 serial0_baud;
AP_Int8 serial3_baud;
AP_Int8 compass_enabled;
// PID controllers
PID pidPitch2Srv;
PID pidYaw2Srv;
Parameters() :
pidPitch2Srv(1.0f, 0.2f, 0.05f, 4000.0f),
pidYaw2Srv(1.0f, 0.2f, 0.05f, 4000.0f)
{}
};
extern const AP_Param::Info var_info[];
#endif // PARAMETERS_H

View File

@ -0,0 +1,125 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/*
* AntennaTracker parameter definitions
*
*/
#define GSCALAR(v, name, def) { g.v.vtype, name, Parameters::k_param_ ## v, &g.v, {def_value : def} }
#define ASCALAR(v, name, def) { aparm.v.vtype, name, Parameters::k_param_ ## v, &aparm.v, {def_value : def} }
#define GGROUP(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &g.v, {group_info : class::var_info} }
#define GOBJECT(v, name, class) { AP_PARAM_GROUP, name, Parameters::k_param_ ## v, &v, {group_info : class::var_info} }
const AP_Param::Info var_info[] PROGMEM = {
GSCALAR(format_version, "FORMAT_VERSION", 0),
GSCALAR(software_type, "SYSID_SW_TYPE", Parameters::k_software_type),
// @Param: SYSID_THISMAV
// @DisplayName: MAVLink system ID
// @Description: The identifier of this device in the MAVLink protocol
// @Range: 1 255
// @User: Advanced
GSCALAR(sysid_this_mav, "SYSID_THISMAV", MAV_SYSTEM_ID),
// @Param: SYSID_MYGCS
// @DisplayName: Ground station MAVLink system ID
// @Description: The identifier of the ground station in the MAVLink protocol. Don't change this unless you also modify the ground station to match.
// @Range: 1 255
// @User: Advanced
GSCALAR(sysid_my_gcs, "SYSID_MYGCS", 255),
// @Param: SERIAL0_BAUD
// @DisplayName: USB Console Baud Rate
// @Description: The baud rate used on the main uart
// @Values: 1:1200,2:2400,4:4800,9:9600,19:19200,38:38400,57:57600,111:111100,115:115200
// @User: Standard
GSCALAR(serial0_baud, "SERIAL0_BAUD", SERIAL0_BAUD/1000),
// @Param: SERIAL3_BAUD
// @DisplayName: Telemetry Baud Rate
// @Description: The baud rate used on the telemetry port
// @Values: 1:1200,2:2400,4:4800,9:9600,19:19200,38:38400,57:57600,111:111100,115:115200
// @User: Standard
GSCALAR(serial3_baud, "SERIAL3_BAUD", SERIAL3_BAUD/1000),
// @Param: MAG_ENABLE
// @DisplayName: Enable Compass
// @Description: Setting this to Enabled(1) will enable the compass. Setting this to Disabled(0) will disable the compass. Note that this is separate from COMPASS_USE. This will enable the low level senor, and will enable logging of magnetometer data. To use the compass for navigation you must also set COMPASS_USE to 1.
// @Values: 0:Disabled,1:Enabled
// @User: Standard
GSCALAR(compass_enabled, "MAG_ENABLE", 1),
// barometer ground calibration. The GND_ prefix is chosen for
// compatibility with previous releases of ArduPlane
// @Group: GND_
// @Path: ../libraries/AP_Baro/AP_Baro.cpp
GOBJECT(barometer, "GND_", AP_Baro),
// @Group: COMPASS_
// @Path: ../libraries/AP_Compass/Compass.cpp
GOBJECT(compass, "COMPASS_", Compass),
// @Group: SCHED_
// @Path: ../libraries/AP_Scheduler/AP_Scheduler.cpp
GOBJECT(scheduler, "SCHED_", AP_Scheduler),
// @Group: SR0_
// @Path: GCS_Mavlink.pde
GOBJECT(gcs0, "SR0_", GCS_MAVLINK),
// @Group: SR3_
// @Path: GCS_Mavlink.pde
GOBJECT(gcs3, "SR3_", GCS_MAVLINK),
// @Group: INS_
// @Path: ../libraries/AP_InertialSensor/AP_InertialSensor.cpp
GOBJECT(ins, "INS_", AP_InertialSensor),
// @Group: AHRS_
// @Path: ../libraries/AP_AHRS/AP_AHRS.cpp
GOBJECT(ahrs, "AHRS_", AP_AHRS),
#if CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
// @Group: SIM_
// @Path: ../libraries/SITL/SITL.cpp
GOBJECT(sitl, "SIM_", SITL),
#endif
// RC channel
//-----------
// @Group: RC1_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GOBJECT(channel_yaw, "RC1_", RC_Channel),
// @Group: RC2_
// @Path: ../libraries/RC_Channel/RC_Channel.cpp
GOBJECT(channel_pitch, "RC2_", RC_Channel),
GGROUP(pidPitch2Srv, "PITCH2SRV_", PID),
GGROUP(pidYaw2Srv, "YAW2SRV_", PID),
AP_VAREND
};
static void load_parameters(void)
{
if (!g.format_version.load() ||
g.format_version != Parameters::k_format_version) {
// erase all parameters
cliSerial->printf_P(PSTR("Firmware change: erasing EEPROM...\n"));
AP_Param::erase_all();
// save the current format version
g.format_version.set_and_save(Parameters::k_format_version);
cliSerial->println_P(PSTR("done."));
} else {
uint32_t before = hal.scheduler->micros();
// Load all auto-loaded EEPROM variables
AP_Param::load_all();
cliSerial->printf_P(PSTR("load_all took %luus\n"), hal.scheduler->micros() - before);
}
}

View File

@ -0,0 +1,83 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
//
#include "defines.h"
#include "APM_Config.h" // <== THIS INCLUDE, DO NOT EDIT IT. EVER.
///
/// DO NOT EDIT THIS INCLUDE - if you want to make a local change, make that
/// change in your local copy of APM_Config.h.
///
// Just so that it's completely clear...
#define ENABLED 1
#define DISABLED 0
// this avoids a very common config error
#define ENABLE ENABLED
#define DISABLE DISABLED
//////////////////////////////////////////////////////////////////////////////
// main board differences
//
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1
# define CONFIG_INS_TYPE CONFIG_INS_OILPAN
# define CONFIG_BARO AP_BARO_BMP085
# define CONFIG_COMPASS AP_COMPASS_HMC5843
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM2
# define CONFIG_INS_TYPE CONFIG_INS_MPU6000
# define CONFIG_BARO AP_BARO_MS5611
# define CONFIG_MS5611_SERIAL AP_BARO_MS5611_SPI
# define CONFIG_COMPASS AP_COMPASS_HMC5843
#elif CONFIG_HAL_BOARD == HAL_BOARD_AVR_SITL
# define CONFIG_INS_TYPE CONFIG_INS_HIL
# define CONFIG_BARO AP_BARO_HIL
# define CONFIG_COMPASS AP_COMPASS_HIL
#elif CONFIG_HAL_BOARD == HAL_BOARD_PX4
# define CONFIG_INS_TYPE CONFIG_INS_PX4
# define CONFIG_BARO AP_BARO_PX4
# define CONFIG_COMPASS AP_COMPASS_PX4
# define SERIAL0_BAUD 115200
#elif CONFIG_HAL_BOARD == HAL_BOARD_FLYMAPLE
# define CONFIG_INS_TYPE CONFIG_INS_FLYMAPLE
# define CONFIG_BARO AP_BARO_BMP085
# define CONFIG_COMPASS AP_COMPASS_HMC5843
# define SERIAL0_BAUD 115200
#elif CONFIG_HAL_BOARD == HAL_BOARD_LINUX
# define CONFIG_INS_TYPE CONFIG_INS_L3G4200D
# define CONFIG_BARO AP_BARO_BMP085
# define CONFIG_COMPASS AP_COMPASS_HMC5843
#endif
#ifndef CONFIG_BARO
# error "CONFIG_BARO not set"
#endif
#ifndef CONFIG_COMPASS
# error "CONFIG_COMPASS not set"
#endif
#ifndef MAV_SYSTEM_ID
// use 2 for antenna tracker by default
# define MAV_SYSTEM_ID 2
#endif
//////////////////////////////////////////////////////////////////////////////
// Serial port speeds.
//
#ifndef SERIAL0_BAUD
# define SERIAL0_BAUD 115200
#endif
#ifndef SERIAL3_BAUD
# define SERIAL3_BAUD 57600
#endif
#ifndef SERIAL_BUFSIZE
# define SERIAL_BUFSIZE 512
#endif
#ifndef SERIAL2_BUFSIZE
# define SERIAL2_BUFSIZE 256
#endif

View File

@ -0,0 +1,56 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
#ifndef _DEFINES_H
#define _DEFINES_H
#define ToRad(x) radians(x) // *pi/180
#define ToDeg(x) degrees(x) // *180/pi
/// please keep each MSG_ to a single MAVLink message. If need be
/// create new MSG_ IDs for additional messages on the same
/// stream
enum ap_message {
MSG_HEARTBEAT,
MSG_ATTITUDE,
MSG_LOCATION,
MSG_AHRS,
MSG_HWSTATUS,
MSG_GPS_RAW,
MSG_SERVO_OUT,
MSG_RADIO_OUT,
MSG_RAW_IMU1,
MSG_RAW_IMU2,
MSG_RAW_IMU3,
MSG_NEXT_PARAM,
MSG_STATUSTEXT,
MSG_EXTENDED_STATUS1,
MSG_EXTENDED_STATUS2,
MSG_NAV_CONTROLLER_OUTPUT,
MSG_RETRY_DEFERRED // this must be last
};
#define EEPROM_MAX_ADDR 4096
// mark a function as not to be inlined
#define NOINLINE __attribute__((noinline))
// InertialSensor driver types
#define CONFIG_INS_OILPAN 1
#define CONFIG_INS_MPU6000 2
#define CONFIG_INS_HIL 3
#define CONFIG_INS_PX4 4
#define CONFIG_INS_FLYMAPLE 5
#define CONFIG_INS_L3G4200D 6
// barometer driver types
#define AP_BARO_BMP085 1
#define AP_BARO_MS5611 2
#define AP_BARO_PX4 3
#define AP_BARO_HIL 4
// compass driver types
#define AP_COMPASS_HMC5843 1
#define AP_COMPASS_PX4 2
#define AP_COMPASS_HIL 3
#endif // _DEFINES_H

View File

@ -0,0 +1,65 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
static void init_barometer(void)
{
gcs_send_text_P(SEVERITY_LOW, PSTR("Calibrating barometer"));
barometer.calibrate();
gcs_send_text_P(SEVERITY_LOW, PSTR("barometer calibration complete"));
}
// read the barometer and return the updated altitude in meters
static void update_barometer(void)
{
barometer.read();
}
/*
update INS and attitude
*/
static void update_ahrs()
{
ahrs.update();
}
/*
read and update compass
*/
static void update_compass(void)
{
if (g.compass_enabled && compass.read()) {
ahrs.set_compass(&compass);
compass.null_offsets();
} else {
ahrs.set_compass(NULL);
}
}
/*
if the compass is enabled then try to accumulate a reading
*/
static void compass_accumulate(void)
{
if (g.compass_enabled) {
compass.accumulate();
}
}
/*
try to accumulate a baro reading
*/
static void barometer_accumulate(void)
{
barometer.accumulate();
}
/*
read the GPS
*/
static void update_GPS(void)
{
g_gps->update();
}

View File

@ -0,0 +1,109 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
static void init_tracker()
{
hal.uartA->begin(SERIAL0_BAUD, 128, SERIAL_BUFSIZE);
// gps port
hal.uartB->begin(38400, 256, 16);
cliSerial->printf_P(PSTR("\n\nInit " THISFIRMWARE
"\n\nFree RAM: %u\n"),
memcheck_available_memory());
// Check the EEPROM format version before loading any parameters from EEPROM
load_parameters();
// reset the uartA baud rate after parameter load
hal.uartA->begin(map_baudrate(g.serial0_baud, SERIAL0_BAUD));
// init baro before we start the GCS, so that the CLI baro test works
barometer.init();
// init the GCS
gcs0.init(hal.uartA);
// Register mavlink_delay_cb, which will run anytime you have
// more than 5ms remaining in your call to hal.scheduler->delay
hal.scheduler->register_delay_callback(mavlink_delay_cb, 5);
// we have a 2nd serial port for telemetry
hal.uartC->begin(map_baudrate(g.serial3_baud, SERIAL3_BAUD),
128, SERIAL2_BUFSIZE);
gcs3.init(hal.uartC);
mavlink_system.sysid = g.sysid_this_mav;
if (g.compass_enabled==true) {
if (!compass.init() || !compass.read()) {
cliSerial->println_P(PSTR("Compass initialisation failed!"));
g.compass_enabled = false;
} else {
ahrs.set_compass(&compass);
}
}
// Do GPS init
g_gps = &g_gps_driver;
// GPS Initialization
g_gps->init(hal.uartB, GPS::GPS_ENGINE_STATIONARY);
mavlink_system.compid = 4;
mavlink_system.type = MAV_TYPE_ANTENNA_TRACKER;
ahrs.init();
ahrs.set_fly_forward(false);
ins.init(AP_InertialSensor::WARM_START, ins_sample_rate);
ahrs.reset();
init_barometer();
hal.uartA->set_blocking_writes(false);
hal.uartC->set_blocking_writes(false);
// setup antenna control PWM channels
channel_yaw.set_angle(4500);
channel_pitch.set_angle(4500);
channel_yaw.output_trim();
channel_pitch.output_trim();
channel_yaw.calc_pwm();
channel_pitch.calc_pwm();
channel_yaw.enable_out();
channel_pitch.enable_out();
gcs_send_text_P(SEVERITY_LOW,PSTR("\nReady to track."));
hal.scheduler->delay(1000);
}
// updates the status of the notify objects
// should be called at 50hz
static void update_notify()
{
notify.update();
}
/*
* map from a 8 bit EEPROM baud rate to a real baud rate
*/
static uint32_t map_baudrate(int8_t rate, uint32_t default_baud)
{
switch (rate) {
case 1: return 1200;
case 2: return 2400;
case 4: return 4800;
case 9: return 9600;
case 19: return 19200;
case 38: return 38400;
case 57: return 57600;
case 111: return 111100;
case 115: return 115200;
}
cliSerial->println_P(PSTR("Invalid SERIAL3_BAUD"));
return default_baud;
}

View File

@ -0,0 +1,81 @@
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/**
state of the vehicle we are tracking
*/
static struct {
Location location;
uint32_t last_update_us;
float heading; // degrees
float ground_speed; // m/s
} vehicle;
static Location our_location;
/**
update the pitch servo. The aim is to drive the boards pitch to the
requested pitch
*/
static void update_pitch_servo(float pitch)
{
channel_pitch.servo_out = g.pidPitch2Srv.get_pid_4500(degrees(ahrs.pitch) - pitch);
channel_pitch.calc_pwm();
channel_pitch.output();
}
/**
update the yaw servo
*/
static void update_yaw_servo(float yaw)
{
channel_yaw.servo_out = g.pidYaw2Srv.get_pid_4500(degrees(ahrs.yaw) - yaw);
channel_yaw.calc_pwm();
channel_yaw.output();
}
/**
main antenna tracking code, called at 50Hz
*/
static void update_tracking(void)
{
// project the vehicle position to take account of lost radio packets
Location vpos = vehicle.location;
float dt = (hal.scheduler->micros() - vehicle.last_update_us) * 1.0e-6f;
location_update(vpos, vehicle.heading, vehicle.ground_speed * dt);
// update our position if we have at least a 2D fix
if (g_gps->status() >= GPS::GPS_OK_FIX_2D) {
our_location.lat = g_gps->latitude;
our_location.lng = g_gps->longitude;
our_location.alt = 0; // assume ground level for now
}
// calculate the bearing to the vehicle
float bearing = get_bearing_cd(our_location, vehicle.location) * 0.01f;
float distance = get_distance(our_location, vehicle.location);
float pitch = degrees(atan2(vehicle.location.alt - our_location.alt, distance));
// update the servos
update_pitch_servo(pitch);
update_yaw_servo(bearing);
// update nav_status for NAV_CONTROLLER_OUTPUT
nav_status.bearing = bearing;
nav_status.pitch = pitch;
nav_status.distance = distance;
}
/**
handle an updated position from the aircraft
*/
static void tracking_update_position(const mavlink_global_position_int_t &msg)
{
vehicle.location.lat = msg.lat;
vehicle.location.lng = msg.lon;
vehicle.location.alt = msg.relative_alt/10;
vehicle.heading = msg.hdg * 0.01f;
vehicle.ground_speed = pythagorous2(msg.vx, msg.vy) * 0.01f;
vehicle.last_update_us = hal.scheduler->micros();
}

View File

@ -0,0 +1,24 @@
#NOTE: Advanced
ACRO_BAL_PITCH,0.25
ACRO_BAL_ROLL,0.25
ACRO_RP_P,8
ACRO_TRAINER,0
ACRO_YAW_P,4.5
ANGLE_MAX,4500
HLD_LAT_P,1
HLD_LON_P,1
LAND_SPEED,200
LOITER_LAT_I,2
LOITER_LAT_P,1
LOITER_LON_I,2
LOITER_LON_P,1
PILOT_VELZ_MAX,1000
THR_ACCEL_I,1.5
THR_ACCEL_P,0.75
THR_ALT_P,1
WPNAV_ACCEL,500
WPNAV_LOIT_SPEED,1500
WPNAV_RADIUS,200
WPNAV_SPEED,1500
WPNAV_SPEED_DN,200
WPNAV_SPEED_UP,500

View File

@ -0,0 +1,24 @@
#NOTE: Beginner
ACRO_BAL_PITCH,0.5
ACRO_BAL_ROLL,0.5
ACRO_RP_P,4
ACRO_TRAINER,2
ACRO_YAW_P,4.5
ANGLE_MAX,3000
HLD_LAT_P,0.5
HLD_LON_P,0.5
LAND_SPEED,50
LOITER_LAT_I,1
LOITER_LAT_P,0.5
LOITER_LON_I,1
LOITER_LON_P,0.5
PILOT_VELZ_MAX,250
THR_ACCEL_I,1.5
THR_ACCEL_P,0.75
THR_ALT_P,1
WPNAV_ACCEL,100
WPNAV_LOIT_SPEED,500
WPNAV_RADIUS,200
WPNAV_SPEED,500
WPNAV_SPEED_DN,200
WPNAV_SPEED_UP,500

View File

@ -0,0 +1,24 @@
#NOTE: Camera
ACRO_BAL_PITCH,1
ACRO_BAL_ROLL,1
ACRO_RP_P,8
ACRO_TRAINER,0
ACRO_YAW_P,4.5
ANGLE_MAX,3000
HLD_LAT_P,1
HLD_LON_P,1
LAND_SPEED,50
LOITER_LAT_I,2
LOITER_LAT_P,1
LOITER_LON_I,2
LOITER_LON_P,1
PILOT_VELZ_MAX,500
THR_ACCEL_I,1.5
THR_ACCEL_P,0.75
THR_ALT_P,1
WPNAV_ACCEL,100
WPNAV_LOIT_SPEED,1000
WPNAV_RADIUS,200
WPNAV_SPEED,500
WPNAV_SPEED_DN,200
WPNAV_SPEED_UP,500

View File

@ -0,0 +1,24 @@
#NOTE: Intermediate
ACRO_BAL_PITCH,0.25
ACRO_BAL_ROLL,0.25
ACRO_RP_P,6
ACRO_TRAINER,1
ACRO_YAW_P,4.5
ANGLE_MAX,4500
HLD_LAT_P,1
HLD_LON_P,1
LAND_SPEED,100
LOITER_LAT_I,2
LOITER_LAT_P,1
LOITER_LON_I,2
LOITER_LON_P,1
PILOT_VELZ_MAX,500
THR_ACCEL_I,1.5
THR_ACCEL_P,0.75
THR_ALT_P,1
WPNAV_ACCEL,200
WPNAV_LOIT_SPEED,1000
WPNAV_RADIUS,200
WPNAV_SPEED,1000
WPNAV_SPEED_DN,200
WPNAV_SPEED_UP,500

View File

@ -19,7 +19,7 @@ FRAME,2
FS_BATT_ENABLE,1 FS_BATT_ENABLE,1
FS_BATT_VOLTAGE,10.5 FS_BATT_VOLTAGE,10.5
FS_THR_ENABLE,1 FS_THR_ENABLE,1
LOG_BITMASK, 958 LOG_BITMASK, 26622
MOT_SPIN_ARMED,90 MOT_SPIN_ARMED,90
RATE_PIT_D,0.006 RATE_PIT_D,0.006
RATE_PIT_I,0.25 RATE_PIT_I,0.25

View File

@ -66,7 +66,7 @@ static Parameters g;
static GPS *g_gps; static GPS *g_gps;
AP_GPS_Auto g_gps_driver(&g_gps); AP_GPS_Auto g_gps_driver(&g_gps);
AP_InertialSensor_MPU6000 ins; AP_InertialSensor_MPU6000 ins;
AP_AHRS_DCM ahrs(&ins, g_gps); AP_AHRS_DCM ahrs(ins, g_gps);
static AP_Compass_HIL compass; static AP_Compass_HIL compass;
AP_Baro_HIL barometer; AP_Baro_HIL barometer;

View File

@ -2,6 +2,7 @@ FRAME 0
MAG_ENABLE 1 MAG_ENABLE 1
FS_THR_ENABLE 1 FS_THR_ENABLE 1
BATT_MONITOR 4 BATT_MONITOR 4
CH7_OPT 7
COMPASS_LEARN 0 COMPASS_LEARN 0
COMPASS_OFS_X 5 COMPASS_OFS_X 5
COMPASS_OFS_Y 13 COMPASS_OFS_Y 13

View File

@ -910,7 +910,6 @@ def fly_ArduCopter(viewerip=None, map=False):
print("Save landing WP") print("Save landing WP")
save_wp(mavproxy, mav) save_wp(mavproxy, mav)
mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==1000', blocking=True)
# save the stored mission to file # save the stored mission to file
print("# Save out the CH7 mission to file") print("# Save out the CH7 mission to file")

View File

@ -121,7 +121,7 @@ def convert_gpx():
kml = m + '.kml' kml = m + '.kml'
util.run_cmd('gpsbabel -i gpx -f %s -o kml,units=m,floating=1,extrude=1 -F %s' % (gpx, kml), checkfail=False) util.run_cmd('gpsbabel -i gpx -f %s -o kml,units=m,floating=1,extrude=1 -F %s' % (gpx, kml), checkfail=False)
util.run_cmd('zip %s.kmz %s.kml' % (m, m), checkfail=False) util.run_cmd('zip %s.kmz %s.kml' % (m, m), checkfail=False)
util.run_cmd(util.reltopdir("../MAVProxy/tools/mavflightview.py") + " --imagefile=%s.png %s" % (m,m)) util.run_cmd("mavflightview.py --imagefile=%s.png %s" % (m,m))
return True return True

View File

@ -49,6 +49,12 @@ def get_bearing(loc1, loc2):
bearing += 360.00 bearing += 360.00
return bearing; return bearing;
def wait_seconds(seconds_to_wait):
tstart = time.time();
tnow = tstart
while tstart + seconds_to_wait > tnow:
tnow = time.time()
def wait_altitude(mav, alt_min, alt_max, timeout=30): def wait_altitude(mav, alt_min, alt_max, timeout=30):
climb_rate = 0 climb_rate = 0
previous_alt = 0 previous_alt = 0
@ -208,10 +214,15 @@ def wait_waypoint(mav, wpnum_start, wpnum_end, allow_skip=True, max_dist=2, time
return False return False
def save_wp(mavproxy, mav): def save_wp(mavproxy, mav):
mavproxy.send('rc 7 2000\n')
mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==2000', blocking=True)
mavproxy.send('rc 7 1000\n') mavproxy.send('rc 7 1000\n')
mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==1000', blocking=True) mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==1000', blocking=True)
wait_seconds(1)
mavproxy.send('rc 7 2000\n')
mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==2000', blocking=True)
wait_seconds(1)
mavproxy.send('rc 7 1000\n')
mav.recv_match(condition='RC_CHANNELS_RAW.chan7_raw==1000', blocking=True)
wait_seconds(1)
def wait_mode(mav, mode, timeout=None): def wait_mode(mav, mode, timeout=None):
print("Waiting for mode %s" % mode) print("Waiting for mode %s" % mode)

View File

@ -60,7 +60,10 @@ def deltree(path):
def build_SIL(atype, target='sitl'): def build_SIL(atype, target='sitl'):
'''build desktop SIL''' '''build desktop SIL'''
run_cmd("make clean %s" % target, run_cmd("make clean",
dir=reltopdir(atype),
checkfail=True)
run_cmd("make %s" % target,
dir=reltopdir(atype), dir=reltopdir(atype),
checkfail=True) checkfail=True)
return True return True

View File

@ -19,7 +19,7 @@ popd
echo "Testing ArduCopter build" echo "Testing ArduCopter build"
pushd ArduCopter pushd ArduCopter
for b in all apm2 apm1-hil apm2-hil sitl heli dmp linux; do for b in all apm2 apm1-hil apm2-hil sitl apm2-heli linux; do
pwd pwd
make clean make clean
make $b -j4 make $b -j4

View File

@ -139,6 +139,6 @@ echo $githash > "buildlogs/history/$hdate/githash.txt"
killall -9 JSBSim || /bin/true killall -9 JSBSim || /bin/true
timelimit 5200 APM/Tools/autotest/autotest.py --timeout=5000 > buildlogs/autotest-output.txt 2>&1 timelimit 6500 APM/Tools/autotest/autotest.py --timeout=6000 > buildlogs/autotest-output.txt 2>&1
) >> build.log 2>&1 ) >> build.log 2>&1

View File

@ -118,8 +118,9 @@ build_arducopter() {
checkout ArduCopter $tag || return checkout ArduCopter $tag || return
echo "Building ArduCopter $tag binaries" echo "Building ArduCopter $tag binaries"
pushd ArduCopter pushd ArduCopter
frames="quad tri hexa y6 octa octa-quad heli"
for b in apm1 apm2; do for b in apm1 apm2; do
for f in quad tri hexa y6 octa octa-quad heli quad-hil heli-hil; do for f in $frames quad-hil heli-hil; do
echo "Building ArduCopter $b-$f binaries" echo "Building ArduCopter $b-$f binaries"
ddir="$binaries/Copter/$hdate/$b-$f" ddir="$binaries/Copter/$hdate/$b-$f"
skip_build $tag $ddir && continue skip_build $tag $ddir && continue
@ -131,7 +132,7 @@ build_arducopter() {
done done
test -n "$PX4_ROOT" && { test -n "$PX4_ROOT" && {
make px4-clean || return make px4-clean || return
for f in quad tri hexa y6 octa octa-quad heli quad-hil heli-hil; do for f in $frames quad-hil heli-hil; do
echo "Building ArduCopter PX4-$f binaries" echo "Building ArduCopter PX4-$f binaries"
ddir="$binaries/Copter/$hdate/PX4-$f" ddir="$binaries/Copter/$hdate/PX4-$f"
skip_build $tag $ddir && continue skip_build $tag $ddir && continue

View File

@ -55,7 +55,7 @@ const AP_Param::GroupInfo AC_Fence::var_info[] PROGMEM = {
}; };
/// Default constructor. /// Default constructor.
AC_Fence::AC_Fence(AP_InertialNav* inav) : AC_Fence::AC_Fence(const AP_InertialNav* inav) :
_inav(inav), _inav(inav),
_alt_max_backup(0), _alt_max_backup(0),
_circle_radius_backup(0), _circle_radius_backup(0),
@ -120,7 +120,7 @@ uint8_t AC_Fence::check_fence()
} }
// get current altitude in meters // get current altitude in meters
float curr_alt = _inav->get_position().z * 0.01f; float curr_alt = _inav->get_altitude() * 0.01f;
// altitude fence check // altitude fence check
if ((_enabled_fences & AC_FENCE_TYPE_ALT_MAX) != 0) { if ((_enabled_fences & AC_FENCE_TYPE_ALT_MAX) != 0) {

View File

@ -32,7 +32,7 @@ class AC_Fence
public: public:
/// Constructor /// Constructor
AC_Fence(AP_InertialNav* inav); AC_Fence(const AP_InertialNav* inav);
/// enable - allows fence to be enabled/disabled. Note: this does not update the eeprom saved value /// enable - allows fence to be enabled/disabled. Note: this does not update the eeprom saved value
void enable(bool true_false) { _enabled = true_false; } void enable(bool true_false) { _enabled = true_false; }
@ -89,7 +89,7 @@ private:
void clear_breach(uint8_t fence_type); void clear_breach(uint8_t fence_type);
// pointers to other objects we depend upon // pointers to other objects we depend upon
AP_InertialNav* _inav; const AP_InertialNav *const _inav;
// parameters // parameters
AP_Int8 _enabled; // top level enable/disable control AP_Int8 _enabled; // top level enable/disable control

View File

@ -52,10 +52,10 @@ AP_GPS_Auto auto_gps(&gps);
GPS_Glitch gps_glitch(gps); GPS_Glitch gps_glitch(gps);
AP_Compass_HMC5843 compass; AP_Compass_HMC5843 compass;
AP_AHRS_DCM ahrs(&ins, gps); AP_AHRS_DCM ahrs(ins, gps);
// Inertial Nav declaration // Inertial Nav declaration
AP_InertialNav inertial_nav(&ahrs, &ins, &baro, gps, gps_glitch); AP_InertialNav inertial_nav(&ahrs, &baro, gps, gps_glitch);
// Fence // Fence
AC_Fence fence(&inertial_nav); AC_Fence fence(&inertial_nav);

View File

@ -50,8 +50,7 @@ const AP_Param::GroupInfo AC_Sprayer::var_info[] PROGMEM = {
AP_GROUPEND AP_GROUPEND
}; };
/// Default constructor. AC_Sprayer::AC_Sprayer(const AP_InertialNav* inav) :
AC_Sprayer::AC_Sprayer(AP_InertialNav* inav) :
_inav(inav), _inav(inav),
_speed_over_min_time(0), _speed_over_min_time(0),
_speed_under_min_time(0) _speed_under_min_time(0)
@ -69,7 +68,6 @@ AC_Sprayer::AC_Sprayer(AP_InertialNav* inav) :
// To-Do: ensure that the pump and spinner servo channels are enabled // To-Do: ensure that the pump and spinner servo channels are enabled
} }
/// enable - allows fence to be enabled/disabled. Note: this does not update the eeprom saved value
void AC_Sprayer::enable(bool true_false) void AC_Sprayer::enable(bool true_false)
{ {
// return immediately if no change // return immediately if no change
@ -97,7 +95,6 @@ void
AC_Sprayer::update() AC_Sprayer::update()
{ {
uint32_t now; uint32_t now;
Vector3f velocity;
float ground_speed; float ground_speed;
// exit immediately if we are disabled (perhaps set pwm values back to defaults) // exit immediately if we are disabled (perhaps set pwm values back to defaults)
@ -111,7 +108,7 @@ AC_Sprayer::update()
} }
// get horizontal velocity // get horizontal velocity
velocity = _inav->get_velocity(); const Vector3f &velocity = _inav->get_velocity();
ground_speed = pythagorous2(velocity.x,velocity.y); ground_speed = pythagorous2(velocity.x,velocity.y);
// get the current time // get the current time

View File

@ -34,19 +34,19 @@
#define AC_SPRAYER_DEFAULT_TURN_ON_DELAY 100 // delay between when we reach the minimum speed and we begin spraying. This reduces the likelihood of constantly turning on/off the pump #define AC_SPRAYER_DEFAULT_TURN_ON_DELAY 100 // delay between when we reach the minimum speed and we begin spraying. This reduces the likelihood of constantly turning on/off the pump
#define AC_SPRAYER_DEFAULT_SHUT_OFF_DELAY 1000 // shut-off delay in milli seconds. This reduces the likelihood of constantly turning on/off the pump #define AC_SPRAYER_DEFAULT_SHUT_OFF_DELAY 1000 // shut-off delay in milli seconds. This reduces the likelihood of constantly turning on/off the pump
/// @class Camera /// @class AC_Sprayer
/// @brief Object managing a Photo or video camera /// @brief Object managing a crop sprayer comprised of a spinner and a pump both controlled by pwm
class AC_Sprayer { class AC_Sprayer {
public: public:
/// Constructor /// Constructor
AC_Sprayer(AP_InertialNav* inav); AC_Sprayer(const AP_InertialNav* inav);
/// enable - allows sprayer to be enabled/disabled. Note: this does not update the eeprom saved value /// enable - allows sprayer to be enabled/disabled. Note: this does not update the eeprom saved value
void enable(bool true_false); void enable(bool true_false);
/// enabled - returns true if fence is enabled /// enabled - returns true if sprayer is enabled
bool enabled() const { return _enabled; } bool enabled() const { return _enabled; }
/// test_pump - set to true to turn on pump as if travelling at 1m/s as a test /// test_pump - set to true to turn on pump as if travelling at 1m/s as a test
@ -64,7 +64,7 @@ public:
private: private:
// pointers to other objects we depend upon // pointers to other objects we depend upon
AP_InertialNav* _inav; const AP_InertialNav* const _inav;
// parameters // parameters
AP_Int8 _enabled; // top level enable/disable control AP_Int8 _enabled; // top level enable/disable control

View File

@ -68,7 +68,7 @@ const AP_Param::GroupInfo AC_WPNav::var_info[] PROGMEM = {
// Note that the Vector/Matrix constructors already implicitly zero // Note that the Vector/Matrix constructors already implicitly zero
// their values. // their values.
// //
AC_WPNav::AC_WPNav(AP_InertialNav* inav, AP_AHRS* ahrs, APM_PI* pid_pos_lat, APM_PI* pid_pos_lon, AC_PID* pid_rate_lat, AC_PID* pid_rate_lon) : AC_WPNav::AC_WPNav(const AP_InertialNav* inav, const AP_AHRS* ahrs, APM_PI* pid_pos_lat, APM_PI* pid_pos_lon, AC_PID* pid_rate_lat, AC_PID* pid_rate_lon) :
_inav(inav), _inav(inav),
_ahrs(ahrs), _ahrs(ahrs),
_pid_pos_lat(pid_pos_lat), _pid_pos_lat(pid_pos_lat),
@ -102,7 +102,8 @@ AC_WPNav::AC_WPNav(AP_InertialNav* inav, AP_AHRS* ahrs, APM_PI* pid_pos_lat, APM
{ {
AP_Param::setup_object_defaults(this, var_info); AP_Param::setup_object_defaults(this, var_info);
// calculate loiter leash // initialise leash lengths
calculate_wp_leash_length(true);
calculate_loiter_leash_length(); calculate_loiter_leash_length();
} }
@ -138,7 +139,7 @@ void AC_WPNav::get_stopping_point(const Vector3f& position, const Vector3f& velo
linear_distance = _wp_accel_cms/(2.0f*kP*kP); linear_distance = _wp_accel_cms/(2.0f*kP*kP);
target_dist = linear_distance + (vel_total*vel_total)/(2.0f*_wp_accel_cms); target_dist = linear_distance + (vel_total*vel_total)/(2.0f*_wp_accel_cms);
} }
target_dist = constrain_float(target_dist, 0, _wp_leash_xy*2.0f); target_dist = constrain_float(target_dist, 0, _wp_leash_xy);
target.x = position.x + (target_dist * velocity.x / vel_total); target.x = position.x + (target_dist * velocity.x / vel_total);
target.y = position.y + (target_dist * velocity.y / vel_total); target.y = position.y + (target_dist * velocity.y / vel_total);
@ -386,7 +387,7 @@ void AC_WPNav::set_origin_and_destination(const Vector3f& origin, const Vector3f
_flags.reached_destination = false; _flags.reached_destination = false;
// initialise the limited speed to current speed along the track // initialise the limited speed to current speed along the track
Vector3f curr_vel = _inav->get_velocity(); const Vector3f &curr_vel = _inav->get_velocity();
// get speed along track (note: we convert vertical speed into horizontal speed equivalent) // get speed along track (note: we convert vertical speed into horizontal speed equivalent)
float speed_along_track = curr_vel.x * _pos_delta_unit.x + curr_vel.y * _pos_delta_unit.y + curr_vel.z * _pos_delta_unit.z; float speed_along_track = curr_vel.x * _pos_delta_unit.x + curr_vel.y * _pos_delta_unit.y + curr_vel.z * _pos_delta_unit.z;
_limited_speed_xy_cms = constrain_float(speed_along_track,0,_wp_speed_cms); _limited_speed_xy_cms = constrain_float(speed_along_track,0,_wp_speed_cms);
@ -437,7 +438,7 @@ void AC_WPNav::advance_target_along_track(float dt)
} }
// get current velocity // get current velocity
Vector3f curr_vel = _inav->get_velocity(); const Vector3f &curr_vel = _inav->get_velocity();
// get speed along track // get speed along track
float speed_along_track = curr_vel.x * _pos_delta_unit.x + curr_vel.y * _pos_delta_unit.y + curr_vel.z * _pos_delta_unit.z; float speed_along_track = curr_vel.x * _pos_delta_unit.x + curr_vel.y * _pos_delta_unit.y + curr_vel.z * _pos_delta_unit.z;
@ -619,7 +620,7 @@ void AC_WPNav::get_loiter_position_to_velocity(float dt, float max_speed_cms)
/// converts desired velocities in lat/lon directions to accelerations in lat/lon frame /// converts desired velocities in lat/lon directions to accelerations in lat/lon frame
void AC_WPNav::get_loiter_velocity_to_acceleration(float vel_lat, float vel_lon, float dt) void AC_WPNav::get_loiter_velocity_to_acceleration(float vel_lat, float vel_lon, float dt)
{ {
Vector3f vel_curr = _inav->get_velocity(); // current velocity in cm/s const Vector3f &vel_curr = _inav->get_velocity(); // current velocity in cm/s
Vector3f vel_error; // The velocity error in cm/s. Vector3f vel_error; // The velocity error in cm/s.
float accel_total; // total acceleration in cm/s/s float accel_total; // total acceleration in cm/s/s

View File

@ -40,7 +40,7 @@ class AC_WPNav
public: public:
/// Constructor /// Constructor
AC_WPNav(AP_InertialNav* inav, AP_AHRS* ahrs, APM_PI* pid_pos_lat, APM_PI* pid_pos_lon, AC_PID* pid_rate_lat, AC_PID* pid_rate_lon); AC_WPNav(const AP_InertialNav* inav, const AP_AHRS* ahrs, APM_PI* pid_pos_lat, APM_PI* pid_pos_lon, AC_PID* pid_rate_lat, AC_PID* pid_rate_lon);
/// ///
/// simple loiter controller /// simple loiter controller
@ -183,15 +183,15 @@ protected:
/// set climb param to true if track climbs vertically, false if descending /// set climb param to true if track climbs vertically, false if descending
void calculate_wp_leash_length(bool climb); void calculate_wp_leash_length(bool climb);
// pointers to inertial nav and ahrs libraries // references to inertial nav and ahrs libraries
AP_InertialNav* _inav; const AP_InertialNav* const _inav;
AP_AHRS* _ahrs; const AP_AHRS* const _ahrs;
// pointers to pid controllers // pointers to pid controllers
APM_PI* _pid_pos_lat; APM_PI* const _pid_pos_lat;
APM_PI* _pid_pos_lon; APM_PI* const _pid_pos_lon;
AC_PID* _pid_rate_lat; AC_PID* const _pid_rate_lat;
AC_PID* _pid_rate_lon; AC_PID* const _pid_rate_lon;
// parameters // parameters
AP_Float _loiter_speed_cms; // maximum horizontal speed in cm/s while in loiter AP_Float _loiter_speed_cms; // maximum horizontal speed in cm/s while in loiter

View File

@ -125,12 +125,14 @@ int32_t AP_PitchController::_get_rate_out(float desired_rate, float scaler, bool
float rate_error = (desired_rate - ToDeg(omega_y)) * scaler; float rate_error = (desired_rate - ToDeg(omega_y)) * scaler;
// Multiply pitch rate error by _ki_rate and integrate // Multiply pitch rate error by _ki_rate and integrate
// Scaler is applied before integrator so that integrator state relates directly to elevator deflection
// This means elevator trim offset doesn't change as the value of scaler changes with airspeed
// Don't integrate if in stabilise mode as the integrator will wind up against the pilots inputs // Don't integrate if in stabilise mode as the integrator will wind up against the pilots inputs
if (!disable_integrator && _K_I > 0) { if (!disable_integrator && _K_I > 0) {
float ki_rate = _K_I * _tau; float ki_rate = _K_I * _tau;
//only integrate if gain and time step are positive and airspeed above min value. //only integrate if gain and time step are positive and airspeed above min value.
if (dt > 0 && aspeed > 0.5f*float(aparm.airspeed_min)) { if (dt > 0 && aspeed > 0.5f*float(aparm.airspeed_min)) {
float integrator_delta = rate_error * ki_rate * delta_time; float integrator_delta = rate_error * ki_rate * delta_time * scaler;
if (_last_out < -45) { if (_last_out < -45) {
// prevent the integrator from increasing if surface defln demand is above the upper limit // prevent the integrator from increasing if surface defln demand is above the upper limit
integrator_delta = max(integrator_delta , 0); integrator_delta = max(integrator_delta , 0);
@ -145,7 +147,7 @@ int32_t AP_PitchController::_get_rate_out(float desired_rate, float scaler, bool
} }
// Scale the integration limit // Scale the integration limit
float intLimScaled = _imax * 0.01f / scaler; float intLimScaled = _imax * 0.01f;
// Constrain the integrator state // Constrain the integrator state
_integrator = constrain_float(_integrator, -intLimScaled, intLimScaled); _integrator = constrain_float(_integrator, -intLimScaled, intLimScaled);
@ -158,7 +160,7 @@ int32_t AP_PitchController::_get_rate_out(float desired_rate, float scaler, bool
// Note the scaler is applied again. We want a 1/speed scaler applied to the feed-forward // Note the scaler is applied again. We want a 1/speed scaler applied to the feed-forward
// path, but want a 1/speed^2 scaler applied to the rate error path. // path, but want a 1/speed^2 scaler applied to the rate error path.
// This is because acceleration scales with speed^2, but rate scales with speed. // This is because acceleration scales with speed^2, but rate scales with speed.
_last_out = ( (rate_error * _K_D) + _integrator + (desired_rate * kp_ff) ) * scaler; _last_out = ( (rate_error * _K_D) + (desired_rate * kp_ff) ) * scaler + _integrator;
// Convert to centi-degrees and constrain // Convert to centi-degrees and constrain
return constrain_float(_last_out * 100, -4500, 4500); return constrain_float(_last_out * 100, -4500, 4500);
@ -216,7 +218,7 @@ float AP_PitchController::_get_coordination_rate_offset(float &aspeed, bool &inv
// don't do turn coordination handling when at very high pitch angles // don't do turn coordination handling when at very high pitch angles
rate_offset = 0; rate_offset = 0;
} else { } else {
rate_offset = fabsf(ToDeg((GRAVITY_MSS / max(aspeed , float(aparm.airspeed_min))) * tanf(bank_angle) * sinf(bank_angle))) * _roll_ff; rate_offset = cosf(_ahrs.pitch)*fabsf(ToDeg((GRAVITY_MSS / max(aspeed , float(aparm.airspeed_min))) * tanf(bank_angle) * sinf(bank_angle))) * _roll_ff;
} }
if (inverted) { if (inverted) {
rate_offset = -rate_offset; rate_offset = -rate_offset;

View File

@ -117,12 +117,14 @@ int32_t AP_RollController::_get_rate_out(float desired_rate, float scaler, bool
aspeed = 0.0f; aspeed = 0.0f;
} }
// Multiply roll rate error by _ki_rate and integrate // Multiply roll rate error by _ki_rate, apply scaler and integrate
// Scaler is applied before integrator so that integrator state relates directly to aileron deflection
// This means aileron trim offset doesn't change as the value of scaler changes with airspeed
// Don't integrate if in stabilise mode as the integrator will wind up against the pilots inputs // Don't integrate if in stabilise mode as the integrator will wind up against the pilots inputs
if (!disable_integrator && ki_rate > 0) { if (!disable_integrator && ki_rate > 0) {
//only integrate if gain and time step are positive and airspeed above min value. //only integrate if gain and time step are positive and airspeed above min value.
if (dt > 0 && aspeed > float(aparm.airspeed_min)) { if (dt > 0 && aspeed > float(aparm.airspeed_min)) {
float integrator_delta = rate_error * ki_rate * delta_time; float integrator_delta = rate_error * ki_rate * delta_time * scaler;
// prevent the integrator from increasing if surface defln demand is above the upper limit // prevent the integrator from increasing if surface defln demand is above the upper limit
if (_last_out < -45) { if (_last_out < -45) {
integrator_delta = max(integrator_delta , 0); integrator_delta = max(integrator_delta , 0);
@ -137,7 +139,7 @@ int32_t AP_RollController::_get_rate_out(float desired_rate, float scaler, bool
} }
// Scale the integration limit // Scale the integration limit
float intLimScaled = _imax * 0.01f / scaler; float intLimScaled = _imax * 0.01f;
// Constrain the integrator state // Constrain the integrator state
_integrator = constrain_float(_integrator, -intLimScaled, intLimScaled); _integrator = constrain_float(_integrator, -intLimScaled, intLimScaled);
@ -146,7 +148,7 @@ int32_t AP_RollController::_get_rate_out(float desired_rate, float scaler, bool
// Note the scaler is applied again. We want a 1/speed scaler applied to the feed-forward // Note the scaler is applied again. We want a 1/speed scaler applied to the feed-forward
// path, but want a 1/speed^2 scaler applied to the rate error path. // path, but want a 1/speed^2 scaler applied to the rate error path.
// This is because acceleration scales with speed^2, but rate scales with speed. // This is because acceleration scales with speed^2, but rate scales with speed.
_last_out = ( (rate_error * _K_D) + _integrator + (desired_rate * kp_ff) ) * scaler; _last_out = ( (rate_error * _K_D) + (desired_rate * kp_ff) ) * scaler + _integrator;
// Convert to centi-degrees and constrain // Convert to centi-degrees and constrain
return constrain_float(_last_out * 100, -4500, 4500); return constrain_float(_last_out * 100, -4500, 4500);

View File

@ -106,7 +106,7 @@ int32_t AP_YawController::get_servo_out(float scaler, bool disable_integrator)
float omega_z = _ahrs.get_gyro().z; float omega_z = _ahrs.get_gyro().z;
// Get the accln vector (m/s^2) // Get the accln vector (m/s^2)
float accel_y = _ahrs.get_ins()->get_accel().y; float accel_y = _ahrs.get_ins().get_accel().y;
// Subtract the steady turn component of rate from the measured rate // Subtract the steady turn component of rate from the measured rate
// to calculate the rate relative to the turn requirement in degrees/sec // to calculate the rate relative to the turn requirement in degrees/sec

View File

@ -41,14 +41,14 @@ const AP_Param::GroupInfo AP_AHRS::var_info[] PROGMEM = {
// @Description: This controls the weight the compass or GPS has on the heading. A higher value means the heading will track the yaw source (GPS or compass) more rapidly. // @Description: This controls the weight the compass or GPS has on the heading. A higher value means the heading will track the yaw source (GPS or compass) more rapidly.
// @Range: 0.1 0.4 // @Range: 0.1 0.4
// @Increment: .01 // @Increment: .01
AP_GROUPINFO("YAW_P", 4, AP_AHRS, _kp_yaw, 0.3f), AP_GROUPINFO("YAW_P", 4, AP_AHRS, _kp_yaw, 0.2f),
// @Param: RP_P // @Param: RP_P
// @DisplayName: AHRS RP_P // @DisplayName: AHRS RP_P
// @Description: This controls how fast the accelerometers correct the attitude // @Description: This controls how fast the accelerometers correct the attitude
// @Range: 0.1 0.4 // @Range: 0.1 0.4
// @Increment: .01 // @Increment: .01
AP_GROUPINFO("RP_P", 5, AP_AHRS, _kp, 0.3f), AP_GROUPINFO("RP_P", 5, AP_AHRS, _kp, 0.2f),
// @Param: WIND_MAX // @Param: WIND_MAX
// @DisplayName: Maximum wind // @DisplayName: Maximum wind
@ -105,6 +105,14 @@ const AP_Param::GroupInfo AP_AHRS::var_info[] PROGMEM = {
// @User: Advanced // @User: Advanced
AP_GROUPINFO("GPS_MINSATS", 11, AP_AHRS, _gps_minsats, 6), AP_GROUPINFO("GPS_MINSATS", 11, AP_AHRS, _gps_minsats, 6),
// @Param: GPS_DELAY
// @DisplayName: AHRS GPS delay steps
// @Description: number of GPS samples to delay accels for synchronisation with the GPS velocity data
// @Range: 0 5
// @Increment: 1
// @User: Advanced
AP_GROUPINFO("GPS_DELAY", 12, AP_AHRS, _gps_delay, 2),
AP_GROUPEND AP_GROUPEND
}; };

View File

@ -37,7 +37,7 @@ class AP_AHRS
{ {
public: public:
// Constructor // Constructor
AP_AHRS(AP_InertialSensor *ins, GPS *&gps) : AP_AHRS(AP_InertialSensor &ins, GPS *&gps) :
_ins(ins), _ins(ins),
_gps(gps) _gps(gps)
{ {
@ -49,7 +49,7 @@ public:
// prone than the APM1, so we should have a lower ki, // prone than the APM1, so we should have a lower ki,
// which will make us less prone to increasing omegaI // which will make us less prone to increasing omegaI
// incorrectly due to sensor noise // incorrectly due to sensor noise
_gyro_drift_limit = ins->get_gyro_drift_rate(); _gyro_drift_limit = ins.get_gyro_drift_rate();
// enable centrifugal correction by default // enable centrifugal correction by default
_flags.correct_centrifugal = true; _flags.correct_centrifugal = true;
@ -78,7 +78,7 @@ public:
// allow for runtime change of orientation // allow for runtime change of orientation
// this makes initial config easier // this makes initial config easier
void set_orientation() { void set_orientation() {
_ins->set_board_orientation((enum Rotation)_board_orientation.get()); _ins.set_board_orientation((enum Rotation)_board_orientation.get());
if (_compass != NULL) { if (_compass != NULL) {
_compass->set_board_orientation((enum Rotation)_board_orientation.get()); _compass->set_board_orientation((enum Rotation)_board_orientation.get());
} }
@ -88,7 +88,7 @@ public:
_airspeed = airspeed; _airspeed = airspeed;
} }
AP_InertialSensor* get_ins() const { const AP_InertialSensor &get_ins() const {
return _ins; return _ins;
} }
@ -242,6 +242,7 @@ protected:
AP_Int8 _wind_max; AP_Int8 _wind_max;
AP_Int8 _board_orientation; AP_Int8 _board_orientation;
AP_Int8 _gps_minsats; AP_Int8 _gps_minsats;
AP_Int8 _gps_delay;
// flags structure // flags structure
struct ahrs_flags { struct ahrs_flags {
@ -263,7 +264,7 @@ protected:
// note: we use ref-to-pointer here so that our caller can change the GPS without our noticing // note: we use ref-to-pointer here so that our caller can change the GPS without our noticing
// IMU under us without our noticing. // IMU under us without our noticing.
AP_InertialSensor *_ins; AP_InertialSensor &_ins;
GPS *&_gps; GPS *&_gps;
// a vector to capture the difference between the controller and body frames // a vector to capture the difference between the controller and body frames

View File

@ -48,10 +48,10 @@ AP_AHRS_DCM::update(void)
float delta_t; float delta_t;
// tell the IMU to grab some data // tell the IMU to grab some data
_ins->update(); _ins.update();
// ask the IMU how much time this sensor reading represents // ask the IMU how much time this sensor reading represents
delta_t = _ins->get_delta_time(); delta_t = _ins.get_delta_time();
// if the update call took more than 0.2 seconds then discard it, // if the update call took more than 0.2 seconds then discard it,
// otherwise we may move too far. This happens when arming motors // otherwise we may move too far. This happens when arming motors
@ -62,10 +62,6 @@ AP_AHRS_DCM::update(void)
return; return;
} }
// Get current values for gyros
_gyro_vector = _ins->get_gyro();
_accel_vector = _ins->get_accel();
// Integrate the DCM matrix using gyro inputs // Integrate the DCM matrix using gyro inputs
matrix_update(delta_t); matrix_update(delta_t);
@ -91,7 +87,7 @@ AP_AHRS_DCM::matrix_update(float _G_Dt)
// and including the P terms would give positive feedback into // and including the P terms would give positive feedback into
// the _P_gain() calculation, which can lead to a very large P // the _P_gain() calculation, which can lead to a very large P
// value // value
_omega = _gyro_vector + _omega_I; _omega = _ins.get_gyro() + _omega_I;
_dcm_matrix.rotate((_omega + _omega_P + _omega_yaw_P) * _G_Dt); _dcm_matrix.rotate((_omega + _omega_P + _omega_yaw_P) * _G_Dt);
} }
@ -351,6 +347,11 @@ AP_AHRS_DCM::drift_correction_yaw(void)
} }
new_value = true; new_value = true;
yaw_error = yaw_error_compass(); yaw_error = yaw_error_compass();
// also update the _gps_last_update, so if we later
// disable the compass due to significant yaw error we
// don't suddenly change yaw with a reset
_gps_last_update = _gps->last_fix_time;
} }
} else if (_flags.fly_forward && have_gps()) { } else if (_flags.fly_forward && have_gps()) {
/* /*
@ -362,7 +363,7 @@ AP_AHRS_DCM::drift_correction_yaw(void)
_gps_last_update = _gps->last_fix_time; _gps_last_update = _gps->last_fix_time;
new_value = true; new_value = true;
float gps_course_rad = ToRad(_gps->ground_course_cd * 0.01f); float gps_course_rad = ToRad(_gps->ground_course_cd * 0.01f);
float yaw_error_rad = gps_course_rad - yaw; float yaw_error_rad = wrap_PI(gps_course_rad - yaw);
yaw_error = sinf(yaw_error_rad); yaw_error = sinf(yaw_error_rad);
/* reset yaw to match GPS heading under any of the /* reset yaw to match GPS heading under any of the
@ -430,7 +431,55 @@ AP_AHRS_DCM::drift_correction_yaw(void)
} }
/**
return an accel vector delayed by AHRS_ACCEL_DELAY samples
*/
Vector3f AP_AHRS_DCM::ra_delayed(const Vector3f &ra)
{
if (_ra_delay_length != _gps_delay.get()) {
// the AHRS_GPS_DELAY setting has changed
// constrain it between 0 and 5
if (_gps_delay.get() > 5) {
_gps_delay.set(5);
}
if (_gps_delay.get() < 0) {
_gps_delay.set(0);
}
if (_ra_delay_buffer != NULL) {
delete[] _ra_delay_buffer;
_ra_delay_buffer = NULL;
}
// allocate the new buffer
_ra_delay_length = _gps_delay.get();
if (_ra_delay_length != 0) {
_ra_delay_buffer = new Vector3f[_ra_delay_length];
}
_ra_delay_next = 0;
if (_ra_delay_buffer != NULL) {
// on size change prefill the buffer with the current value
for (uint8_t i=0; i<_ra_delay_length; i++) {
_ra_delay_buffer[i] = ra;
}
}
}
if (_ra_delay_buffer == NULL) {
// we're not doing any delay
return ra;
}
// get the old element, and then fill it with the new element
Vector3f ret = _ra_delay_buffer[_ra_delay_next];
_ra_delay_buffer[_ra_delay_next] = ra;
// move to the next element
_ra_delay_next++;
if (_ra_delay_next == _ra_delay_length) {
_ra_delay_next = 0;
}
return ret;
}
// perform drift correction. This function aims to update _omega_P and // perform drift correction. This function aims to update _omega_P and
// _omega_I with our best estimate of the short term and long term // _omega_I with our best estimate of the short term and long term
@ -456,7 +505,7 @@ AP_AHRS_DCM::drift_correction(float deltat)
temp_dcm.rotateXY(_trim); temp_dcm.rotateXY(_trim);
// rotate accelerometer values into the earth frame // rotate accelerometer values into the earth frame
_accel_ef = temp_dcm * _accel_vector; _accel_ef = temp_dcm * _ins.get_accel();
// integrate the accel vector in the earth frame between GPS readings // integrate the accel vector in the earth frame between GPS readings
_ra_sum += _accel_ef * deltat; _ra_sum += _accel_ef * deltat;
@ -543,30 +592,35 @@ AP_AHRS_DCM::drift_correction(float deltat)
Vector3f GA_e; Vector3f GA_e;
GA_e = Vector3f(0, 0, -1.0f); GA_e = Vector3f(0, 0, -1.0f);
bool using_gps_corrections = false;
if (_flags.correct_centrifugal && (_have_gps_lock || _flags.fly_forward)) { if (_flags.correct_centrifugal && (_have_gps_lock || _flags.fly_forward)) {
float v_scale = gps_gain.get()/(_ra_deltat*GRAVITY_MSS); float v_scale = gps_gain.get()/(_ra_deltat*GRAVITY_MSS);
Vector3f vdelta = (velocity - _last_velocity) * v_scale; Vector3f vdelta = (velocity - _last_velocity) * v_scale;
// limit vertical acceleration correction to 0.5 gravities. The
// barometer sometimes gives crazy acceleration changes.
vdelta.z = constrain_float(vdelta.z, -0.5f, 0.5f);
GA_e += vdelta; GA_e += vdelta;
GA_e.normalize(); GA_e.normalize();
if (GA_e.is_inf()) { if (GA_e.is_inf()) {
// wait for some non-zero acceleration information // wait for some non-zero acceleration information
return; return;
} }
using_gps_corrections = true;
} }
// calculate the error term in earth frame. // calculate the error term in earth frame.
Vector3f GA_b = _ra_sum / (_ra_deltat * GRAVITY_MSS); _ra_sum /= (_ra_deltat * GRAVITY_MSS);
float length = GA_b.length();
if (length > 1.0f) { // get the delayed ra_sum to match the GPS lag
GA_b /= length; Vector3f GA_b;
if (using_gps_corrections) {
GA_b = ra_delayed(_ra_sum);
} else {
GA_b = _ra_sum;
}
GA_b.normalize();
if (GA_b.is_inf()) { if (GA_b.is_inf()) {
// wait for some non-zero acceleration information // wait for some non-zero acceleration information
return; return;
} }
}
Vector3f error = GA_b % GA_e; Vector3f error = GA_b % GA_e;
#define YAW_INDEPENDENT_DRIFT_CORRECTION 0 #define YAW_INDEPENDENT_DRIFT_CORRECTION 0
@ -600,8 +654,15 @@ AP_AHRS_DCM::drift_correction(float deltat)
} }
} }
// if ins is unhealthy then stop attitude drift correction and
// hope the gyros are OK for a while. Just slowly reduce _omega_P
// to prevent previous bad accels from throwing us off
if (!_ins.healthy()) {
error.zero();
} else {
// convert the error term to body frame // convert the error term to body frame
error = _dcm_matrix.mul_transpose(error); error = _dcm_matrix.mul_transpose(error);
}
if (error.is_nan() || error.is_inf()) { if (error.is_nan() || error.is_inf()) {
// don't allow bad values // don't allow bad values
@ -625,7 +686,7 @@ AP_AHRS_DCM::drift_correction(float deltat)
if (_flags.fly_forward && _gps && _gps->status() >= GPS::GPS_OK_FIX_2D && if (_flags.fly_forward && _gps && _gps->status() >= GPS::GPS_OK_FIX_2D &&
_gps->ground_speed_cm < GPS_SPEED_MIN && _gps->ground_speed_cm < GPS_SPEED_MIN &&
_accel_vector.x >= 7 && _ins.get_accel().x >= 7 &&
pitch_sensor > -3000 && pitch_sensor < 3000) { pitch_sensor > -3000 && pitch_sensor < 3000) {
// assume we are in a launch acceleration, and reduce the // assume we are in a launch acceleration, and reduce the
// rp gain by 50% to reduce the impact of GPS lag on // rp gain by 50% to reduce the impact of GPS lag on

View File

@ -25,7 +25,7 @@ class AP_AHRS_DCM : public AP_AHRS
{ {
public: public:
// Constructors // Constructors
AP_AHRS_DCM(AP_InertialSensor *ins, GPS *&gps) : AP_AHRS_DCM(AP_InertialSensor &ins, GPS *&gps) :
AP_AHRS(ins, gps), AP_AHRS(ins, gps),
_last_declination(0), _last_declination(0),
_mag_earth(1,0) _mag_earth(1,0)
@ -92,9 +92,6 @@ private:
// primary representation of attitude // primary representation of attitude
Matrix3f _dcm_matrix; Matrix3f _dcm_matrix;
Vector3f _gyro_vector; // Store the gyros turn rate in a vector
Vector3f _accel_vector; // current accel vector
Vector3f _omega_P; // accel Omega proportional correction Vector3f _omega_P; // accel Omega proportional correction
Vector3f _omega_yaw_P; // proportional yaw correction Vector3f _omega_yaw_P; // proportional yaw correction
Vector3f _omega_I; // Omega Integrator correction Vector3f _omega_I; // Omega Integrator correction
@ -102,6 +99,12 @@ private:
float _omega_I_sum_time; float _omega_I_sum_time;
Vector3f _omega; // Corrected Gyro_Vector data Vector3f _omega; // Corrected Gyro_Vector data
// variables to cope with delaying the GA sum to match GPS lag
Vector3f ra_delayed(const Vector3f &ra);
uint8_t _ra_delay_length;
uint8_t _ra_delay_next;
Vector3f *_ra_delay_buffer;
// P term gain based on spin rate // P term gain based on spin rate
float _P_gain(float spin_rate); float _P_gain(float spin_rate);

View File

@ -5,7 +5,7 @@ class AP_AHRS_HIL : public AP_AHRS
{ {
public: public:
// Constructors // Constructors
AP_AHRS_HIL(AP_InertialSensor *ins, GPS *&gps) : AP_AHRS_HIL(AP_InertialSensor &ins, GPS *&gps) :
AP_AHRS(ins, gps), AP_AHRS(ins, gps),
_drift() _drift()
{} {}
@ -21,7 +21,7 @@ public:
// Methods // Methods
void update(void) { void update(void) {
_ins->update(); _ins.update();
} }
void setHil(float roll, float pitch, float yaw, void setHil(float roll, float pitch, float yaw,

View File

@ -48,7 +48,7 @@ GPS *g_gps;
AP_GPS_Auto g_gps_driver(&g_gps); AP_GPS_Auto g_gps_driver(&g_gps);
// choose which AHRS system to use // choose which AHRS system to use
AP_AHRS_DCM ahrs(&ins, g_gps); AP_AHRS_DCM ahrs(ins, g_gps);
AP_Baro_HIL barometer; AP_Baro_HIL barometer;

View File

@ -170,6 +170,7 @@ void AP_Airspeed::read(void)
} }
airspeed_pressure = get_pressure(); airspeed_pressure = get_pressure();
airspeed_pressure = max(airspeed_pressure - _offset, 0); airspeed_pressure = max(airspeed_pressure - _offset, 0);
_last_pressure = airspeed_pressure;
_raw_airspeed = sqrtf(airspeed_pressure * _ratio); _raw_airspeed = sqrtf(airspeed_pressure * _ratio);
_airspeed = 0.7f * _airspeed + 0.3f * _raw_airspeed; _airspeed = 0.7f * _airspeed + 0.3f * _raw_airspeed;
} }

View File

@ -106,7 +106,7 @@ public:
// return the differential pressure in Pascal for the last // return the differential pressure in Pascal for the last
// airspeed reading. Used by the calibration code // airspeed reading. Used by the calibration code
float get_differential_pressure(void) const { float get_differential_pressure(void) const {
return max(_last_pressure - _offset, 0); return max(_last_pressure, 0);
} }
// set the apparent to true airspeed ratio // set the apparent to true airspeed ratio
@ -125,6 +125,9 @@ public:
// log data to MAVLink // log data to MAVLink
void log_mavlink_send(mavlink_channel_t chan, const Vector3f &vground); void log_mavlink_send(mavlink_channel_t chan, const Vector3f &vground);
// return health status of sensor
bool healthy(void) const { return _healthy; }
static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info[];

View File

@ -31,9 +31,17 @@ extern const AP_HAL::HAL& hal;
// probe and initialise the sensor // probe and initialise the sensor
bool AP_Airspeed_I2C::init(void) bool AP_Airspeed_I2C::init(void)
{ {
// get pointer to i2c bus semaphore
AP_HAL::Semaphore* i2c_sem = hal.i2c->get_semaphore();
// take i2c bus sempahore
if (!i2c_sem->take(200))
return false;
_measure(); _measure();
hal.scheduler->delay(10); hal.scheduler->delay(10);
_collect(); _collect();
i2c_sem->give();
if (_last_sample_time_ms != 0) { if (_last_sample_time_ms != 0) {
hal.scheduler->register_timer_process(AP_HAL_MEMBERPROC(&AP_Airspeed_I2C::_timer)); hal.scheduler->register_timer_process(AP_HAL_MEMBERPROC(&AP_Airspeed_I2C::_timer));
return true; return true;
@ -45,16 +53,16 @@ bool AP_Airspeed_I2C::init(void)
void AP_Airspeed_I2C::_measure(void) void AP_Airspeed_I2C::_measure(void)
{ {
_measurement_started_ms = 0; _measurement_started_ms = 0;
if (hal.i2c->writeRegisters(I2C_ADDRESS_MS4525DO, 0, 0, NULL) != 0) { if (hal.i2c->writeRegisters(I2C_ADDRESS_MS4525DO, 0, 0, NULL) == 0) {
return;
}
_measurement_started_ms = hal.scheduler->millis(); _measurement_started_ms = hal.scheduler->millis();
}
} }
// read the values from the sensor // read the values from the sensor
void AP_Airspeed_I2C::_collect(void) void AP_Airspeed_I2C::_collect(void)
{ {
uint8_t data[4]; uint8_t data[4];
_measurement_started_ms = 0; _measurement_started_ms = 0;
if (hal.i2c->read(I2C_ADDRESS_MS4525DO, 4, data) != 0) { if (hal.i2c->read(I2C_ADDRESS_MS4525DO, 4, data) != 0) {
@ -82,8 +90,14 @@ void AP_Airspeed_I2C::_collect(void)
// 1kHz timer // 1kHz timer
void AP_Airspeed_I2C::_timer(void) void AP_Airspeed_I2C::_timer(void)
{ {
AP_HAL::Semaphore* i2c_sem = hal.i2c->get_semaphore();
if (!i2c_sem->take_nonblocking())
return;
if (_measurement_started_ms == 0) { if (_measurement_started_ms == 0) {
_measure(); _measure();
i2c_sem->give();
return; return;
} }
if ((hal.scheduler->millis() - _measurement_started_ms) > 10) { if ((hal.scheduler->millis() - _measurement_started_ms) > 10) {
@ -91,6 +105,7 @@ void AP_Airspeed_I2C::_timer(void)
// start a new measurement // start a new measurement
_measure(); _measure();
} }
i2c_sem->give();
} }
// return the current differential_pressure in Pascal // return the current differential_pressure in Pascal

View File

@ -66,13 +66,13 @@ public:
return _ground_pressure.get(); return _ground_pressure.get();
} }
// get last time sample was taken // get last time sample was taken (in ms)
uint32_t get_last_update() { return _last_update; }; uint32_t get_last_update() { return _last_update; };
static const struct AP_Param::GroupInfo var_info[]; static const struct AP_Param::GroupInfo var_info[];
protected: protected:
uint32_t _last_update; uint32_t _last_update; // in ms
uint8_t _pressure_samples; uint8_t _pressure_samples;
private: private:

View File

@ -88,6 +88,10 @@ void AP_Baro_MS5611_SPI::init()
return; /* never reached */ return; /* never reached */
} }
// now that we have initialised, we set the SPI bus speed to high
// (8MHz on APM2)
_spi->set_bus_speed(AP_HAL::SPIDeviceDriver::SPI_SPEED_HIGH);
} }
uint16_t AP_Baro_MS5611_SPI::read_16bits(uint8_t reg) uint16_t AP_Baro_MS5611_SPI::read_16bits(uint8_t reg)

View File

@ -49,6 +49,7 @@ const AP_Param::GroupInfo AP_BattMonitor::var_info[] PROGMEM = {
// @DisplayName: Battery capacity // @DisplayName: Battery capacity
// @Description: Capacity of the battery in mAh when full // @Description: Capacity of the battery in mAh when full
// @Units: mAh // @Units: mAh
// @Increment: 50
// @User: Standard // @User: Standard
AP_GROUPINFO("CAPACITY", 6, AP_BattMonitor, _pack_capacity, AP_BATT_CAPACITY_DEFAULT), AP_GROUPINFO("CAPACITY", 6, AP_BattMonitor, _pack_capacity, AP_BATT_CAPACITY_DEFAULT),

View File

@ -1,104 +0,0 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/// @file AP_Buffer.h
/// @brief fifo buffer template class
#include <AP_Buffer.h>
#include <stdint.h>
// Constructor
template <class T, uint8_t SIZE>
AP_Buffer<T,SIZE>::AP_Buffer() :
_num_items(0)
{
// clear the buffer
clear();
}
// clear - removes all points from the curve
template <class T, uint8_t SIZE>
void AP_Buffer<T,SIZE>::clear() {
// clear the curve
_num_items = 0;
_head = 0;
}
// add - adds an item to the buffer. returns TRUE if successfully added
template <class T, uint8_t SIZE>
void AP_Buffer<T,SIZE>::add( T item )
{
// determine position of new item
uint8_t tail = _head + _num_items;
if( tail >= SIZE ) {
tail -= SIZE;
}
// add item to buffer
_buff[tail] = item;
// increment number of items
if( _num_items < SIZE ) {
_num_items++;
}else{
// no room for new items so drop oldest item
_head++;
if( _head >= SIZE ) {
_head = 0;
}
}
}
// get - returns the next value in the buffer
template <class T, uint8_t SIZE>
T AP_Buffer<T,SIZE>::get()
{
T result;
// return zero if buffer is empty
if( _num_items == 0 ) {
return 0;
}
// get next value in buffer
result = _buff[_head];
// increment to next point
_head++;
if( _head >= SIZE )
_head = 0;
// reduce number of items
_num_items--;
// return item
return result;
}
// peek - check what the next value in the buffer is but don't pull it off
template <class T, uint8_t SIZE>
T AP_Buffer<T,SIZE>::peek(uint8_t position) const
{
uint8_t j = _head+position;
// return zero if position is out of range
if( position >= _num_items ) {
return 0;
}
// wrap around if necessary
if( j >= SIZE )
j -= SIZE;
// return desired value
return _buff[j];
}
template float AP_Buffer<float,5>::peek(uint8_t position) const;
template AP_Buffer<float, 5>::AP_Buffer();
template void AP_Buffer<float, 5>::clear();
template void AP_Buffer<float, 5>::add(float);
template float AP_Buffer<float,15>::peek(uint8_t position) const;
template AP_Buffer<float, 15>::AP_Buffer();
template void AP_Buffer<float, 15>::clear();
template void AP_Buffer<float, 15>::add(float);

Some files were not shown because too many files have changed in this diff Show More