diff --git a/.gitignore b/.gitignore
index 8e9075ba49..de03b0a607 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.built
+.context
*.context
*.bdat
*.pdat
@@ -43,7 +44,6 @@ nuttx/nuttx.hex
.settings
Firmware.sublime-workspace
.DS_Store
-nsh_romfsimg.h
cscope.out
.configX-e
nuttx-export.zip
@@ -55,3 +55,8 @@ mavlink/include/mavlink/v0.9/
core
.gdbinit
mkdeps
+Archives
+Build
+!ROMFS/*/*.d
+!ROMFS/*/*/*.d
+!ROMFS/*/*/*/*.d
diff --git a/Documentation/control_flow.graffle b/Documentation/control_flow.graffle
new file mode 100644
index 0000000000..2535231108
--- /dev/null
+++ b/Documentation/control_flow.graffle
@@ -0,0 +1,16650 @@
+
+
+
+
+ ApplicationVersion
+
+ com.omnigroup.OmniGraffle
+ 139.16.0.171715
+
+ CreationDate
+ 2013-02-22 17:51:02 +0000
+ Creator
+ Lorenz Meier
+ GraphDocumentVersion
+ 8
+ GuidesLocked
+ NO
+ GuidesVisible
+ YES
+ ImageCounter
+ 1
+ LinksVisible
+ NO
+ MagnetsVisible
+ NO
+ MasterSheets
+
+ ModificationDate
+ 2013-04-20 15:38:47 +0000
+ Modifier
+ Lorenz Meier
+ NotesVisible
+ NO
+ OriginVisible
+ NO
+ PageBreaks
+ YES
+ PrintInfo
+
+ NSBottomMargin
+
+ float
+ 41
+
+ NSHorizonalPagination
+
+ coded
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG
+
+ NSLeftMargin
+
+ float
+ 18
+
+ NSPaperName
+
+ string
+ iso-a3
+
+ NSPaperSize
+
+ size
+ {842, 1191}
+
+ NSPrintReverseOrientation
+
+ int
+ 0
+
+ NSRightMargin
+
+ float
+ 18
+
+ NSTopMargin
+
+ float
+ 18
+
+
+ ReadOnly
+ NO
+ Sheets
+
+
+ ActiveLayerIndex
+ 0
+ AutoAdjust
+
+ BackgroundGraphic
+
+ Bounds
+ {{0, 0}, {806, 1132}}
+ Class
+ SolidGraphic
+ ID
+ 2
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+
+ BaseZoom
+ 0
+ CanvasOrigin
+ {0, 0}
+ ColumnAlign
+ 1
+ ColumnSpacing
+ 36
+ DisplayScale
+ 1 0/72 in = 1.0000 in
+ GraphicsList
+
+
+ Bounds
+ {{320.41170773935767, 646.55758982070449}, {100, 24}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ FontInfo
+
+ Color
+
+ w
+ 0
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 46
+ Line
+
+ ID
+ 45
+ Position
+ 0.49247664213180542
+ RotationType
+ 0
+
+ Shape
+ Rectangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 limited / checked}
+
+ Wrap
+ NO
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 44
+
+ ID
+ 45
+ Points
+
+ {283.47949897905681, 658.66217570036315}
+ {459.99996984645378, 658.44980851233595}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 29
+
+
+
+ Bounds
+ {{460.49996948242188, 640.30001831054688}, {248.00003051757812, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 44
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 ACTUATOR_CONTROLS_EFFECTIVE_0}
+
+
+
+ Bounds
+ {{324, 353.1875}, {120, 28}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 43
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Align
+ 0
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red68\green147\blue53;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs24 \cf2 MAVLink:\
+'MANUAL_CONTROL'}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Bounds
+ {{324, 174.5}, {129, 28}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 42
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Align
+ 0
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red68\green147\blue53;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs24 \cf2 MAVLink:\
+'RC_CHANNELS_RAW'}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Bounds
+ {{114.97958374023438, 786}, {191, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 40
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red68\green147\blue53;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 MAVLink: 'SERVO_OUTPUT_RAW'}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Bounds
+ {{528.5, 689}, {112, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 39
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;\red68\green147\blue53;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf2 MAVLink: 'ctrl eff 0-3'}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 11
+
+ ID
+ 38
+ Points
+
+ {584.52245687751122, 125.49999965650382}
+ {584.56069426576869, 157.00000090441219}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 37
+
+
+
+ Bounds
+ {{448.5, 89}, {272, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 37
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 VEHICLE_GLOBAL_POSITION_SETPOINT /\
+VEHICLE_LOCAL_POSITION_SETPOINT}
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 27
+
+ ID
+ 34
+ Points
+
+ {210.47275259888471, 495.87499981747118}
+ {210.43193555768113, 543.06250166479344}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 10
+
+
+
+ Bounds
+ {{108, 737.9375}, {205, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 33
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 ACTUATOR_OUTPUTS}
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 29
+
+ ID
+ 32
+ Points
+
+ {210.46968123779743, 580.06249992316259}
+ {210.44442316539605, 627.25000030102035}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 27
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 33
+
+ ID
+ 30
+ Points
+
+ {210.48620562018775, 690.25}
+ {210.49612530146715, 737.4375}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 29
+
+
+
+ Bounds
+ {{137.97958374023438, 627.75}, {145, 62}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 29
+ Shape
+ RoundRect
+ Style
+
+ fill
+
+ Color
+
+ b
+ 1
+ g
+ 0.814996
+ r
+ 0.627106
+
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Actuator Mixer}
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{107.97958374023438, 543.5625}, {205, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 27
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 ACTUATOR_CONTROLS_0}
+
+
+
+ Bounds
+ {{394.22506405270201, 452.15000309396282}, {89, 24}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ FontInfo
+
+ Color
+
+ w
+ 0
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 25
+ Line
+
+ ID
+ 22
+ Position
+ 0.5900501012802124
+ RotationType
+ 0
+
+ Shape
+ Rectangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 if in auto mode}
+
+ Wrap
+ NO
+
+
+ Bounds
+ {{152.49994329565658, 397.00120984204113}, {116, 24}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ FontInfo
+
+ Color
+
+ w
+ 0
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 24
+ Line
+
+ ID
+ 17
+ Position
+ 0.49406537413597107
+ RotationType
+ 0
+
+ Shape
+ Rectangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 if in stabilized mode}
+
+ Wrap
+ NO
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 21
+
+ ID
+ 23
+ OrthogonalBarAutomatic
+
+ OrthogonalBarPoint
+ {0, 0}
+ OrthogonalBarPosition
+ -1
+ Points
+
+ {584.49994992834695, 220}
+ {584.4997453697481, 348.6875000000008}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 2
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 11
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 10
+
+ ID
+ 22
+ OrthogonalBarAutomatic
+
+ OrthogonalBarPoint
+ {0, 0}
+ OrthogonalBarPosition
+ 33.206413269042969
+ Points
+
+ {583.83119320765968, 385.68717359526977}
+ {581, 464}
+ {283.49994000956832, 464.30111342104294}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 2
+ Pattern
+ 2
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 21
+
+
+
+ Bounds
+ {{482, 349.1875}, {205, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 21
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 VEHICLE_ATTITUDE_SETPOINT}
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 10
+
+ ID
+ 17
+ Points
+
+ {210.49997491180866, 385.6875}
+ {210.49991091996927, 432.875}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ Pattern
+ 2
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 6
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 5
+
+ ID
+ 16
+ Points
+
+ {283.49999999999511, 270.00001907176534}
+ {339.50000000000028, 270.00001907176534}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 9
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 6
+
+ ID
+ 15
+ Points
+
+ {210.49998770563047, 301.5}
+ {210.49998770563047, 348.6875}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 9
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 9
+
+ ID
+ 13
+ Points
+
+ {210.49171354592596, 207}
+ {210.49498558851923, 238.4999999999998}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 4
+
+
+
+ Class
+ LineGraphic
+ Head
+
+ ID
+ 4
+
+ ID
+ 12
+ Points
+
+ {210.49498558851246, 138.5000000000002}
+ {210.48997117702493, 170.00000000001342}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ FilledArrow
+ Legacy
+
+ LineType
+ 1
+ TailArrow
+ 0
+
+
+ Tail
+
+ ID
+ 8
+
+
+
+ Bounds
+ {{512, 157.5}, {145, 62}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 11
+ Shape
+ RoundRect
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.999136
+ g
+ 0.808554
+ r
+ 0.587078
+
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Position Controller}
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{138, 433.375}, {145, 62}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 10
+ Shape
+ RoundRect
+ Style
+
+ fill
+
+ Color
+
+ b
+ 1
+ g
+ 0.814996
+ r
+ 0.627106
+
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 Attitude Controller}
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{138, 239}, {145, 62}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 9
+ Shape
+ RoundRect
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.366082
+ g
+ 0.639788
+ r
+ 1
+
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 RC scaling and function mapping}
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{138, 76}, {145, 62}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 8
+ Shape
+ RoundRect
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.324773
+ g
+ 0.632962
+ r
+ 0.99252
+
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 RC Input\
+PX4IO or PX4FMU}
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{108, 349.1875}, {205, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 6
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 MANUAL_CONTROL_SETPOINT}
+
+
+
+ Bounds
+ {{340, 252}, {115, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 5
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 RC_CHANNELS}
+
+
+
+ Bounds
+ {{108, 170.5}, {204.97958374023438, 36}}
+ Class
+ ShapedGraphic
+ FontInfo
+
+ Font
+ Helvetica
+ Size
+ 12
+
+ ID
+ 4
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\i\fs24 \cf0 INPUT_RC}
+
+
+
+ GridInfo
+
+ HPages
+ 1
+ KeepToScale
+
+ Layers
+
+
+ Lock
+ NO
+ Name
+ Layer 1
+ Print
+ YES
+ View
+ YES
+
+
+ LayoutInfo
+
+ Animate
+ NO
+ circoMinDist
+ 18
+ circoSeparation
+ 0.0
+ layoutEngine
+ dot
+ neatoSeparation
+ 0.0
+ twopiSeparation
+ 0.0
+
+ Orientation
+ 2
+ PrintOnePage
+
+ RowAlign
+ 1
+ RowSpacing
+ 36
+ SheetTitle
+ Canvas 1
+ UniqueID
+ 1
+ VPages
+ 1
+
+
+ ActiveLayerIndex
+ 0
+ AutoAdjust
+
+ BackgroundGraphic
+
+ Bounds
+ {{0, 0}, {806, 1132}}
+ Class
+ SolidGraphic
+ ID
+ 2
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+
+ BaseZoom
+ 0
+ CanvasOrigin
+ {0, 0}
+ ColumnAlign
+ 1
+ ColumnSpacing
+ 36
+ DisplayScale
+ 1 0/72 in = 1.0000 in
+ GraphicsList
+
+
+ Bounds
+ {{129, 170}, {83, 44}}
+ Class
+ ShapedGraphic
+ ID
+ 4
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ GridInfo
+
+ HPages
+ 1
+ KeepToScale
+
+ Layers
+
+
+ Lock
+ NO
+ Name
+ Layer 1
+ Print
+ YES
+ View
+ YES
+
+
+ LayoutInfo
+
+ Animate
+ NO
+ circoMinDist
+ 18
+ circoSeparation
+ 0.0
+ layoutEngine
+ dot
+ neatoSeparation
+ 0.0
+ twopiSeparation
+ 0.0
+
+ Orientation
+ 2
+ PrintOnePage
+
+ RowAlign
+ 1
+ RowSpacing
+ 36
+ SheetTitle
+ Remote Control
+ UniqueID
+ 5
+ VPages
+ 1
+
+
+ ActiveLayerIndex
+ 0
+ AutoAdjust
+
+ BackgroundGraphic
+
+ Bounds
+ {{0, 0}, {806, 1132}}
+ Class
+ SolidGraphic
+ ID
+ 2
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+
+ BaseZoom
+ 0
+ CanvasOrigin
+ {0, 0}
+ ColumnAlign
+ 1
+ ColumnSpacing
+ 36
+ DisplayScale
+ 1 0/72 in = 1.0000 in
+ GraphicsList
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{575.98995971679688, 379}, {47, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1124
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 QUAD
+\b0 X}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{576.13064904528869, 216.6250047923653}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 1126
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{565.46398168220912, 200.5990128790099}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 1127
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 1125
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{684.97877057518497, 320.1208883952101}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1129
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1131
+ Points
+
+ {744.59415627118847, 308.1935744741462}
+ {742.38444757998036, 309.34262299357425}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{656.69108999710829, 361.8760779997491}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1132
+ Rotation
+ 45
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{646.29122523639319, 281.66198172978545}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1133
+ Rotation
+ 135
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{643.54122523639319, 278.91198172978545}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1134
+ Rotation
+ 135
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1130
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1136
+ Points
+
+ {649.54722336322868, 356.21791362626482}
+ {651.75693205443667, 355.0688651068366}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{721.45028963730863, 284.03541010066203}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1137
+ Rotation
+ 225
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{646.35015439802385, 281.24950637062551}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1138
+ Rotation
+ 315
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{643.60015439802385, 278.49950637062551}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1139
+ Rotation
+ 315
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1135
+ Rotation
+ 315
+
+
+ Bounds
+ {{646.0670873832953, 281.20919655324775}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1140
+ Rotation
+ 315
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1128
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{494.01518801866729, 320.05486147948341}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1142
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1144
+ Points
+
+ {458.75335031844725, 307.77399956263616}
+ {460.96305900965541, 308.92304808206421}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{530.65641659252742, 361.45650308823895}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1145
+ Rotation
+ 135
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{455.55628135324292, 281.24240681827519}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1146
+ Rotation
+ 45
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{452.80628135324292, 278.49240681827519}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1147
+ Rotation
+ 45
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1143
+ Rotation
+ 225
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1149
+ Points
+
+ {553.44673702887792, 356.15188491228344}
+ {551.23702833767004, 355.00283639285527}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{465.54367075479814, 283.96938138668088}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1150
+ Rotation
+ 315
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{455.14380599408253, 281.1834776566443}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1151
+ Rotation
+ 225
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{452.39380599408253, 278.4334776566443}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1152
+ Rotation
+ 225
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1148
+ Rotation
+ 225
+ VFlip
+ YES
+
+
+ Bounds
+ {{455.10349617670488, 281.1431681805102}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1153
+ Rotation
+ 225
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1141
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{684.74305392865585, 129.32699556949493}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1155
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1157
+ Points
+
+ {649.48121622843564, 117.04613365264774}
+ {651.69092491964352, 118.19518217207589}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{721.38428250251582, 170.72863717825052}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1158
+ Rotation
+ 135
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{646.28414726323126, 90.514540908286847}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1159
+ Rotation
+ 45
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{643.53414726323126, 87.764540908286847}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1160
+ Rotation
+ 45
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1156
+ Rotation
+ 225
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1162
+ Points
+
+ {744.17460293886643, 165.42401900229501}
+ {741.96489424765866, 164.27497048286693}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{656.27153666478659, 93.241515476692427}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1163
+ Rotation
+ 315
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{645.87167190407115, 90.455611746655876}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1164
+ Rotation
+ 225
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{643.12167190407115, 87.705611746655876}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1165
+ Rotation
+ 225
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1161
+ Rotation
+ 225
+ VFlip
+ YES
+
+
+ Bounds
+ {{645.83136208669339, 90.415302270521892}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1166
+ Rotation
+ 225
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1154
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{494.00811680064464, 129.15022794494948}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1168
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1170
+ Points
+
+ {553.62350249664826, 117.22291402388569}
+ {551.41379380544015, 118.37196254331369}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{465.72043622256808, 170.9054175494887}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1171
+ Rotation
+ 45
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{455.32057146185286, 90.691321279524772}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1172
+ Rotation
+ 135
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{452.57057146185286, 87.941321279524772}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1173
+ Rotation
+ 135
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1169
+ Rotation
+ 315
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1175
+ Points
+
+ {458.57656958868847, 165.24725317600405}
+ {460.78627827989641, 164.09820465657594}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{530.47963586276819, 93.064749650401353}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1176
+ Rotation
+ 225
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{455.37950062348352, 90.278845920365001}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1177
+ Rotation
+ 315
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{452.62950062348352, 87.528845920365001}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1178
+ Rotation
+ 315
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1174
+ Rotation
+ 315
+
+
+ Bounds
+ {{455.09643360875504, 90.238536102987126}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1179
+ Rotation
+ 315
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1167
+ Rotation
+ 315
+
+
+ Bounds
+ {{547.25939156789127, 219.8035943432547}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1180
+ Rotation
+ 225
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{647.66855809291212, 119.39442062517122}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1181
+ Rotation
+ 225
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{647.66855089985006, 219.80357636059938}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1182
+ Rotation
+ 315
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{547.20046240626141, 119.33550225313491}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1183
+ Rotation
+ 315
+ Shape
+ Rectangle
+
+
+ ID
+ 1123
+
+
+ Bounds
+ {{287.14883422851562, 373}, {46, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1121
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 QUAD
+\b0 +}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{252.93672553699014, 864.96332065264312}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1186
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 6}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1188
+ Points
+
+ {248.68672172228349, 826.3749926090228}
+ {249.43672172228361, 828.7499926090228}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{252.68672172228372, 918.12499260902291}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1189
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{214.43672172228372, 826.3749926090228}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1190
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{211.68672172228372, 823.6249926090228}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1191
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1187
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1193
+ Points
+
+ {281.43672680854809, 927.54165927568897}
+ {280.6867268085482, 925.1666592756892}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{261.43672680854797, 817.2916592756892}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1194
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{214.18672680854797, 826.0416592756892}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1195
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{211.43672680854797, 823.2916592756892}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1196
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1192
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{214.02503832182103, 826.05162629068673}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1197
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1185
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{255.93671290080545, 636.38001505533919}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1199
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 5}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1201
+ Points
+
+ {251.6867090860988, 597.79168701171886}
+ {252.43670908609892, 600.16668701171886}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{255.68670908609903, 689.54168701171898}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1202
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{217.43670908609903, 597.79168701171886}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1203
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{214.68670908609903, 595.04168701171886}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1204
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1200
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1206
+ Points
+
+ {284.43671417236339, 698.95835367838504}
+ {283.68671417236351, 696.58335367838527}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{264.43671417236328, 588.70835367838527}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1207
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{217.18671417236328, 597.45835367838527}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1208
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{214.43671417236328, 594.70835367838527}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1209
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1205
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{217.02502568563636, 597.46832069338279}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1210
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1198
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{480.49999872844216, 864.96333555380545}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1212
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1214
+ Points
+
+ {476.24999491373552, 826.37500751018513}
+ {476.99999491373563, 828.75000751018513}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{480.24999491373575, 918.12500751018524}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1215
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.99999491373575, 826.37500751018513}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1216
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{439.24999491373575, 823.62500751018513}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1217
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1213
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1219
+ Points
+
+ {509.00000000000011, 927.5416741768513}
+ {508.25000000000023, 925.16667417685153}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{489, 817.29167417685153}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1220
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.75, 826.04167417685153}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1221
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{439, 823.29167417685153}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1222
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1218
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.58831151327308, 826.05164119184906}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1223
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1211
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{480.49999872844216, 636.38001505533896}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1225
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1227
+ Points
+
+ {476.24999491373552, 597.79168701171864}
+ {476.99999491373563, 600.16668701171864}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{480.24999491373575, 689.54168701171875}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1228
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.99999491373575, 597.79168701171864}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1229
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{439.24999491373575, 595.04168701171864}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1230
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1226
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1232
+ Points
+
+ {509.00000000000011, 698.95835367838481}
+ {508.25000000000023, 696.58335367838504}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{489, 588.70835367838504}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1233
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.75, 597.45835367838504}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1234
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{439, 594.70835367838504}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1235
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1231
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.58831151327308, 597.46832069338257}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1236
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1224
+
+
+ Bounds
+ {{452.7625732421875, 947.72591400146473}, {45, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1237
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 OCTO
+\b0 +}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{353.51001119036124, 739.42163658141953}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 1239
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{342.8433593880041, 726.66665752440122}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 1240
+ Rotation
+ 45
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 1238
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{366.83836873372331, 916.58333714803678}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1242
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1244
+ Points
+
+ {429.42669677734398, 945.3333333333303}
+ {427.05169677734398, 944.58333333333019}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{320.42669677734375, 924.08333333333019}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1245
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{327.92669677734398, 878.08333333333019}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1246
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{325.17669677734398, 875.33333333333019}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1247
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1243
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1249
+ Points
+
+ {328.26003011067723, 912.08333841959472}
+ {330.63503011067723, 912.83333841959472}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{421.26003011067723, 914.83333841959472}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1250
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{328.26003011067723, 877.83333841959472}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1251
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{325.51003011067723, 875.08333841959472}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1252
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1248
+
+
+ Bounds
+ {{327.92668660481695, 877.67164993286758}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1253
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1241
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{205.66167195637968, 750.54168065389615}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1255
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 7}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1257
+ Points
+
+ {268.25000000000023, 779.29167683918968}
+ {265.87500000000023, 778.54167683918956}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{159.24999999999994, 758.04167683918956}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1258
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{166.75, 712.04167683918956}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1259
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{164, 709.29167683918956}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1260
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1256
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1262
+ Points
+
+ {167.08333333333348, 746.0416819254541}
+ {169.45833333333348, 746.7916819254541}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{260.08333333333348, 748.7916819254541}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1263
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{167.08333333333348, 711.7916819254541}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1264
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{164.33333333333348, 709.0416819254541}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1265
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1261
+
+
+ Bounds
+ {{166.74998982747337, 711.62999343872696}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1266
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1254
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{528.01506551106706, 750.54168065389615}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1268
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 8}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1270
+ Points
+
+ {590.60339355468773, 779.29167683918968}
+ {588.22839355468773, 778.54167683918956}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{481.6033935546875, 758.04167683918956}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1271
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{489.10339355468773, 712.04167683918956}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1272
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{486.35339355468773, 709.29167683918956}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1273
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1269
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1275
+ Points
+
+ {489.43672688802098, 746.0416819254541}
+ {491.81172688802098, 746.7916819254541}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{582.43672688802098, 748.7916819254541}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1276
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{489.43672688802098, 711.7916819254541}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1277
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{486.68672688802098, 709.0416819254541}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1278
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1274
+
+
+ Bounds
+ {{489.10338338216064, 711.62999343872696}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1279
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1267
+
+
+ Bounds
+ {{306.14882584901056, 766.45459545146662}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1280
+ Rotation
+ 225
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{468.3533935546875, 695.66666666666504}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1281
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{440.55795213074884, 760.88380015384382}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1282
+ Rotation
+ 135
+ Shape
+ Rectangle
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{366.83834838867119, 584.49999872844194}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1284
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1286
+ Points
+
+ {429.42667643229174, 613.24999491373558}
+ {427.05167643229174, 612.49999491373546}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{320.42667643229152, 591.99999491373546}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1287
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{327.92667643229174, 545.99999491373546}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1288
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{325.17667643229174, 543.24999491373546}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1289
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1285
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1291
+ Points
+
+ {328.26000976562511, 579.99999999999977}
+ {330.63500976562511, 580.74999999999977}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{421.260009765625, 582.74999999999977}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1292
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{328.26000976562523, 545.74999999999977}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1293
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{325.51000976562523, 542.99999999999977}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1294
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1290
+
+
+ Bounds
+ {{327.92666625976494, 545.58831151327263}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1295
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1283
+
+
+ Bounds
+ {{281.3533935546875, 695.66666666666504}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1296
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{442.5579845556756, 629.04542696963983}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1297
+ Rotation
+ 225
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{374.84336344400776, 790.58333841959472}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1298
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{374.84335708617891, 600.24999491373535}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1299
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{309.12873002381525, 629.45457637798029}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1300
+ Rotation
+ 135
+ Shape
+ Rectangle
+
+
+ ID
+ 1184
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{181.15661763567644, 222.11968549092626}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 1024
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{170.4899658333193, 209.364706433908}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 1025
+ Rotation
+ 45
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 1023
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{194.48495483398159, 368.44802729289523}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1027
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1029
+ Points
+
+ {257.0732828776022, 397.19802347818882}
+ {254.69828287760208, 396.4480234781887}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{148.07328287760188, 375.9480234781887}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1030
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{155.57328287760205, 329.9480234781887}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1031
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{152.82328287760205, 327.1980234781887}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1032
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1028
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1034
+ Points
+
+ {155.90661621093548, 363.94802856445312}
+ {158.28161621093548, 364.69802856445312}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{248.90661621093545, 366.69802856445312}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1035
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{155.90661621093548, 329.69802856445312}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1036
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{153.15661621093548, 326.94802856445312}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1037
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1033
+
+
+ Bounds
+ {{155.57327270507534, 329.53634007772598}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1038
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1026
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{59.499998728441994, 233.36969502765339}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1040
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1042
+ Points
+
+ {55.249994913735321, 194.78136698403296}
+ {55.999994913735435, 197.1563669840329}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{59.249994913735435, 286.53136698403307}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1043
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{20.999994913735549, 194.78136698403301}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1044
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{18.249994913735549, 192.03136698403301}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1045
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1041
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1047
+ Points
+
+ {87.999999999999915, 295.9480336506993}
+ {87.250000000000028, 293.57303365069941}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{67.999999999999915, 185.69803365069959}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1048
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{20.749999999999915, 194.44803365069947}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1049
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{17.999999999999915, 191.69803365069947}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1050
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1046
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{20.588311513272686, 194.45800066569694}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1051
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1039
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{329.22993342082486, 233.36969502765339}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1053
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1055
+ Points
+
+ {324.97992960611816, 194.7813669840329}
+ {325.72992960611828, 197.15636698403287}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{328.97992960611828, 286.53136698403307}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1056
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{290.72992960611839, 194.78136698403301}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1057
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{287.97992960611839, 192.03136698403301}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1058
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1054
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1060
+ Points
+
+ {357.72993469238281, 295.9480336506993}
+ {356.97993469238293, 293.57303365069941}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{337.72993469238281, 185.69803365069953}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1061
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{290.47993469238281, 194.44803365069947}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1062
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{287.72993469238281, 191.69803365069947}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1063
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1059
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{290.31824620565556, 194.45800066569686}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1064
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1052
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{194.48495483398159, 92.448027292895233}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1066
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1068
+ Points
+
+ {257.0732828776022, 121.19802347818882}
+ {254.69828287760208, 120.4480234781887}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{148.07328287760188, 99.948023478188702}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1069
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{155.57328287760205, 53.948023478188688}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1070
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{152.82328287760205, 51.198023478188688}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1071
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1067
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1073
+ Points
+
+ {155.90661621093548, 87.948028564453111}
+ {158.28161621093548, 88.698028564453111}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{248.90661621093545, 90.698028564453111}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1074
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{155.90661621093548, 53.698028564453111}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1075
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{153.15661621093548, 50.948028564453111}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1076
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1072
+
+
+ Bounds
+ {{155.57327270507534, 53.536340077725967}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1077
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1065
+
+
+ Bounds
+ {{131.48995971679412, 178.36470031738281}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1078
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{273.48996988932043, 178.36469523111947}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1079
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{202.48996988932029, 249.36468505859375}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1080
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{202.48995971679412, 107.28136189778644}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1081
+ Shape
+ Rectangle
+
+
+ ID
+ 1022
+
+
+ GridInfo
+
+ HPages
+ 1
+ KeepToScale
+
+ Layers
+
+
+ Lock
+ NO
+ Name
+ Layer 1
+ Print
+ YES
+ View
+ YES
+
+
+ LayoutInfo
+
+ Animate
+ NO
+ circoMinDist
+ 18
+ circoSeparation
+ 0.0
+ layoutEngine
+ dot
+ neatoSeparation
+ 0.0
+ twopiSeparation
+ 0.0
+
+ Orientation
+ 2
+ PrintOnePage
+
+ RowAlign
+ 1
+ RowSpacing
+ 36
+ SheetTitle
+ Rotor Assignments
+ UniqueID
+ 2
+ VPages
+ 1
+
+
+ ActiveLayerIndex
+ 0
+ AutoAdjust
+
+ BackgroundGraphic
+
+ Bounds
+ {{0, 0}, {806, 1132}}
+ Class
+ SolidGraphic
+ ID
+ 2
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+
+ BaseZoom
+ 0
+ CanvasOrigin
+ {0, 0}
+ ColumnAlign
+ 1
+ ColumnSpacing
+ 36
+ DisplayScale
+ 1 0/72 in = 1.0000 in
+ GraphicsList
+
+
+ Bounds
+ {{479, 926}, {45, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1210
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 HEXA
+\b0 X}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{323.13577025880016, 749.76557170439401}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 1124
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{312.46911845644303, 737.01059264737569}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 1125
+ Rotation
+ 45
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 1123
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{407.17230315305846, 883.72204834096681}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1127
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1129
+ Points
+
+ {379.80522301611819, 860.03627302756399}
+ {381.64224206895665, 861.71808336155198}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{432.69752786153174, 932.25483880979243}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1130
+ Rotation
+ 150
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{368.7196421785618, 844.9870622696244}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1131
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{365.9696421785618, 842.2370622696244}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1132
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1128
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1134
+ Points
+
+ {458.75089272822612, 931.27417383395721}
+ {456.91387367538789, 929.59236349996911}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{389.85858788281303, 840.55560805172911}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1135
+ Rotation
+ 330
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{368.33647356578285, 844.82338459189691}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1136
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{365.58647356578285, 842.07338459189691}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1137
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1133
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Bounds
+ {{368.26061274159781, 844.81035428333826}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1138
+ Rotation
+ 240
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1126
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{267.75726457856609, 881.27816449485533}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1140
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 6}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1142
+ Points
+
+ {331.94303989196902, 882.48992268280176}
+ {329.51122955798087, 883.02790362996325}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{230.47447410974044, 913.3476178373885}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1143
+ Rotation
+ 60
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{228.99225064990861, 842.82550352035832}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1144
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{226.24225064990861, 840.07550352035832}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1145
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1141
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1147
+ Points
+
+ {227.70513908557558, 904.27791574513662}
+ {230.13694941956365, 903.73993479797491}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{313.17370486780385, 854.92022059054989}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1148
+ Rotation
+ 240
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{229.15592832763582, 842.44233490757972}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1149
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{226.40592832763582, 839.69233490757972}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1150
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1146
+ Rotation
+ 330
+
+
+ Bounds
+ {{228.84558214533197, 842.36647408339456}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1151
+ Rotation
+ 330
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1139
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{474.97119637474935, 761.64314519248808}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1153
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1155
+ Points
+
+ {539.15697168815223, 762.85490338043462}
+ {536.72516135416413, 763.39288432759611}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{437.68840590592367, 793.71259853502136}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1156
+ Rotation
+ 60
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{436.20618244609187, 723.19048421799118}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1157
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{433.45618244609187, 720.44048421799118}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1158
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1154
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1160
+ Points
+
+ {434.91907088175884, 784.64289644276937}
+ {437.35088121574688, 784.10491549560766}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{520.38763666398711, 735.28520128818252}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1161
+ Rotation
+ 240
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{436.36986012381902, 722.80731560521247}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1162
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{433.61986012381902, 720.05731560521247}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1163
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1159
+ Rotation
+ 330
+
+
+ Bounds
+ {{436.05951394151521, 722.73145478102731}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1164
+ Rotation
+ 330
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1152
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{197.82245308809811, 760.38763453076365}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1166
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1168
+ Points
+
+ {170.45537295115798, 736.70185921736106}
+ {172.29239200399638, 738.38366955134893}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{223.34767779657142, 808.92042499958939}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1169
+ Rotation
+ 150
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{159.36979211360145, 721.65264845942124}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1170
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{156.61979211360145, 718.90264845942124}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1171
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1167
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1173
+ Points
+
+ {249.4010426632658, 807.93976002375393}
+ {247.56402361042768, 806.25794968976606}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{180.50873781785265, 717.22119424152584}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1174
+ Rotation
+ 330
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{158.98662350082267, 721.48897078169387}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1175
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{156.23662350082267, 718.73897078169387}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1176
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1172
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Bounds
+ {{158.91076267663743, 721.47594047313521}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1177
+ Rotation
+ 240
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1165
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{405.7864385681853, 642.051622339657}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1179
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 5}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1181
+ Points
+
+ {378.41935843124503, 618.36584702625407}
+ {380.25637748408349, 620.04765736024217}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{431.31166327665852, 690.58441280848263}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1182
+ Rotation
+ 150
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{367.33377759368858, 603.3166362683146}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1183
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{364.58377759368858, 600.5666362683146}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1184
+ Rotation
+ 60
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1180
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1186
+ Points
+
+ {457.36502814335307, 689.6037478326474}
+ {455.52800909051496, 687.92193749865953}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{388.47272329793987, 598.8851820504193}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1187
+ Rotation
+ 330
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{366.95060898090981, 603.15295859058722}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1188
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{364.20060898090981, 600.40295859058722}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1189
+ Rotation
+ 240
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1185
+ Rotation
+ 240
+ VFlip
+ YES
+
+
+ Bounds
+ {{366.87474815672459, 603.13992828202845}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1190
+ Rotation
+ 240
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1178
+ Rotation
+ 330
+
+
+ Bounds
+ {{416.05401025695778, 706.97194681357246}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1191
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{273.20840928884093, 706.24568349439642}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1192
+ Rotation
+ 270
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{309.23428435411637, 768.64435011115415}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1193
+ Rotation
+ 30
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{380.02813770004576, 644.57328454142464}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1194
+ Rotation
+ 30
+ Shape
+ Rectangle
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{268.61421230672084, 643.49244485638758}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1196
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1198
+ Points
+
+ {332.79998762012377, 644.70420304433412}
+ {330.36817728613562, 645.24218399149561}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{231.33142183789516, 675.56189819892086}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1199
+ Rotation
+ 60
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{229.84919837806336, 605.03978388189068}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1200
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{227.09919837806336, 602.28978388189068}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1201
+ Rotation
+ 150
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1197
+ Rotation
+ 330
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1203
+ Points
+
+ {228.56208681373033, 666.49219610666887}
+ {230.99389714771837, 665.95421515950716}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{314.03065259595854, 617.13450095208213}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1204
+ Rotation
+ 240
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{230.01287605579051, 604.65661526911197}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1205
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{227.26287605579051, 601.90661526911197}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1206
+ Rotation
+ 330
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1202
+ Rotation
+ 330
+
+
+ Bounds
+ {{229.7025298734867, 604.58075444492681}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1207
+ Rotation
+ 330
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1195
+ Rotation
+ 330
+
+
+ Bounds
+ {{380.57688435489479, 768.55104482376805}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1208
+ Rotation
+ 330
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{309.53521396482506, 645.50328259865807}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1209
+ Rotation
+ 330
+ Shape
+ Rectangle
+
+
+ ID
+ 1122
+ Rotation
+ 330
+
+
+ Bounds
+ {{431, 450}, {44, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1121
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 HEXA
+\b0 +}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{326.15660523791308, 258.95613225301122}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 320
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{315.48995343555595, 246.20115319599296}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 321
+ Rotation
+ 45
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 319
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{339.36497966449247, 411.82398351031941}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 323
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 325
+ Points
+
+ {335.11497584978588, 373.23565546669897}
+ {335.86497584978599, 375.61065546669897}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{339.11497584978599, 464.98565546669914}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 326
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{300.86497584978611, 373.23565546669909}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 327
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{298.11497584978611, 370.48565546669909}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 328
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 324
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 330
+ Points
+
+ {367.86498093605042, 474.40232213336532}
+ {367.11498093605053, 472.02732213336543}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{347.86498093605042, 364.15232213336554}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 331
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{300.61498093605042, 372.90232213336543}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 332
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{297.86498093605042, 370.15232213336543}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 333
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 329
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{300.45329244932327, 372.91228914836296}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 334
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 322
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{219.84995651245046, 339.99999872844211}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 336
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 338
+ Points
+
+ {282.43828455607104, 368.74999491373569}
+ {280.06328455607098, 367.99999491373558}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{173.43828455607076, 347.49999491373558}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 339
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{180.93828455607093, 301.49999491373558}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 340
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{178.18828455607093, 298.74999491373558}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 341
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 337
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 343
+ Points
+
+ {181.27161788940435, 335.5}
+ {183.64661788940435, 336.25}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{274.2716178894043, 338.25}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 344
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{181.27161788940435, 301.25}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 345
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{178.52161788940435, 298.5}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 346
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 342
+
+
+ Bounds
+ {{180.93827438354421, 301.08831151327286}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 347
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 335
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{459.11999511718477, 339.99999872844211}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 349
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 6}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 351
+ Points
+
+ {521.70832316080532, 368.74999491373569}
+ {519.33332316080532, 367.99999491373558}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{412.70832316080504, 347.49999491373558}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 352
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{420.20832316080521, 301.49999491373558}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 353
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{417.45832316080521, 298.74999491373558}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 354
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 350
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 356
+ Points
+
+ {420.54165649413864, 335.5}
+ {422.91665649413864, 336.25}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{513.54165649413858, 338.25}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 357
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{420.54165649413864, 301.25}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 358
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{417.79165649413864, 298.5}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 359
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 355
+
+
+ Bounds
+ {{420.20831298827852, 301.08831151327286}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 360
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 348
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{219.72989813487507, 200.33832295734095}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 362
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 5}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 364
+ Points
+
+ {215.47989432016846, 161.74999491372051}
+ {216.22989432016857, 164.12499491372046}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{219.47989432016857, 253.49999491372063}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 365
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{181.22989432016868, 161.74999491372057}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 366
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{178.47989432016868, 158.99999491372057}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 367
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 363
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 369
+ Points
+
+ {248.22989940643305, 262.91666158038686}
+ {247.47989940643316, 260.54166158038697}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{228.22989940643305, 152.66666158038709}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 370
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{180.97989940643305, 161.41666158038697}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 371
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{178.22989940643305, 158.66666158038697}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 372
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 368
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{180.81821091970582, 161.42662859538444}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 373
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 361
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{458.99999872844205, 201.83832295734095}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 375
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 377
+ Points
+
+ {454.74999491373541, 163.24999491372051}
+ {455.49999491373552, 165.62499491372046}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{458.74999491373552, 254.99999491372063}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 378
+ Rotation
+ 180
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{420.49999491373563, 163.24999491372057}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 379
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{417.74999491373563, 160.49999491372057}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 380
+ Rotation
+ 90
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 376
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 382
+ Points
+
+ {487.5, 264.41666158038686}
+ {486.75000000000011, 262.04166158038697}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{467.5, 154.16666158038709}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 383
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{420.25, 162.91666158038697}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 384
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{417.5, 160.16666158038697}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 385
+ Rotation
+ 270
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 381
+ Rotation
+ 270
+ VFlip
+ YES
+
+
+ Bounds
+ {{420.0883115132728, 162.92662859538444}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 386
+ Rotation
+ 270
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 374
+
+
+ Bounds
+ {{409.00361117886365, 251.82615622621091}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 387
+ Rotation
+ 300
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{285.65882358120746, 179.77439325790914}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 388
+ Rotation
+ 300
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{285.65881327292152, 251.82616124293514}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 389
+ Rotation
+ 60
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{409.00362148715112, 179.77439325790914}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 390
+ Rotation
+ 60
+ Shape
+ Rectangle
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{339.48495483398165, 134.49999872844211}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 392
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 394
+ Points
+
+ {402.0732828776022, 163.24999491373569}
+ {399.69828287760214, 162.49999491373558}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{293.07328287760191, 141.99999491373558}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 395
+ Rotation
+ 90
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{300.57328287760208, 95.999994913735577}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 396
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{297.82328287760208, 93.249994913735577}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 397
+ Rotation
+ 180
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 393
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 399
+ Points
+
+ {300.90661621093551, 130}
+ {303.28161621093551, 130.75}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{393.90661621093545, 132.75}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 400
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{300.90661621093551, 95.75}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 401
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{298.15661621093551, 93}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 402
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 398
+
+
+ Bounds
+ {{300.5732727050754, 95.588311513272842}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 403
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 391
+
+
+ Bounds
+ {{347.48996988932038, 287.41665649414062}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 404
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{347.4899597167942, 145.33333333333331}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 405
+ Shape
+ Rectangle
+
+
+ ID
+ 318
+
+
+ GridInfo
+
+ HPages
+ 1
+ KeepToScale
+
+ Layers
+
+
+ Lock
+ NO
+ Name
+ Layer 1
+ Print
+ YES
+ View
+ YES
+
+
+ LayoutInfo
+
+ Animate
+ NO
+ circoMinDist
+ 18
+ circoSeparation
+ 0.0
+ layoutEngine
+ dot
+ neatoSeparation
+ 0.0
+ twopiSeparation
+ 0.0
+
+ Orientation
+ 2
+ PrintOnePage
+
+ RowAlign
+ 1
+ RowSpacing
+ 36
+ SheetTitle
+ Rotor Assignment 2
+ UniqueID
+ 3
+ VPages
+ 1
+
+
+ ActiveLayerIndex
+ 0
+ AutoAdjust
+
+ BackgroundGraphic
+
+ Bounds
+ {{0, 0}, {806, 1132}}
+ Class
+ SolidGraphic
+ ID
+ 2
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+
+ BaseZoom
+ 0
+ CanvasOrigin
+ {0, 0}
+ ColumnAlign
+ 1
+ ColumnSpacing
+ 36
+ DisplayScale
+ 1 0/72 in = 1.0000 in
+ GraphicsList
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{317.51000800051321, 240.42163882949882}, {50.666667938232422, 36}}
+ Class
+ ShapedGraphic
+ ID
+ 1417
+ Rotation
+ 270
+ Shape
+ HorizontalTriangle
+ Style
+
+ fill
+
+ Color
+
+ b
+ 0.13195
+ g
+ 0.165669
+ r
+ 1
+
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{306.84335619815613, 227.6666597724805}, {72, 72}}
+ Class
+ ShapedGraphic
+ ID
+ 1418
+ Rotation
+ 45
+ Shape
+ Rectangle
+ Style
+
+ stroke
+
+ CornerRadius
+ 9
+
+
+
+
+ ID
+ 1416
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{181.87174317649047, 313.76849034719959}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1421
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 6}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1423
+ Points
+
+ {159.49938242361688, 285.249576623557}
+ {161.10116522486757, 287.15677793899749}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{201.23696348262672, 364.71920821881605}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1424
+ Rotation
+ 157.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{143.41457890258161, 275.07218626448082}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1425
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{140.66457890258161, 272.32218626448082}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1426
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1422
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1428
+ Points
+
+ {228.47124867019181, 366.1825051496383}
+ {226.8694658689414, 364.27530383419804}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{170.73366761118237, 268.21287355437971}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1429
+ Rotation
+ 337.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{143.05605219122737, 274.85989550871483}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1430
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{140.30605219122737, 272.10989550871483}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1431
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1427
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Bounds
+ {{142.96005354220407, 274.85679605657162}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1432
+ Rotation
+ 247.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1420
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{272.11841406704639, 103.73309829351469}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1434
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 5}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1436
+ Points
+
+ {249.74605331417285, 75.214184569872145}
+ {251.34783611542343, 77.121385885312606}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{291.48363437318255, 154.68381616513099}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1437
+ Rotation
+ 157.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{233.66124979313764, 65.036794210795819}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1438
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{230.91124979313764, 62.286794210795819}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1439
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1435
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1441
+ Points
+
+ {318.71791956074799, 156.14711309595339}
+ {317.11613675949758, 154.23991178051318}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{260.98033850173846, 58.177481500694711}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1442
+ Rotation
+ 337.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{233.30272308178348, 64.824503455029671}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1443
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{230.55272308178348, 62.074503455029671}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1444
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1440
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Bounds
+ {{233.20672443276007, 64.821404002886837}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1445
+ Rotation
+ 247.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1433
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{392.11278792691934, 400.85319857921803}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1447
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 4}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1449
+ Points
+
+ {369.74042717404592, 372.33428485557562}
+ {371.34220997529656, 374.24148617101616}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{411.47800823305562, 451.80391645083449}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1450
+ Rotation
+ 157.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{353.65562365301071, 362.15689449649926}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1451
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{350.90562365301071, 359.40689449649926}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1452
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1448
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1454
+ Points
+
+ {438.71229342062088, 453.26721338165692}
+ {437.11051061937059, 451.36001206621654}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{380.97471236161118, 355.29758178639815}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1455
+ Rotation
+ 337.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{353.29709694165621, 361.94460374073327}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1456
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{350.54709694165621, 359.19460374073327}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1457
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1453
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Bounds
+ {{353.20109829263305, 361.94150428859024}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1458
+ Rotation
+ 247.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1446
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{479.58783759318999, 189.66974728965576}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1460
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 3}
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1462
+ Points
+
+ {457.21547665220845, 161.15083366194582}
+ {458.81725945345897, 163.05803497738634}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{498.95305771121809, 240.62046525720473}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1463
+ Rotation
+ 157.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{441.13067313117307, 150.9734433028697}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1464
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{438.38067313117307, 148.2234433028697}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1465
+ Rotation
+ 67.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1461
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1467
+ Points
+
+ {526.18734328198354, 242.08376201128482}
+ {524.58556048073308, 240.17656069584442}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{468.44976222297396, 144.11413041602617}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1468
+ Rotation
+ 337.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ Bounds
+ {{440.77214680301904, 150.76115237036112}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1469
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ Bounds
+ {{438.02214680301904, 148.01115237036112}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1470
+ Rotation
+ 247.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+ VFlip
+ YES
+
+
+ ID
+ 1466
+ Rotation
+ 247.5
+ VFlip
+ YES
+
+
+ Bounds
+ {{440.67614795890404, 150.75805299902771}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1471
+ Rotation
+ 247.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.673128
+ g
+ 0.534129
+ r
+ 0.217952
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ VFlip
+ YES
+
+
+ ID
+ 1459
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{324.9947377700048, 478.76189426912856}, {46, 14}}
+ Class
+ ShapedGraphic
+ FitText
+ YES
+ Flow
+ Resize
+ ID
+ 1472
+ Shape
+ Rectangle
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ Pad
+ 0
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\b\fs24 \cf0 OCTO
+\b0 X}
+ VerticalPad
+ 0
+
+ Wrap
+ NO
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{267.24952227247923, 404.95559172255122}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1474
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 2}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1476
+ Points
+
+ {332.396988909622, 413.07125181593568}
+ {329.91576246001244, 413.28721548361688}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{226.49295677281663, 431.38573061302958}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1477
+ Rotation
+ 67.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{228.4458262787623, 366.49842726410935}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1478
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{225.6958262787623, 363.74842726410935}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1479
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1475
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1481
+ Points
+
+ {226.20695455654064, 421.06707636999505}
+ {228.68818100615007, 420.8511127023138}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{316.11098669334581, 384.25259757290121}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1482
+ Rotation
+ 247.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{228.65811718740025, 366.13990092182132}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1483
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{225.90811718740025, 363.38990092182132}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1484
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1480
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{228.33784007224426, 366.04390208826476}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1485
+ Rotation
+ 337.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1473
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{181.88306202487647, 189.87345220332375}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1487
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 7}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1489
+ Points
+
+ {247.03052866201915, 197.98911229670802}
+ {244.5493022124096, 198.20507596438921}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{141.12649652521372, 216.30359109380208}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1490
+ Rotation
+ 67.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{143.07936603115925, 151.41628774488177}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1491
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{140.32936603115925, 148.66628774488177}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1492
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1488
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1494
+ Points
+
+ {140.84049430893771, 205.98493685076758}
+ {143.32172075854714, 205.76897318308625}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{230.74452644574279, 169.17045805367366}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1495
+ Rotation
+ 247.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{143.29165693979732, 151.05776140259383}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1496
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{140.54165693979732, 148.30776140259383}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1497
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1493
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{142.97137982464162, 150.96176256903718}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1498
+ Rotation
+ 337.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1486
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{479.69876456560792, 313.23275528336626}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1500
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 8}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1502
+ Points
+
+ {544.84623120275069, 321.34841537675055}
+ {542.36500475314142, 321.56437904443163}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{438.94219906594537, 339.66289417384445}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1503
+ Rotation
+ 67.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{440.89506857189104, 274.77559082492428}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1504
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{438.14506857189104, 272.02559082492428}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1505
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1501
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1507
+ Points
+
+ {438.65619684966936, 329.34423993081015}
+ {441.13742329927879, 329.12827626312878}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{528.56022898647439, 292.52976113371614}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1508
+ Rotation
+ 247.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{441.107359480529, 274.41706448263619}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1509
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{438.357359480529, 271.66706448263619}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1510
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1506
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{440.78708236537307, 274.3210656490798}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1511
+ Rotation
+ 337.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1499
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{248.28852278518417, 235.77792148758147}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1512
+ Rotation
+ 247.5
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{425.23537052568395, 232.45140364934065}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1513
+ Rotation
+ 292.50006103515625
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{374.59821460510483, 282.06732351898592}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1514
+ Rotation
+ 157.5
+ Shape
+ Rectangle
+
+
+ Class
+ Group
+ Graphics
+
+
+ Bounds
+ {{394.33229525377027, 98.150584482954116}, {24, 24}}
+ Class
+ ShapedGraphic
+ ID
+ 1516
+ Shape
+ Circle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ Text
+ {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs24 \cf0 1}
+ VerticalPad
+ 0
+
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1518
+ Points
+
+ {459.47976189091298, 106.26624457633855}
+ {456.99853544130355, 106.48220824401977}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{353.57572975410767, 124.58072337343253}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1519
+ Rotation
+ 67.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{355.52859926005328, 59.693420024512235}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1520
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{352.77859926005328, 56.943420024512235}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1521
+ Rotation
+ 157.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1517
+ Rotation
+ 337.5
+
+
+ Class
+ Group
+ Graphics
+
+
+ Class
+ LineGraphic
+ ID
+ 1523
+ Points
+
+ {353.28972753783154, 114.26206913039776}
+ {355.77095398744109, 114.04610546271654}
+
+ Style
+
+ stroke
+
+ HeadArrow
+ 0
+ Legacy
+
+ TailArrow
+ 0
+
+
+
+
+ Bounds
+ {{443.19375967463657, 77.447590333303964}, {16, 18.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1524
+ Rotation
+ 247.5
+ Shape
+ HorizontalTriangle
+ Style
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ Bounds
+ {{355.74089016869129, 59.33489368222402}, {101.5, 101.5}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1525
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ Bounds
+ {{352.99089016869129, 56.58489368222402}, {107, 107}}
+ Class
+ ShapedGraphic
+ HFlip
+ YES
+ ID
+ 1526
+ Rotation
+ 337.5
+ Shape
+ AdjustableArc
+ ShapeData
+
+ endAngle
+ 72
+ startAngle
+ 281
+
+ Style
+
+ fill
+
+ Draws
+ NO
+
+ shadow
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+ TextRelativeArea
+ {{0.10000000000000001, 0.14999999999999999}, {0.80000000000000004, 0.69999999999999996}}
+
+
+ ID
+ 1522
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{355.42061305353548, 59.238894848667528}, {101.82337649086284, 101.82337649086284}}
+ Class
+ ShapedGraphic
+ ID
+ 1527
+ Rotation
+ 337.5
+ Shape
+ Circle
+ Style
+
+ fill
+
+ Color
+
+ a
+ 0.78
+ b
+ 0.234512
+ g
+ 0.673128
+ r
+ 0.148947
+
+
+ shadow
+
+ Draws
+ NO
+
+ stroke
+
+ Draws
+ NO
+
+
+ Text
+
+ VerticalPad
+ 0
+
+
+
+ ID
+ 1515
+ Rotation
+ 337.5
+
+
+ Bounds
+ {{252.46989794607327, 160.88960179706885}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1528
+ Rotation
+ 292.50006103515625
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{426.89836479441431, 161.02992820772749}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1529
+ Rotation
+ 247.5
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{302.52032988683095, 284.35823469264687}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1530
+ Rotation
+ 22.500026702880859
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{375.35774119930903, 108.51315184010758}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1531
+ Rotation
+ 22.500026702880859
+ Shape
+ Rectangle
+
+
+ Bounds
+ {{303.4692327942559, 110.3467678696648}, {8, 134}}
+ Class
+ ShapedGraphic
+ ID
+ 1532
+ Rotation
+ 157.5
+ Shape
+ Rectangle
+
+
+ ID
+ 1419
+ Rotation
+ 45
+
+
+ ID
+ 1415
+
+
+ GridInfo
+
+ HPages
+ 1
+ KeepToScale
+
+ Layers
+
+
+ Lock
+ NO
+ Name
+ Layer 1
+ Print
+ YES
+ View
+ YES
+
+
+ LayoutInfo
+
+ Animate
+ NO
+ circoMinDist
+ 18
+ circoSeparation
+ 0.0
+ layoutEngine
+ dot
+ neatoSeparation
+ 0.0
+ twopiSeparation
+ 0.0
+
+ Orientation
+ 2
+ PrintOnePage
+
+ RowAlign
+ 1
+ RowSpacing
+ 36
+ SheetTitle
+ Rotor Assignment 3
+ UniqueID
+ 4
+ VPages
+ 1
+
+
+ SmartAlignmentGuidesActive
+ YES
+ SmartDistanceGuidesActive
+ YES
+ UseEntirePage
+
+ WindowInfo
+
+ CurrentSheet
+ 4
+ ExpandedCanvases
+
+
+ name
+ Canvas 1
+
+
+ Frame
+ {{96, 56}, {1043, 822}}
+ ListView
+
+ OutlineWidth
+ 142
+ RightSidebar
+
+ ShowRuler
+
+ Sidebar
+
+ SidebarWidth
+ 120
+ VisibleRegion
+ {{-51, -33}, {908, 683}}
+ Zoom
+ 1
+ ZoomValues
+
+
+ Canvas 1
+ 1
+ 0.5
+
+
+ Rotor Assignments
+ 1
+ 4
+
+
+ Rotor Assignment 2
+ 1
+ 4
+
+
+ Rotor Assignment 3
+ 1
+ 1
+
+
+ Remote Control
+ 1
+ 1
+
+
+
+
+
diff --git a/Makefile b/Makefile
index e9442afd2c..1d1287b7f7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,43 +1,53 @@
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
#
# Top-level Makefile for building PX4 firmware images.
#
-#
-# Note that this is a transitional process; the eventual goal is for this
-# project to slim down and simply generate PX4 link kits via the NuttX
-# 'make export' mechanism.
-#
-#
#
-# Some useful paths.
+# Get path and tool configuration
#
-export PX4BASE = $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
-export NUTTX_SRC = $(PX4BASE)/nuttx
-export NUTTX_APPS = $(PX4BASE)/apps
-export MAVLINK_SRC = $(PX4BASE)/mavlink
-export ROMFS_SRC = $(PX4BASE)/ROMFS
-export IMAGE_DIR = $(PX4BASE)/Images
+export PX4_BASE := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))/
+include $(PX4_BASE)makefiles/setup.mk
#
-# Tools
+# Canned firmware configurations that we build.
#
-MKFW = $(PX4BASE)/Tools/px_mkfw.py
-UPLOADER = $(PX4BASE)/Tools/px_uploader.py
+CONFIGS ?= $(subst config_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)config_*.mk))))
#
-# What are we currently configured for?
+# Boards that we build NuttX export kits for.
#
-CONFIGURED = $(PX4BASE)/.configured
-ifneq ($(wildcard $(CONFIGURED)),)
-export TARGET := $(shell cat $(CONFIGURED))
-endif
-
-#
-# What we will build
-#
-FIRMWARE_BUNDLE = $(IMAGE_DIR)/$(TARGET).px4
-FIRMWARE_BINARY = $(IMAGE_DIR)/$(TARGET).bin
-FIRMWARE_PROTOTYPE = $(IMAGE_DIR)/$(TARGET).prototype
+BOARDS := $(subst board_,,$(basename $(notdir $(wildcard $(PX4_MK_DIR)board_*.mk))))
#
# Debugging
@@ -45,120 +55,156 @@ FIRMWARE_PROTOTYPE = $(IMAGE_DIR)/$(TARGET).prototype
MQUIET = --no-print-directory
#MQUIET = --print-directory
-all: $(FIRMWARE_BUNDLE)
+################################################################################
+# No user-serviceable parts below
+################################################################################
#
-# Generate a wrapped .px4 file from the built binary
+# If the user has listed a config as a target, strip it out and override CONFIGS.
#
-$(FIRMWARE_BUNDLE): $(FIRMWARE_BINARY) $(MKFW) $(FIRMWARE_PROTOTYPE)
- @echo Generating $@
- @$(MKFW) --prototype $(FIRMWARE_PROTOTYPE) \
- --git_identity $(PX4BASE) \
- --image $(FIRMWARE_BINARY) > $@
+FIRMWARE_GOAL = firmware
+EXPLICIT_CONFIGS := $(filter $(CONFIGS),$(MAKECMDGOALS))
+ifneq ($(EXPLICIT_CONFIGS),)
+CONFIGS := $(EXPLICIT_CONFIGS)
+.PHONY: $(EXPLICIT_CONFIGS)
+$(EXPLICIT_CONFIGS): all
#
-# Build the firmware binary.
+# If the user has asked to upload, they must have also specified exactly one
+# config.
#
-.PHONY: $(FIRMWARE_BINARY)
-$(FIRMWARE_BINARY): setup_$(TARGET) configure-check
- @echo Building $@ for $(TARGET)
- @make -C $(NUTTX_SRC) -r $(MQUIET) all
- @cp $(NUTTX_SRC)/nuttx.bin $@
-
-#
-# The 'configure' targets select one particular firmware configuration
-# and makes it current.
-#
-configure_px4fmu:
- @echo Configuring for px4fmu
- @make -C $(PX4BASE) distclean
- @cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4fmu/nsh
- @echo px4fmu > $(CONFIGURED)
-
-configure_px4io:
- @echo Configuring for px4io
- @make -C $(PX4BASE) distclean
- @cd $(NUTTX_SRC)/tools && /bin/sh configure.sh px4io/io
- @echo px4io > $(CONFIGURED)
-
-configure-check:
-ifeq ($(wildcard $(CONFIGURED)),)
- @echo
- @echo "Not configured - use 'make configure_px4fmu' or 'make configure_px4io' first"
- @echo
- @exit 1
+ifneq ($(filter upload,$(MAKECMDGOALS)),)
+ifneq ($(words $(EXPLICIT_CONFIGS)),1)
+$(error In order to upload, exactly one board config must be specified)
+endif
+FIRMWARE_GOAL = upload
+.PHONY: upload
+upload:
+ @:
+endif
endif
+#
+# Built products
+#
+STAGED_FIRMWARES = $(foreach config,$(CONFIGS),$(IMAGE_DIR)$(config).px4)
+FIRMWARES = $(foreach config,$(CONFIGS),$(BUILD_DIR)$(config).build/firmware.px4)
+
+all: $(STAGED_FIRMWARES)
#
-# Per-configuration additional targets
+# Copy FIRMWARES into the image directory.
#
-.PHONY: px4fmu_setup
-setup_px4fmu:
- @echo Generating ROMFS
- @make -C $(ROMFS_SRC) all
-
-setup_px4io:
-
-# fake target to make configure-check happy if TARGET is not set
-setup_:
+$(STAGED_FIRMWARES): $(IMAGE_DIR)%.px4: $(BUILD_DIR)%.build/firmware.px4
+ @echo %% Copying $@
+ $(Q) $(COPY) $< $@
#
-# Firmware uploading.
+# Generate FIRMWARES.
#
+.PHONY: $(FIRMWARES)
+$(BUILD_DIR)%.build/firmware.px4: config = $(patsubst $(BUILD_DIR)%.build/firmware.px4,%,$@)
+$(BUILD_DIR)%.build/firmware.px4: work_dir = $(BUILD_DIR)$(config).build/
+$(FIRMWARES): $(BUILD_DIR)%.build/firmware.px4:
+ @echo %%%%
+ @echo %%%% Building $(config) in $(work_dir)
+ @echo %%%%
+ $(Q) mkdir -p $(work_dir)
+ $(Q) make -r -C $(work_dir) \
+ -f $(PX4_MK_DIR)firmware.mk \
+ CONFIG=$(config) \
+ WORK_DIR=$(work_dir) \
+ $(FIRMWARE_GOAL)
-# serial port defaults by operating system.
-SYSTYPE = $(shell uname)
-ifeq ($(SYSTYPE),Darwin)
-SERIAL_PORTS ?= "/dev/tty.usbmodemPX1,/dev/tty.usbmodemPX2,/dev/tty.usbmodemPX3,/dev/tty.usbmodemPX4,/dev/tty.usbmodem1,/dev/tty.usbmodem2,/dev/tty.usbmodem3,/dev/tty.usbmodem4"
-endif
-ifeq ($(SYSTYPE),Linux)
-SERIAL_PORTS ?= "/dev/ttyACM5,/dev/ttyACM4,/dev/ttyACM3,/dev/ttyACM2,/dev/ttyACM1,/dev/ttyACM0"
-endif
-ifeq ($(SERIAL_PORTS),)
-SERIAL_PORTS = "\\\\.\\COM32,\\\\.\\COM31,\\\\.\\COM30,\\\\.\\COM29,\\\\.\\COM28,\\\\.\\COM27,\\\\.\\COM26,\\\\.\\COM25,\\\\.\\COM24,\\\\.\\COM23,\\\\.\\COM22,\\\\.\\COM21,\\\\.\\COM20,\\\\.\\COM19,\\\\.\\COM18,\\\\.\\COM17,\\\\.\\COM16,\\\\.\\COM15,\\\\.\\COM14,\\\\.\\COM13,\\\\.\\COM12,\\\\.\\COM11,\\\\.\\COM10,\\\\.\\COM9,\\\\.\\COM8,\\\\.\\COM7,\\\\.\\COM6,\\\\.\\COM5,\\\\.\\COM4,\\\\.\\COM3,\\\\.\\COM2,\\\\.\\COM1,\\\\.\\COM0"
+#
+# Build the NuttX export archives.
+#
+# Note that there are no explicit dependencies extended from these
+# archives. If NuttX is updated, the user is expected to rebuild the
+# archives/build area manually. Likewise, when the 'archives' target is
+# invoked, all archives are always rebuilt.
+#
+# XXX Should support fetching/unpacking from a separate directory to permit
+# downloads of the prebuilt archives as well...
+#
+# XXX PX4IO configuration name is bad - NuttX configs should probably all be "px4"
+#
+NUTTX_ARCHIVES = $(foreach board,$(BOARDS),$(ARCHIVE_DIR)$(board).export)
+.PHONY: archives
+archives: $(NUTTX_ARCHIVES)
+
+# We cannot build these parallel; note that we also force -j1 for the
+# sub-make invocations.
+ifneq ($(filter archives,$(MAKECMDGOALS)),)
+.NOTPARALLEL:
endif
-upload: $(FIRMWARE_BUNDLE) $(UPLOADER)
- $(UPLOADER) --port $(SERIAL_PORTS) $(FIRMWARE_BUNDLE)
-
-#
-# JTAG firmware uploading with OpenOCD
-#
-ifeq ($(JTAGCONFIG),)
-JTAGCONFIG=interface/olimex-jtag-tiny.cfg
-endif
-
-upload-jtag-px4fmu:
- @echo Attempting to flash PX4FMU board via JTAG
- @openocd -f $(JTAGCONFIG) -f ../Bootloader/stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase nuttx/nuttx" -c "flash write_image erase ../Bootloader/px4fmu_bl.elf" -c "reset run" -c shutdown
-
-upload-jtag-px4io: all
- @echo Attempting to flash PX4IO board via JTAG
- @openocd -f $(JTAGCONFIG) -f ../Bootloader/stm32f1x.cfg -c init -c "reset halt" -c "flash write_image erase nuttx/nuttx" -c "flash write_image erase ../Bootloader/px4io_bl.elf" -c "reset run" -c shutdown
-
-#
-# Hacks and fixups
-#
-
-ifeq ($(SYSTYPE),Darwin)
-# PATH inherited by Eclipse may not include toolchain install location
-export PATH := $(PATH):/usr/local/bin
-endif
+$(ARCHIVE_DIR)%.export: board = $(notdir $(basename $@))
+$(ARCHIVE_DIR)%.export: configuration = $(if $(filter $(board),px4io),io,nsh)
+$(NUTTX_ARCHIVES): $(ARCHIVE_DIR)%.export: $(NUTTX_SRC) $(NUTTX_APPS)
+ @echo %% Configuring NuttX for $(board)
+ $(Q) (cd $(NUTTX_SRC) && $(RMDIR) nuttx-export)
+ $(Q) make -r -j1 -C $(NUTTX_SRC) -r $(MQUIET) distclean
+ $(Q) (cd $(NUTTX_SRC)tools && ./configure.sh $(board)/$(configuration))
+ @echo %% Exporting NuttX for $(board)
+ $(Q) make -r -j1 -C $(NUTTX_SRC) -r $(MQUIET) export
+ $(Q) mkdir -p $(dir $@)
+ $(Q) $(COPY) $(NUTTX_SRC)nuttx-export.zip $@
#
# Cleanup targets. 'clean' should remove all built products and force
# a complete re-compilation, 'distclean' should remove everything
# that's generated leaving only files that are in source control.
#
-.PHONY: clean upload-jtag-px4fmu
+.PHONY: clean
clean:
- @make -C $(NUTTX_SRC) -r $(MQUIET) distclean
- @make -C $(ROMFS_SRC) -r $(MQUIET) clean
+ $(Q) $(RMDIR) $(BUILD_DIR)*.build
+ $(Q) $(REMOVE) $(IMAGE_DIR)*.px4
.PHONY: distclean
-distclean:
- @rm -f $(CONFIGURED)
- @make -C $(NUTTX_SRC) -r $(MQUIET) distclean
- @make -C $(ROMFS_SRC) -r $(MQUIET) distclean
+distclean: clean
+ $(Q) $(REMOVE) $(ARCHIVE_DIR)*.export
+ $(Q) make -C $(NUTTX_SRC) -r $(MQUIET) distclean
+#
+# Print some help text
+#
+.PHONY: help
+help:
+ @echo ""
+ @echo " PX4 firmware builder"
+ @echo " ===================="
+ @echo ""
+ @echo " Available targets:"
+ @echo " ------------------"
+ @echo ""
+ @echo " archives"
+ @echo " Build the NuttX RTOS archives that are used by the firmware build."
+ @echo ""
+ @echo " all"
+ @echo " Build all firmware configs: $(CONFIGS)"
+ @echo " A limited set of configs can be built with CONFIGS="
+ @echo ""
+ @for config in $(CONFIGS); do \
+ echo " $$config"; \
+ echo " Build just the $$config firmware configuration."; \
+ echo ""; \
+ done
+ @echo " clean"
+ @echo " Remove all firmware build pieces."
+ @echo ""
+ @echo " distclean"
+ @echo " Remove all compilation products, including NuttX RTOS archives."
+ @echo ""
+ @echo " upload"
+ @echo " When exactly one config is being built, add this target to upload the"
+ @echo " firmware to the board when the build is complete. Not supported for"
+ @echo " all configurations."
+ @echo ""
+ @echo " Common options:"
+ @echo " ---------------"
+ @echo ""
+ @echo " V=1"
+ @echo " If V is set, more verbose output is printed during the build. This can"
+ @echo " help when diagnosing issues with the build or toolchain."
+ @echo ""
diff --git a/ROMFS/.gitignore b/ROMFS/.gitignore
deleted file mode 100644
index 30d3d7fe50..0000000000
--- a/ROMFS/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/img
diff --git a/ROMFS/Makefile b/ROMFS/Makefile
deleted file mode 100644
index ed39ab8257..0000000000
--- a/ROMFS/Makefile
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# Makefile to generate a PX4FMU ROMFS image.
-#
-# In normal use, 'make install' will generate a new ROMFS header and place it
-# into the px4fmu configuration in the appropriate location.
-#
-
-#
-# Directories of interest
-#
-SRCROOT ?= $(dir $(lastword $(MAKEFILE_LIST)))
-BUILDROOT ?= $(SRCROOT)/img
-ROMFS_HEADER ?= $(SRCROOT)/../nuttx/configs/px4fmu/include/nsh_romfsimg.h
-
-#
-# List of files to install in the ROMFS, specified as ~
-#
-ROMFS_FSSPEC := $(SRCROOT)/scripts/rcS~init.d/rcS \
- $(SRCROOT)/scripts/rc.sensors~init.d/rc.sensors \
- $(SRCROOT)/scripts/rc.logging~init.d/rc.logging \
- $(SRCROOT)/scripts/rc.standalone~init.d/rc.standalone \
- $(SRCROOT)/scripts/rc.PX4IO~init.d/rc.PX4IO \
- $(SRCROOT)/scripts/rc.PX4IOAR~init.d/rc.PX4IOAR \
- $(SRCROOT)/scripts/rc.FMU_quad_x~init.d/rc.FMU_quad_x \
- $(SRCROOT)/scripts/rc.usb~init.d/rc.usb \
- $(SRCROOT)/scripts/rc.hil~init.d/rc.hil \
- $(SRCROOT)/mixers/FMU_pass.mix~mixers/FMU_pass.mix \
- $(SRCROOT)/mixers/FMU_Q.mix~mixers/FMU_Q.mix \
- $(SRCROOT)/mixers/FMU_X5.mix~mixers/FMU_X5.mix \
- $(SRCROOT)/mixers/FMU_AERT.mix~mixers/FMU_AERT.mix \
- $(SRCROOT)/mixers/FMU_AET.mix~mixers/FMU_AET.mix \
- $(SRCROOT)/mixers/FMU_RET.mix~mixers/FMU_ERT.mix \
- $(SRCROOT)/mixers/FMU_quad_x.mix~mixers/FMU_quad_x.mix \
- $(SRCROOT)/mixers/FMU_quad_+.mix~mixers/FMU_quad_+.mix \
- $(SRCROOT)/mixers/FMU_hex_x.mix~mixers/FMU_hex_x.mix \
- $(SRCROOT)/mixers/FMU_hex_+.mix~mixers/FMU_hex_+.mix \
- $(SRCROOT)/mixers/FMU_octo_x.mix~mixers/FMU_octo_x.mix \
- $(SRCROOT)/mixers/FMU_octo_+.mix~mixers/FMU_octo_+.mix \
- $(SRCROOT)/logging/logconv.m~logging/logconv.m
-
-# the EXTERNAL_SCRIPTS variable is used to add out of tree scripts
-# to ROMFS.
-ROMFS_FSSPEC += $(EXTERNAL_SCRIPTS)
-
-#
-# Add the PX4IO firmware to the spec if someone has dropped it into the
-# source directory, or otherwise specified its location.
-#
-# Normally this is only something you'd do when working on PX4IO; most
-# users will upgrade with firmware off the microSD card.
-#
-PX4IO_FIRMWARE ?= $(SRCROOT)/px4io.bin
-ifneq ($(wildcard $(PX4IO_FIRMWARE)),)
-ROMFS_FSSPEC += $(PX4IO_FIRMWARE)~px4io.bin
-endif
-
-################################################################################
-# No user-serviceable parts below
-################################################################################
-
-#
-# Just the source files from the ROMFS spec, so that we can fail cleanly if they don't
-# exist
-#
-ROMFS_SRCFILES = $(foreach spec,$(ROMFS_FSSPEC),$(firstword $(subst ~, ,$(spec))))
-
-#
-# Just the destination directories from the ROMFS spec
-#
-ROMFS_DIRS = $(sort $(dir $(foreach spec,$(ROMFS_FSSPEC),$(lastword $(subst ~, ,$(spec))))))
-
-
-#
-# Intermediate products
-#
-ROMFS_IMG = $(BUILDROOT)/romfs.img
-ROMFS_WORKDIR = $(BUILDROOT)/romfs
-
-#
-# Convenience target for rebuilding the ROMFS header
-#
-all: $(ROMFS_HEADER)
-
-$(ROMFS_HEADER): $(ROMFS_IMG) $(dir $(ROMFS_HEADER))
- @echo Generating the ROMFS header...
- @(cd $(dir $(ROMFS_IMG)) && xxd -i $(notdir $(ROMFS_IMG))) | sed -e 's/char/const char/' > $@
-
-$(ROMFS_IMG): $(ROMFS_WORKDIR)
- @echo Generating the ROMFS image...
- @genromfs -f $@ -d $(ROMFS_WORKDIR) -V "NSHInitVol"
-
-$(ROMFS_WORKDIR): $(ROMFS_SRCFILES)
- @echo Rebuilding the ROMFS work area...
- @rm -rf $(ROMFS_WORKDIR)
- @mkdir -p $(ROMFS_WORKDIR)
- @for dir in $(ROMFS_DIRS) ; do mkdir -p $(ROMFS_WORKDIR)/$$dir; done
- @for spec in $(ROMFS_FSSPEC) ; do \
- echo $$spec | sed -e 's%^.*~% %' ;\
- `echo "cp $$spec" | sed -e 's%~% $(ROMFS_WORKDIR)/%'` ;\
- done
-
-$(BUILDROOT):
- @mkdir -p $(BUILDROOT)
-
-clean:
- @rm -rf $(BUILDROOT)
-
-distclean: clean
- @rm -f $(PX4IO_FIRMWARE) $(ROMFS_HEADER)
-
-.PHONY: all install clean distclean
-
-#
-# Hacks and fixups
-#
-SYSTYPE = $(shell uname)
-
-ifeq ($(SYSTYPE),Darwin)
-# PATH inherited by Eclipse may not include toolchain install location
-export PATH := $(PATH):/usr/local/bin
-endif
-
diff --git a/ROMFS/logging/logconv.m b/ROMFS/logging/logconv.m
deleted file mode 100755
index 92ee014135..0000000000
--- a/ROMFS/logging/logconv.m
+++ /dev/null
@@ -1,224 +0,0 @@
-% This Matlab Script can be used to import the binary logged values of the
-% PX4FMU into data that can be plotted and analyzed.
-
-% Clear everything
-clc
-clear all
-close all
-
-% Set the path to your sysvector.bin file here
-filePath = 'sysvector.bin';
-
-% Work around a Matlab bug (not related to PX4)
-% where timestamps from 1.1.1970 do not allow to
-% read the file's size
-if ismac
- system('touch -t 201212121212.12 sysvector.bin');
-end
-
-%%%%%%%%%%%%%%%%%%%%%%%
-% SYSTEM VECTOR
-%
-% //All measurements in NED frame
-%
-% uint64_t timestamp; //[us]
-% float gyro[3]; //[rad/s]
-% float accel[3]; //[m/s^2]
-% float mag[3]; //[gauss]
-% float baro; //pressure [millibar]
-% float baro_alt; //altitude above MSL [meter]
-% float baro_temp; //[degree celcius]
-% float control[4]; //roll, pitch, yaw [-1..1], thrust [0..1]
-% float actuators[8]; //motor 1-8, in motor units (PWM: 1000-2000,AR.Drone: 0-512)
-% float vbat; //battery voltage in [volt]
-% float bat_current - current drawn from battery at this time instant
-% float bat_discharged - discharged energy in mAh
-% float adc[4]; //ADC ports [volt]
-% float local_position[3]; //tangent plane mapping into x,y,z [m]
-% int32_t gps_raw_position[3]; //latitude [degrees] north, longitude [degrees] east, altitude above MSL [millimeter]
-% float attitude[3]; //pitch, roll, yaw [rad]
-% float rotMatrix[9]; //unitvectors
-% float actuator_control[4]; //unitvector
-% float optical_flow[4]; //roll, pitch, yaw [-1..1], thrust [0..1]
-% float diff_pressure; - pressure difference in millibar
-% float ind_airspeed;
-% float true_airspeed;
-
-% Definition of the logged values
-logFormat{1} = struct('name', 'timestamp', 'bytes', 8, 'array', 1, 'precision', 'uint64', 'machineformat', 'ieee-le.l64');
-logFormat{2} = struct('name', 'gyro', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{3} = struct('name', 'accel', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{4} = struct('name', 'mag', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{5} = struct('name', 'baro', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{6} = struct('name', 'baro_alt', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{7} = struct('name', 'baro_temp', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{8} = struct('name', 'control', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{9} = struct('name', 'actuators', 'bytes', 4, 'array', 8, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{10} = struct('name', 'vbat', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{11} = struct('name', 'bat_current', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{12} = struct('name', 'bat_discharged', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{13} = struct('name', 'adc', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{14} = struct('name', 'local_position', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{15} = struct('name', 'gps_raw_position', 'bytes', 4, 'array', 3, 'precision', 'uint32', 'machineformat', 'ieee-le');
-logFormat{16} = struct('name', 'attitude', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{17} = struct('name', 'rot_matrix', 'bytes', 4, 'array', 9, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{18} = struct('name', 'vicon_position', 'bytes', 4, 'array', 6, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{19} = struct('name', 'actuator_control', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{20} = struct('name', 'optical_flow', 'bytes', 4, 'array', 6, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{21} = struct('name', 'diff_pressure', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{22} = struct('name', 'ind_airspeed', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-logFormat{23} = struct('name', 'true_airspeed', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
-
-% First get length of one line
-columns = length(logFormat);
-lineLength = 0;
-
-for i=1:columns
- lineLength = lineLength + logFormat{i}.bytes * logFormat{i}.array;
-end
-
-
-if exist(filePath, 'file')
-
- fileInfo = dir(filePath);
- fileSize = fileInfo.bytes;
-
- elements = int64(fileSize./(lineLength));
-
- fid = fopen(filePath, 'r');
- offset = 0;
- for i=1:columns
- % using fread with a skip speeds up the import drastically, do not
- % import the values one after the other
- sysvector.(genvarname(logFormat{i}.name)) = transpose(fread(...
- fid, ...
- [logFormat{i}.array, elements], [num2str(logFormat{i}.array),'*',logFormat{i}.precision,'=>',logFormat{i}.precision], ...
- lineLength - logFormat{i}.bytes*logFormat{i}.array, ...
- logFormat{i}.machineformat) ...
- );
- offset = offset + logFormat{i}.bytes*logFormat{i}.array;
- fseek(fid, offset,'bof');
- end
-
- % shot the flight time
- time_us = sysvector.timestamp(end) - sysvector.timestamp(1);
- time_s = time_us*1e-6;
- time_m = time_s/60;
-
- % close the logfile
- fclose(fid);
-
- disp(['end log2matlab conversion' char(10)]);
-else
- disp(['file: ' filePath ' does not exist' char(10)]);
-end
-
-%% Plot GPS RAW measurements
-
-% Only plot GPS data if available
-if cumsum(double(sysvector.gps_raw_position(200:end,1))) > 0
- figure('units','normalized','outerposition',[0 0 1 1])
- plot3(sysvector.gps_raw_position(200:end,1), sysvector.gps_raw_position(200:end,2), sysvector.gps_raw_position(200:end,3));
-end
-
-
-%% Plot optical flow trajectory
-
-flow_sz = size(sysvector.timestamp);
-flow_elements = flow_sz(1);
-
-xt(1:flow_elements,1) = sysvector.timestamp(:,1); % time column [ms]
-
-
-%calc dt
-dt = zeros(flow_elements,1);
-for i = 1:flow_elements-1
- dt(i+1,1) = double(xt(i+1,1)-xt(i,1)) * 10^(-6); % timestep [s]
-end
-dt(1,1) = mean(dt);
-
-
-global_speed = zeros(flow_elements,3);
-
-%calc global speed (with rot matrix)
-for i = 1:flow_elements
- rotM = [sysvector.rot_matrix(i,1:3);sysvector.rot_matrix(i,4:6);sysvector.rot_matrix(i,7:9)]';
- speedX = sysvector.optical_flow(i,3);
- speedY = sysvector.optical_flow(i,4);
-
- relSpeed = [-speedY,speedX,0];
- global_speed(i,:) = relSpeed * rotM;
-end
-
-
-
-px = zeros(flow_elements,1);
-py = zeros(flow_elements,1);
-distance = 0;
-
-last_vx = 0;
-last_vy = 0;
-elem_cnt = 0;
-
-% Very basic accumulation, stops on bad flow quality
-for i = 1:flow_elements
- if sysvector.optical_flow(i,6) > 5
- px(i,1) = global_speed(i,1)*dt(i,1);
- py(i,1) = global_speed(i,2)*dt(i,1);
- distance = distance + norm([px(i,1) py(i,1)]);
- last_vx = px(i,1);
- last_vy = py(i,1);
- else
- px(i,1) = last_vx;
- py(i,1) = last_vy;
- last_vx = last_vx*0.95;
- last_vy = last_vy*0.95;
- end
-end
-
-px_sum = cumsum(px);
-py_sum = cumsum(py);
-time = cumsum(dt);
-
-figure()
-set(gca, 'Units','normal');
-
-plot(py_sum, px_sum, '-blue', 'LineWidth',2);
-axis equal;
-% set title and axis captions
-xlabel('X position (meters)','fontsize',14)
-ylabel('Y position (meters)','fontsize',14)
-% mark begin and end
-hold on
-plot(py_sum(1,1),px_sum(1,1),'ks','LineWidth',2,...
-'MarkerEdgeColor','k',...
-'MarkerFaceColor','g',...
-'MarkerSize',10)
-hold on
-plot(py_sum(end,1),px_sum(end,1),'kv','LineWidth',2,...
-'MarkerEdgeColor','k',...
-'MarkerFaceColor','b',...
-'MarkerSize',10)
-% add total length as annotation
-set(gca,'fontsize',13);
-legend('Trajectory', 'START', sprintf('END\n(%.2f m, %.0f:%.0f s)', distance, time_m, time_s - time_m*60));
-title('Optical Flow Position Integration', 'fontsize', 15);
-
-figure()
-plot(time, sysvector.optical_flow(:,5), 'blue');
-axis([time(1,1) time(end,1) 0 (max(sysvector.optical_flow(i,5))+0.2)]);
-xlabel('seconds','fontsize',14);
-ylabel('m','fontsize',14);
-set(gca,'fontsize',13);
-title('Ultrasound Altitude', 'fontsize', 15);
-
-
-figure()
-plot(time, global_speed(:,2), 'red');
-hold on;
-plot(time, global_speed(:,1), 'blue');
-legend('y velocity (m/s)', 'x velocity (m/s)');
-xlabel('seconds','fontsize',14);
-ylabel('m/s','fontsize',14);
-set(gca,'fontsize',13);
-title('Optical Flow Velocity', 'fontsize', 15);
diff --git a/ROMFS/scripts/rc.FMU_quad_x b/ROMFS/px4fmu_common/init.d/rc.FMU_quad_x
similarity index 90%
rename from ROMFS/scripts/rc.FMU_quad_x
rename to ROMFS/px4fmu_common/init.d/rc.FMU_quad_x
index 8787443ea2..980197d68e 100644
--- a/ROMFS/scripts/rc.FMU_quad_x
+++ b/ROMFS/px4fmu_common/init.d/rc.FMU_quad_x
@@ -20,10 +20,10 @@ uorb start
# Load microSD params
#
echo "[init] loading microSD params"
-param select /fs/microsd/parameters
-if [ -f /fs/microsd/parameters ]
+param select /fs/microsd/params
+if [ -f /fs/microsd/params ]
then
- param load /fs/microsd/parameters
+ param load /fs/microsd/params
fi
#
diff --git a/ROMFS/px4fmu_common/init.d/rc.IO_QUAD b/ROMFS/px4fmu_common/init.d/rc.IO_QUAD
new file mode 100644
index 0000000000..5f2de0d7e0
--- /dev/null
+++ b/ROMFS/px4fmu_common/init.d/rc.IO_QUAD
@@ -0,0 +1,107 @@
+#!nsh
+
+# Disable USB and autostart
+set USB no
+set MODE quad
+
+#
+# Start the ORB (first app to start)
+#
+uorb start
+
+#
+# Load microSD params
+#
+echo "[init] loading microSD params"
+param select /fs/microsd/params
+if [ -f /fs/microsd/params ]
+then
+ param load /fs/microsd/params
+fi
+
+#
+# Force some key parameters to sane values
+# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
+# see https://pixhawk.ethz.ch/mavlink/
+#
+param set MAV_TYPE 2
+
+#
+# Check if PX4IO Firmware should be upgraded (from Andrew Tridgell)
+#
+if [ -f /fs/microsd/px4io.bin ]
+then
+ echo "PX4IO Firmware found. Checking Upgrade.."
+ if cmp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
+ then
+ echo "No newer version, skipping upgrade."
+ else
+ echo "Loading /fs/microsd/px4io.bin"
+ if px4io update /fs/microsd/px4io.bin > /fs/microsd/px4io_update.log
+ then
+ cp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
+ echo "Flashed /fs/microsd/px4io.bin OK" >> /fs/microsd/px4io_update.log
+ else
+ echo "Failed flashing /fs/microsd/px4io.bin" >> /fs/microsd/px4io_update.log
+ echo "Failed to upgrade PX4IO firmware - check if PX4IO is in bootloader mode"
+ fi
+ fi
+fi
+
+#
+# Start MAVLink (depends on orb)
+#
+mavlink start -d /dev/ttyS1 -b 57600
+usleep 5000
+
+#
+# Start the commander (depends on orb, mavlink)
+#
+commander start
+
+#
+# Start PX4IO interface (depends on orb, commander)
+#
+px4io start
+
+#
+# Allow PX4IO to recover from midair restarts.
+# this is very unlikely, but quite safe and robust.
+px4io recovery
+
+#
+# Start the sensors (depends on orb, px4io)
+#
+sh /etc/init.d/rc.sensors
+
+#
+# Start GPS interface (depends on orb)
+#
+gps start
+
+#
+# Start the attitude estimator (depends on orb)
+#
+attitude_estimator_ekf start
+
+#
+# Load mixer and start controllers (depends on px4io)
+#
+mixer load /dev/pwm_output /etc/mixers/FMU_quad_+.mix
+multirotor_att_control start
+
+#
+# Start logging
+#
+#sdlog start -s 4
+
+#
+# Start system state
+#
+if blinkm start
+then
+ echo "using BlinkM for state indication"
+ blinkm systemstate
+else
+ echo "no BlinkM found, OK."
+fi
\ No newline at end of file
diff --git a/ROMFS/px4fmu_common/init.d/rc.PX4IO b/ROMFS/px4fmu_common/init.d/rc.PX4IO
new file mode 100644
index 0000000000..925a5703e7
--- /dev/null
+++ b/ROMFS/px4fmu_common/init.d/rc.PX4IO
@@ -0,0 +1,107 @@
+#!nsh
+
+# Disable USB and autostart
+set USB no
+set MODE camflyer
+
+#
+# Start the ORB (first app to start)
+#
+uorb start
+
+#
+# Load microSD params
+#
+echo "[init] loading microSD params"
+param select /fs/microsd/params
+if [ -f /fs/microsd/params ]
+then
+ param load /fs/microsd/params
+fi
+
+#
+# Force some key parameters to sane values
+# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
+# see https://pixhawk.ethz.ch/mavlink/
+#
+param set MAV_TYPE 1
+
+#
+# Check if PX4IO Firmware should be upgraded (from Andrew Tridgell)
+#
+if [ -f /fs/microsd/px4io.bin ]
+then
+ echo "PX4IO Firmware found. Checking Upgrade.."
+ if cmp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
+ then
+ echo "No newer version, skipping upgrade."
+ else
+ echo "Loading /fs/microsd/px4io.bin"
+ if px4io update /fs/microsd/px4io.bin > /fs/microsd/px4io_update.log
+ then
+ cp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
+ echo "Flashed /fs/microsd/px4io.bin OK" >> /fs/microsd/px4io_update.log
+ else
+ echo "Failed flashing /fs/microsd/px4io.bin" >> /fs/microsd/px4io_update.log
+ echo "Failed to upgrade PX4IO firmware - check if PX4IO is in bootloader mode"
+ fi
+ fi
+fi
+
+#
+# Start MAVLink (depends on orb)
+#
+mavlink start -d /dev/ttyS1 -b 57600
+usleep 5000
+
+#
+# Start the commander (depends on orb, mavlink)
+#
+commander start
+
+#
+# Start PX4IO interface (depends on orb, commander)
+#
+px4io start
+
+#
+# Allow PX4IO to recover from midair restarts.
+# this is very unlikely, but quite safe and robust.
+px4io recovery
+
+#
+# Start the sensors (depends on orb, px4io)
+#
+sh /etc/init.d/rc.sensors
+
+#
+# Start GPS interface (depends on orb)
+#
+gps start
+
+#
+# Start the attitude estimator (depends on orb)
+#
+kalman_demo start
+
+#
+# Load mixer and start controllers (depends on px4io)
+#
+mixer load /dev/pwm_output /etc/mixers/FMU_Q.mix
+control_demo start
+
+#
+# Start logging
+#
+#sdlog start -s 4
+
+#
+# Start system state
+#
+if blinkm start
+then
+ echo "using BlinkM for state indication"
+ blinkm systemstate
+else
+ echo "no BlinkM found, OK."
+fi
diff --git a/ROMFS/scripts/rc.PX4IOAR b/ROMFS/px4fmu_common/init.d/rc.PX4IOAR
similarity index 89%
rename from ROMFS/scripts/rc.PX4IOAR
rename to ROMFS/px4fmu_common/init.d/rc.PX4IOAR
index 72df68e350..f55ac2ae34 100644
--- a/ROMFS/scripts/rc.PX4IOAR
+++ b/ROMFS/px4fmu_common/init.d/rc.PX4IOAR
@@ -2,10 +2,10 @@
#
# Flight startup script for PX4FMU on PX4IOAR carrier board.
#
-
+
# Disable the USB interface
set USB no
-
+
# Disable autostarting other apps
set MODE ardrone
@@ -17,21 +17,26 @@ echo "[init] doing PX4IOAR startup..."
uorb start
#
-# Init the parameter storage
+# Load microSD params
#
echo "[init] loading microSD params"
-param select /fs/microsd/parameters
-if [ -f /fs/microsd/parameters ]
+param select /fs/microsd/params
+if [ -f /fs/microsd/params ]
then
- param load /fs/microsd/parameters
+ param load /fs/microsd/params
fi
-
+
#
# Force some key parameters to sane values
# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
# see https://pixhawk.ethz.ch/mavlink/
#
param set MAV_TYPE 2
+
+#
+# Configure PX4FMU for operation with PX4IOAR
+#
+fmu mode_gpio_serial
#
# Start the sensors.
@@ -54,11 +59,6 @@ commander start
#
attitude_estimator_ekf start
-#
-# Configure PX4FMU for operation with PX4IOAR
-#
-fmu mode_gpio_serial
-
#
# Fire up the multi rotor attitude controller
#
@@ -68,17 +68,17 @@ multirotor_att_control start
# Fire up the AR.Drone interface.
#
ardrone_interface start -d /dev/ttyS1
-
-#
-# Start GPS capture
-#
-gps start
#
# Start logging
#
sdlog start -s 10
+#
+# Start GPS capture
+#
+gps start
+
#
# Start system state
#
@@ -95,4 +95,5 @@ fi
# use the same UART for telemetry
#
echo "[init] startup done"
-exit
\ No newline at end of file
+
+exit
diff --git a/ROMFS/scripts/rc.boarddetect b/ROMFS/px4fmu_common/init.d/rc.boarddetect
similarity index 100%
rename from ROMFS/scripts/rc.boarddetect
rename to ROMFS/px4fmu_common/init.d/rc.boarddetect
diff --git a/ROMFS/scripts/rc.hil b/ROMFS/px4fmu_common/init.d/rc.hil
similarity index 80%
rename from ROMFS/scripts/rc.hil
rename to ROMFS/px4fmu_common/init.d/rc.hil
index 3b37ac26b6..7614ac0feb 100644
--- a/ROMFS/scripts/rc.hil
+++ b/ROMFS/px4fmu_common/init.d/rc.hil
@@ -17,10 +17,10 @@ hil mode_pwm
# Load microSD params
#
echo "[init] loading microSD params"
-param select /fs/microsd/parameters
-if [ -f /fs/microsd/parameters ]
+param select /fs/microsd/params
+if [ -f /fs/microsd/params ]
then
- param load /fs/microsd/parameters
+ param load /fs/microsd/params
fi
#
@@ -35,6 +35,17 @@ param set MAV_TYPE 1
#
commander start
+#
+# Check if we got an IO
+#
+if [ px4io start ]
+then
+ echo "IO started"
+else
+ fmu mode_serial
+ echo "FMU started"
+end
+
#
# Start the sensors (depends on orb, px4io)
#
diff --git a/ROMFS/scripts/rc.jig b/ROMFS/px4fmu_common/init.d/rc.jig
similarity index 100%
rename from ROMFS/scripts/rc.jig
rename to ROMFS/px4fmu_common/init.d/rc.jig
diff --git a/ROMFS/scripts/rc.logging b/ROMFS/px4fmu_common/init.d/rc.logging
similarity index 100%
rename from ROMFS/scripts/rc.logging
rename to ROMFS/px4fmu_common/init.d/rc.logging
diff --git a/ROMFS/scripts/rc.sensors b/ROMFS/px4fmu_common/init.d/rc.sensors
similarity index 88%
rename from ROMFS/scripts/rc.sensors
rename to ROMFS/px4fmu_common/init.d/rc.sensors
index 42c2f52e94..62c7184b85 100644
--- a/ROMFS/scripts/rc.sensors
+++ b/ROMFS/px4fmu_common/init.d/rc.sensors
@@ -7,6 +7,14 @@
# Start sensor drivers here.
#
+#
+# Check for UORB
+#
+if uorb start
+then
+ echo "uORB started"
+fi
+
ms5611 start
adc start
diff --git a/ROMFS/scripts/rc.standalone b/ROMFS/px4fmu_common/init.d/rc.standalone
similarity index 100%
rename from ROMFS/scripts/rc.standalone
rename to ROMFS/px4fmu_common/init.d/rc.standalone
diff --git a/ROMFS/scripts/rc.usb b/ROMFS/px4fmu_common/init.d/rc.usb
similarity index 100%
rename from ROMFS/scripts/rc.usb
rename to ROMFS/px4fmu_common/init.d/rc.usb
diff --git a/ROMFS/scripts/rcS b/ROMFS/px4fmu_common/init.d/rcS
similarity index 95%
rename from ROMFS/scripts/rcS
rename to ROMFS/px4fmu_common/init.d/rcS
index 89a7678797..c0a70f7ddc 100755
--- a/ROMFS/scripts/rcS
+++ b/ROMFS/px4fmu_common/init.d/rcS
@@ -21,9 +21,9 @@ set MODE autostart
set USB autoconnect
#
-# Start playing the startup tune
+
#
-tone_alarm start
+
#
# Try to mount the microSD card.
@@ -32,8 +32,12 @@ echo "[init] looking for microSD..."
if mount -t vfat /dev/mmcsd0 /fs/microsd
then
echo "[init] card mounted at /fs/microsd"
+ # Start playing the startup tune
+ tone_alarm start
else
echo "[init] no microSD card found"
+ # Play SOS
+ tone_alarm 2
fi
#
diff --git a/ROMFS/px4fmu_common/logging/logconv.m b/ROMFS/px4fmu_common/logging/logconv.m
new file mode 100644
index 0000000000..3750ddae2a
--- /dev/null
+++ b/ROMFS/px4fmu_common/logging/logconv.m
@@ -0,0 +1,586 @@
+% This Matlab Script can be used to import the binary logged values of the
+% PX4FMU into data that can be plotted and analyzed.
+
+%% ************************************************************************
+% PX4LOG_PLOTSCRIPT: Main function
+% ************************************************************************
+function PX4Log_Plotscript
+
+% Clear everything
+clc
+clear all
+close all
+
+% ************************************************************************
+% SETTINGS
+% ************************************************************************
+
+% Set the path to your sysvector.bin file here
+filePath = 'sysvector.bin';
+
+% Set the minimum and maximum times to plot here [in seconds]
+mintime=0; %The minimum time/timestamp to display, as set by the user [0 for first element / start]
+maxtime=0; %The maximum time/timestamp to display, as set by the user [0 for last element / end]
+
+%Determine which data to plot. Not completely implemented yet.
+bDisplayGPS=true;
+
+%conversion factors
+fconv_gpsalt=1E-3; %[mm] to [m]
+fconv_gpslatlong=1E-7; %[gps_raw_position_unit] to [deg]
+fconv_timestamp=1E-6; % [microseconds] to [seconds]
+
+% ************************************************************************
+% Import the PX4 logs
+% ************************************************************************
+ImportPX4LogData();
+
+%Translate min and max plot times to indices
+time=double(sysvector.timestamp) .*fconv_timestamp;
+mintime_log=time(1); %The minimum time/timestamp found in the log
+maxtime_log=time(end); %The maximum time/timestamp found in the log
+CurTime=mintime_log; %The current time at which to draw the aircraft position
+
+[imintime,imaxtime]=FindMinMaxTimeIndices();
+
+% ************************************************************************
+% PLOT & GUI SETUP
+% ************************************************************************
+NrFigures=5;
+NrAxes=10;
+h.figures(1:NrFigures)=0.0; % Temporary initialization of figure handle array - these are numbered consecutively
+h.axes(1:NrAxes)=0.0; % Temporary initialization of axes handle array - these are numbered consecutively
+h.pathpoints=[]; % Temporary initiliazation of path points
+
+% Setup the GUI to control the plots
+InitControlGUI();
+% Setup the plotting-GUI (figures, axes) itself.
+InitPlotGUI();
+
+% ************************************************************************
+% DRAW EVERYTHING
+% ************************************************************************
+DrawRawData();
+DrawCurrentAircraftState();
+
+%% ************************************************************************
+% *** END OF MAIN SCRIPT ***
+% NESTED FUNCTION DEFINTIONS FROM HERE ON
+% ************************************************************************
+
+
+%% ************************************************************************
+% IMPORTPX4LOGDATA (nested function)
+% ************************************************************************
+% Attention: This is the import routine for firmware from ca. 03/2013.
+% Other firmware versions might require different import
+% routines.
+
+function ImportPX4LogData()
+ % Work around a Matlab bug (not related to PX4)
+ % where timestamps from 1.1.1970 do not allow to
+ % read the file's size
+ if ismac
+ system('touch -t 201212121212.12 sysvector.bin');
+ end
+
+ % ************************************************************************
+ % RETRIEVE SYSTEM VECTOR
+ % *************************************************************************
+ % //All measurements in NED frame
+ %
+ % uint64_t timestamp; //[us]
+ % float gyro[3]; //[rad/s]
+ % float accel[3]; //[m/s^2]
+ % float mag[3]; //[gauss]
+ % float baro; //pressure [millibar]
+ % float baro_alt; //altitude above MSL [meter]
+ % float baro_temp; //[degree celcius]
+ % float control[4]; //roll, pitch, yaw [-1..1], thrust [0..1]
+ % float actuators[8]; //motor 1-8, in motor units (PWM: 1000-2000,AR.Drone: 0-512)
+ % float vbat; //battery voltage in [volt]
+ % float bat_current - current drawn from battery at this time instant
+ % float bat_discharged - discharged energy in mAh
+ % float adc[4]; //remaining auxiliary ADC ports [volt]
+ % float local_position[3]; //tangent plane mapping into x,y,z [m]
+ % int32_t gps_raw_position[3]; //latitude [degrees] north, longitude [degrees] east, altitude above MSL [millimeter]
+ % float attitude[3]; //pitch, roll, yaw [rad]
+ % float rotMatrix[9]; //unitvectors
+ % float actuator_control[4]; //unitvector
+ % float optical_flow[4]; //roll, pitch, yaw [-1..1], thrust [0..1]
+ % float diff_pressure; - pressure difference in millibar
+ % float ind_airspeed;
+ % float true_airspeed;
+
+ % Definition of the logged values
+ logFormat{1} = struct('name', 'timestamp', 'bytes', 8, 'array', 1, 'precision', 'uint64', 'machineformat', 'ieee-le.l64');
+ logFormat{2} = struct('name', 'gyro', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{3} = struct('name', 'accel', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{4} = struct('name', 'mag', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{5} = struct('name', 'baro', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{6} = struct('name', 'baro_alt', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{7} = struct('name', 'baro_temp', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{8} = struct('name', 'control', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{9} = struct('name', 'actuators', 'bytes', 4, 'array', 8, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{10} = struct('name', 'vbat', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{11} = struct('name', 'bat_current', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{12} = struct('name', 'bat_discharged', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{13} = struct('name', 'adc', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{14} = struct('name', 'local_position', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{15} = struct('name', 'gps_raw_position', 'bytes', 4, 'array', 3, 'precision', 'uint32', 'machineformat', 'ieee-le');
+ logFormat{16} = struct('name', 'attitude', 'bytes', 4, 'array', 3, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{17} = struct('name', 'rot_matrix', 'bytes', 4, 'array', 9, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{18} = struct('name', 'vicon_position', 'bytes', 4, 'array', 6, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{19} = struct('name', 'actuator_control', 'bytes', 4, 'array', 4, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{20} = struct('name', 'optical_flow', 'bytes', 4, 'array', 6, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{21} = struct('name', 'diff_pressure', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{22} = struct('name', 'ind_airspeed', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+ logFormat{23} = struct('name', 'true_airspeed', 'bytes', 4, 'array', 1, 'precision', 'float', 'machineformat', 'ieee-le');
+
+ % First get length of one line
+ columns = length(logFormat);
+ lineLength = 0;
+
+ for i=1:columns
+ lineLength = lineLength + logFormat{i}.bytes * logFormat{i}.array;
+ end
+
+
+ if exist(filePath, 'file')
+
+ fileInfo = dir(filePath);
+ fileSize = fileInfo.bytes;
+
+ elements = int64(fileSize./(lineLength));
+
+ fid = fopen(filePath, 'r');
+ offset = 0;
+ for i=1:columns
+ % using fread with a skip speeds up the import drastically, do not
+ % import the values one after the other
+ sysvector.(genvarname(logFormat{i}.name)) = transpose(fread(...
+ fid, ...
+ [logFormat{i}.array, elements], [num2str(logFormat{i}.array),'*',logFormat{i}.precision,'=>',logFormat{i}.precision], ...
+ lineLength - logFormat{i}.bytes*logFormat{i}.array, ...
+ logFormat{i}.machineformat) ...
+ );
+ offset = offset + logFormat{i}.bytes*logFormat{i}.array;
+ fseek(fid, offset,'bof');
+ end
+
+ % shot the flight time
+ time_us = sysvector.timestamp(end) - sysvector.timestamp(1);
+ time_s = time_us*1e-6;
+ time_m = time_s/60;
+
+ % close the logfile
+ fclose(fid);
+
+ disp(['end log2matlab conversion' char(10)]);
+ else
+ disp(['file: ' filePath ' does not exist' char(10)]);
+ end
+end
+
+%% ************************************************************************
+% INITCONTROLGUI (nested function)
+% ************************************************************************
+%Setup central control GUI components to control current time where data is shown
+function InitControlGUI()
+ %**********************************************************************
+ % GUI size definitions
+ %**********************************************************************
+ dxy=5; %margins
+ %Panel: Plotctrl
+ dlabels=120;
+ dsliders=200;
+ dedits=80;
+ hslider=20;
+
+ hpanel1=40; %panel1
+ hpanel2=220;%panel2
+ hpanel3=3*hslider+4*dxy+3*dxy;%panel3.
+
+ width=dlabels+dsliders+dedits+4*dxy+2*dxy; %figure width
+ height=hpanel1+hpanel2+hpanel3+4*dxy; %figure height
+
+ %**********************************************************************
+ % Create GUI
+ %**********************************************************************
+ h.figures(1)=figure('Units','pixels','position',[200 200 width height],'Name','Control GUI');
+ h.guistatepanel=uipanel('Title','Current GUI state','Units','pixels','Position',[dxy dxy width-2*dxy hpanel1],'parent',h.figures(1));
+ h.aircraftstatepanel=uipanel('Title','Current aircraft state','Units','pixels','Position',[dxy hpanel1+2*dxy width-2*dxy hpanel2],'parent',h.figures(1));
+ h.plotctrlpanel=uipanel('Title','Plot Control','Units','pixels','Position',[dxy hpanel1+hpanel2+3*dxy width-2*dxy hpanel3],'parent',h.figures(1));
+
+ %%Control GUI-elements
+ %Slider: Current time
+ h.labels.CurTime=uicontrol(gcf,'style','text','Position',[dxy dxy dlabels hslider],'String','Current time t[s]:','parent',h.plotctrlpanel,'HorizontalAlignment','left');
+ h.sliders.CurTime=uicontrol(gcf,'style','slider','units','pix','position',[2*dxy+dlabels dxy dsliders hslider],...
+ 'min',mintime,'max',maxtime,'value',mintime,'callback',@curtime_callback,'parent',h.plotctrlpanel);
+ temp=get(h.sliders.CurTime,'Max')-get(h.sliders.CurTime,'Min');
+ set(h.sliders.CurTime,'SliderStep',[1.0/temp 5.0/temp]);
+ h.edits.CurTime=uicontrol(gcf,'style','edit','position',[3*dxy+dlabels+dsliders dxy dedits hslider],'String',get(h.sliders.CurTime,'value'),...
+ 'BackgroundColor','white','callback',@curtime_callback,'parent',h.plotctrlpanel);
+
+ %Slider: MaxTime
+ h.labels.MaxTime=uicontrol(gcf,'style','text','position',[dxy 2*dxy+hslider dlabels hslider],'String','Max. time t[s] to display:','parent',h.plotctrlpanel,'HorizontalAlignment','left');
+ h.sliders.MaxTime=uicontrol(gcf,'style','slider','units','pix','position',[2*dxy+dlabels 2*dxy+hslider dsliders hslider],...
+ 'min',mintime_log,'max',maxtime_log,'value',maxtime,'callback',@minmaxtime_callback,'parent',h.plotctrlpanel);
+ h.edits.MaxTime=uicontrol(gcf,'style','edit','position',[3*dxy+dlabels+dsliders 2*dxy+hslider dedits hslider],'String',get(h.sliders.MaxTime,'value'),...
+ 'BackgroundColor','white','callback',@minmaxtime_callback,'parent',h.plotctrlpanel);
+
+ %Slider: MinTime
+ h.labels.MinTime=uicontrol(gcf,'style','text','position',[dxy 3*dxy+2*hslider dlabels hslider],'String','Min. time t[s] to dispay :','parent',h.plotctrlpanel,'HorizontalAlignment','left');
+ h.sliders.MinTime=uicontrol(gcf,'style','slider','units','pix','position',[2*dxy+dlabels 3*dxy+2*hslider dsliders hslider],...
+ 'min',mintime_log,'max',maxtime_log,'value',mintime,'callback',@minmaxtime_callback,'parent',h.plotctrlpanel);
+ h.edits.MinTime=uicontrol(gcf,'style','edit','position',[3*dxy+dlabels+dsliders 3*dxy+2*hslider dedits hslider],'String',get(h.sliders.MinTime,'value'),...
+ 'BackgroundColor','white','callback',@minmaxtime_callback,'parent',h.plotctrlpanel);
+
+ %%Current data/state GUI-elements (Multiline-edit-box)
+ h.edits.AircraftState=uicontrol(gcf,'style','edit','Units','normalized','position',[.02 .02 0.96 0.96],'Min',1,'Max',10,'String','This shows the current aircraft state',...
+ 'HorizontalAlignment','left','parent',h.aircraftstatepanel);
+
+ h.labels.GUIState=uicontrol(gcf,'style','text','Units','pixels','position',[dxy dxy width-4*dxy hslider],'String','Current state of this GUI',...
+ 'HorizontalAlignment','left','parent',h.guistatepanel);
+
+end
+
+%% ************************************************************************
+% INITPLOTGUI (nested function)
+% ************************************************************************
+function InitPlotGUI()
+
+ % Setup handles to lines and text
+ h.markertext=[];
+ templinehandle=0.0;%line([0 1],[0 5]); % Just a temporary handle to init array
+ h.markerline(1:NrAxes)=templinehandle; % the actual handle-array to the lines - these are numbered consecutively
+ h.markerline(1:NrAxes)=0.0;
+
+ % Setup all other figures and axes for plotting
+ % PLOT WINDOW 1: GPS POSITION
+ h.figures(2)=figure('units','normalized','Toolbar','figure', 'Name', 'GPS Position');
+ h.axes(1)=axes();
+ set(h.axes(1),'Parent',h.figures(2));
+
+ % PLOT WINDOW 2: IMU, baro altitude
+ h.figures(3)=figure('Name', 'IMU / Baro Altitude');
+ h.axes(2)=subplot(4,1,1);
+ h.axes(3)=subplot(4,1,2);
+ h.axes(4)=subplot(4,1,3);
+ h.axes(5)=subplot(4,1,4);
+ set(h.axes(2:5),'Parent',h.figures(3));
+
+ % PLOT WINDOW 3: ATTITUDE ESTIMATE, ACTUATORS/CONTROLS, AIRSPEEDS,...
+ h.figures(4)=figure('Name', 'Attitude Estimate / Actuators / Airspeeds');
+ h.axes(6)=subplot(4,1,1);
+ h.axes(7)=subplot(4,1,2);
+ h.axes(8)=subplot(4,1,3);
+ h.axes(9)=subplot(4,1,4);
+ set(h.axes(6:9),'Parent',h.figures(4));
+
+ % PLOT WINDOW 4: LOG STATS
+ h.figures(5) = figure('Name', 'Log Statistics');
+ h.axes(10)=subplot(1,1,1);
+ set(h.axes(10:10),'Parent',h.figures(5));
+
+end
+
+%% ************************************************************************
+% DRAWRAWDATA (nested function)
+% ************************************************************************
+%Draws the raw data from the sysvector, but does not add any
+%marker-lines or so
+function DrawRawData()
+ % ************************************************************************
+ % PLOT WINDOW 1: GPS POSITION & GUI
+ % ************************************************************************
+ figure(h.figures(2));
+ % Only plot GPS data if available
+ if (sum(double(sysvector.gps_raw_position(imintime:imaxtime,1)))>0) && (bDisplayGPS)
+ %Draw data
+ plot3(h.axes(1),double(sysvector.gps_raw_position(imintime:imaxtime,1))*fconv_gpslatlong, ...
+ double(sysvector.gps_raw_position(imintime:imaxtime,2))*fconv_gpslatlong, ...
+ double(sysvector.gps_raw_position(imintime:imaxtime,3))*fconv_gpsalt,'r.');
+ title(h.axes(1),'GPS Position Data(if available)');
+ xlabel(h.axes(1),'Latitude [deg]');
+ ylabel(h.axes(1),'Longitude [deg]');
+ zlabel(h.axes(1),'Altitude above MSL [m]');
+ grid on
+
+ %Reset path
+ h.pathpoints=0;
+ end
+
+ % ************************************************************************
+ % PLOT WINDOW 2: IMU, baro altitude
+ % ************************************************************************
+ figure(h.figures(3));
+ plot(h.axes(2),time(imintime:imaxtime),sysvector.mag(imintime:imaxtime,:));
+ title(h.axes(2),'Magnetometers [Gauss]');
+ legend(h.axes(2),'x','y','z');
+ plot(h.axes(3),time(imintime:imaxtime),sysvector.accel(imintime:imaxtime,:));
+ title(h.axes(3),'Accelerometers [m/s²]');
+ legend(h.axes(3),'x','y','z');
+ plot(h.axes(4),time(imintime:imaxtime),sysvector.gyro(imintime:imaxtime,:));
+ title(h.axes(4),'Gyroscopes [rad/s]');
+ legend(h.axes(4),'x','y','z');
+ plot(h.axes(5),time(imintime:imaxtime),sysvector.baro_alt(imintime:imaxtime),'color','blue');
+ if(bDisplayGPS)
+ hold on;
+ plot(h.axes(5),time(imintime:imaxtime),double(sysvector.gps_raw_position(imintime:imaxtime,3)).*fconv_gpsalt,'color','red');
+ hold off
+ legend('Barometric Altitude [m]','GPS Altitude [m]');
+ else
+ legend('Barometric Altitude [m]');
+ end
+ title(h.axes(5),'Altitude above MSL [m]');
+
+ % ************************************************************************
+ % PLOT WINDOW 3: ATTITUDE ESTIMATE, ACTUATORS/CONTROLS, AIRSPEEDS,...
+ % ************************************************************************
+ figure(h.figures(4));
+ %Attitude Estimate
+ plot(h.axes(6),time(imintime:imaxtime), sysvector.attitude(imintime:imaxtime,:).*180./3.14159);
+ title(h.axes(6),'Estimated attitude [deg]');
+ legend(h.axes(6),'roll','pitch','yaw');
+ %Actuator Controls
+ plot(h.axes(7),time(imintime:imaxtime), sysvector.actuator_control(imintime:imaxtime,:));
+ title(h.axes(7),'Actuator control [-]');
+ legend(h.axes(7),'0','1','2','3');
+ %Actuator Controls
+ plot(h.axes(8),time(imintime:imaxtime), sysvector.actuators(imintime:imaxtime,1:8));
+ title(h.axes(8),'Actuator PWM (raw-)outputs [µs]');
+ legend(h.axes(8),'CH1','CH2','CH3','CH4','CH5','CH6','CH7','CH8');
+ set(h.axes(8), 'YLim',[800 2200]);
+ %Airspeeds
+ plot(h.axes(9),time(imintime:imaxtime), sysvector.ind_airspeed(imintime:imaxtime));
+ hold on
+ plot(h.axes(9),time(imintime:imaxtime), sysvector.true_airspeed(imintime:imaxtime));
+ hold off
+ %add GPS total airspeed here
+ title(h.axes(9),'Airspeed [m/s]');
+ legend(h.axes(9),'Indicated Airspeed (IAS)','True Airspeed (TAS)','GPS Airspeed');
+ %calculate time differences and plot them
+ intervals = zeros(0,imaxtime - imintime);
+ for k = imintime+1:imaxtime
+ intervals(k) = time(k) - time(k-1);
+ end
+ plot(h.axes(10), time(imintime:imaxtime), intervals);
+
+ %Set same timescale for all plots
+ for i=2:NrAxes
+ set(h.axes(i),'XLim',[mintime maxtime]);
+ end
+
+ set(h.labels.GUIState,'String','OK','BackgroundColor',[240/255 240/255 240/255]);
+end
+
+%% ************************************************************************
+% DRAWCURRENTAIRCRAFTSTATE(nested function)
+% ************************************************************************
+function DrawCurrentAircraftState()
+ %find current data index
+ i=find(time>=CurTime,1,'first');
+
+ %**********************************************************************
+ % Current aircraft state label update
+ %**********************************************************************
+ acstate{1,:}=[sprintf('%s \t\t','GPS Pos:'),'[lat=',num2str(double(sysvector.gps_raw_position(i,1))*fconv_gpslatlong),'°, ',...
+ 'lon=',num2str(double(sysvector.gps_raw_position(i,2))*fconv_gpslatlong),'°, ',...
+ 'alt=',num2str(double(sysvector.gps_raw_position(i,3))*fconv_gpsalt),'m]'];
+ acstate{2,:}=[sprintf('%s \t\t','Mags[gauss]'),'[x=',num2str(sysvector.mag(i,1)),...
+ ', y=',num2str(sysvector.mag(i,2)),...
+ ', z=',num2str(sysvector.mag(i,3)),']'];
+ acstate{3,:}=[sprintf('%s \t\t','Accels[m/s²]'),'[x=',num2str(sysvector.accel(i,1)),...
+ ', y=',num2str(sysvector.accel(i,2)),...
+ ', z=',num2str(sysvector.accel(i,3)),']'];
+ acstate{4,:}=[sprintf('%s \t\t','Gyros[rad/s]'),'[x=',num2str(sysvector.gyro(i,1)),...
+ ', y=',num2str(sysvector.gyro(i,2)),...
+ ', z=',num2str(sysvector.gyro(i,3)),']'];
+ acstate{5,:}=[sprintf('%s \t\t','Altitude[m]'),'[Barometric: ',num2str(sysvector.baro_alt(i)),'m, GPS: ',num2str(double(sysvector.gps_raw_position(i,3))*fconv_gpsalt),'m]'];
+ acstate{6,:}=[sprintf('%s \t','Est. attitude[deg]:'),'[Roll=',num2str(sysvector.attitude(i,1).*180./3.14159),...
+ ', Pitch=',num2str(sysvector.attitude(i,2).*180./3.14159),...
+ ', Yaw=',num2str(sysvector.attitude(i,3).*180./3.14159),']'];
+ acstate{7,:}=sprintf('%s \t[','Actuator Ctrls [-]:');
+ for j=1:4
+ acstate{7,:}=[acstate{7,:},num2str(sysvector.actuator_control(i,j)),','];
+ end
+ acstate{7,:}=[acstate{7,:},']'];
+ acstate{8,:}=sprintf('%s \t[','Actuator Outputs [PWM/µs]:');
+ for j=1:8
+ acstate{8,:}=[acstate{8,:},num2str(sysvector.actuators(i,j)),','];
+ end
+ acstate{8,:}=[acstate{8,:},']'];
+ acstate{9,:}=[sprintf('%s \t','Airspeed[m/s]:'),'[IAS: ',num2str(sysvector.ind_airspeed(i)),', TAS: ',num2str(sysvector.true_airspeed(i)),']'];
+
+ set(h.edits.AircraftState,'String',acstate);
+
+ %**********************************************************************
+ % GPS Plot Update
+ %**********************************************************************
+ %Plot traveled path, and and time.
+ figure(h.figures(2));
+ hold on;
+ if(CurTime>mintime+1) %the +1 is only a small bugfix
+ h.pathline=plot3(h.axes(1),double(sysvector.gps_raw_position(imintime:i,1))*fconv_gpslatlong, ...
+ double(sysvector.gps_raw_position(imintime:i,2))*fconv_gpslatlong, ...
+ double(sysvector.gps_raw_position(imintime:i,3))*fconv_gpsalt,'b','LineWidth',2);
+ end;
+ hold off
+ %Plot current position
+ newpoint=[double(sysvector.gps_raw_position(i,1))*fconv_gpslatlong double(sysvector.gps_raw_position(i,2))*fconv_gpslatlong double(sysvector.gps_raw_position(i,3))*fconv_gpsalt];
+ if(numel(h.pathpoints)<=3) %empty path
+ h.pathpoints(1,1:3)=newpoint;
+ else %Not empty, append new point
+ h.pathpoints(size(h.pathpoints,1)+1,:)=newpoint;
+ end
+ axes(h.axes(1));
+ line(h.pathpoints(:,1),h.pathpoints(:,2),h.pathpoints(:,3),'LineStyle','none','Marker','.','MarkerEdge','black','MarkerSize',20);
+
+
+ % Plot current time (small label next to current gps position)
+ textdesc=strcat(' t=',num2str(time(i)),'s');
+ if(isvalidhandle(h.markertext))
+ delete(h.markertext); %delete old text
+ end
+ h.markertext=text(double(sysvector.gps_raw_position(i,1))*fconv_gpslatlong,double(sysvector.gps_raw_position(i,2))*fconv_gpslatlong,...
+ double(sysvector.gps_raw_position(i,3))*fconv_gpsalt,textdesc);
+ set(h.edits.CurTime,'String',CurTime);
+
+ %**********************************************************************
+ % Plot the lines showing the current time in the 2-d plots
+ %**********************************************************************
+ for i=2:NrAxes
+ if(isvalidhandle(h.markerline(i))) delete(h.markerline(i)); end
+ ylims=get(h.axes(i),'YLim');
+ h.markerline(i)=line([CurTime CurTime] ,get(h.axes(i),'YLim'),'Color','black');
+ set(h.markerline(i),'parent',h.axes(i));
+ end
+
+ set(h.labels.GUIState,'String','OK','BackgroundColor',[240/255 240/255 240/255]);
+end
+
+%% ************************************************************************
+% MINMAXTIME CALLBACK (nested function)
+% ************************************************************************
+function minmaxtime_callback(hObj,event) %#ok
+ new_mintime=get(h.sliders.MinTime,'Value');
+ new_maxtime=get(h.sliders.MaxTime,'Value');
+
+ %Safety checks:
+ bErr=false;
+ %1: mintime must be < maxtime
+ if((new_mintime>maxtime) || (new_maxtimeCurTime)
+ set(h.labels.GUIState,'String','Error: Mintime cannot be bigger than CurTime! CurTime set to new mintime.','BackgroundColor','red');
+ mintime=new_mintime;
+ CurTime=mintime;
+ bErr=true;
+ end
+ %3: MaxTime must be >CurTime
+ if(new_maxtime
+ %find current time
+ if(hObj==h.sliders.CurTime)
+ CurTime=get(h.sliders.CurTime,'Value');
+ elseif (hObj==h.edits.CurTime)
+ temp=str2num(get(h.edits.CurTime,'String'));
+ if(tempmintime)
+ CurTime=temp;
+ else
+ %Error
+ set(h.labels.GUIState,'String','Error: You tried to set an invalid current time! Previous value restored.','BackgroundColor','red');
+ end
+ else
+ %Error
+ set(h.labels.GUIState,'String','Error: curtime_callback','BackgroundColor','red');
+ end
+
+ set(h.sliders.CurTime,'Value',CurTime);
+ set(h.edits.CurTime,'String',num2str(CurTime));
+
+ %Redraw time markers, but don't have to redraw the whole raw data
+ DrawCurrentAircraftState();
+end
+
+%% ************************************************************************
+% FINDMINMAXINDICES (nested function)
+% ************************************************************************
+function [idxmin,idxmax] = FindMinMaxTimeIndices()
+ for i=1:size(sysvector.timestamp,1)
+ if time(i)>=mintime; idxmin=i; break; end
+ end
+ for i=1:size(sysvector.timestamp,1)
+ if maxtime==0; idxmax=size(sysvector.timestamp,1); break; end
+ if time(i)>=maxtime; idxmax=i; break; end
+ end
+ mintime=time(idxmin);
+ maxtime=time(idxmax);
+end
+
+%% ************************************************************************
+% ISVALIDHANDLE (nested function)
+% ************************************************************************
+function isvalid = isvalidhandle(handle)
+ if(exist(varname(handle))>0 && length(ishandle(handle))>0)
+ if(ishandle(handle)>0)
+ if(handle>0.0)
+ isvalid=true;
+ return;
+ end
+ end
+ end
+ isvalid=false;
+end
+
+%% ************************************************************************
+% JUST SOME SMALL HELPER FUNCTIONS (nested function)
+% ************************************************************************
+function out = varname(var)
+ out = inputname(1);
+end
+
+%This is the end of the matlab file / the main function
+end
diff --git a/ROMFS/mixers/FMU_AERT.mix b/ROMFS/px4fmu_common/mixers/FMU_AERT.mix
similarity index 100%
rename from ROMFS/mixers/FMU_AERT.mix
rename to ROMFS/px4fmu_common/mixers/FMU_AERT.mix
diff --git a/ROMFS/mixers/FMU_AET.mix b/ROMFS/px4fmu_common/mixers/FMU_AET.mix
similarity index 100%
rename from ROMFS/mixers/FMU_AET.mix
rename to ROMFS/px4fmu_common/mixers/FMU_AET.mix
diff --git a/ROMFS/mixers/FMU_Q.mix b/ROMFS/px4fmu_common/mixers/FMU_Q.mix
similarity index 100%
rename from ROMFS/mixers/FMU_Q.mix
rename to ROMFS/px4fmu_common/mixers/FMU_Q.mix
diff --git a/ROMFS/mixers/FMU_RET.mix b/ROMFS/px4fmu_common/mixers/FMU_RET.mix
similarity index 100%
rename from ROMFS/mixers/FMU_RET.mix
rename to ROMFS/px4fmu_common/mixers/FMU_RET.mix
diff --git a/ROMFS/mixers/FMU_X5.mix b/ROMFS/px4fmu_common/mixers/FMU_X5.mix
similarity index 100%
rename from ROMFS/mixers/FMU_X5.mix
rename to ROMFS/px4fmu_common/mixers/FMU_X5.mix
diff --git a/ROMFS/px4fmu_common/mixers/FMU_delta.mix b/ROMFS/px4fmu_common/mixers/FMU_delta.mix
new file mode 100644
index 0000000000..9814667041
--- /dev/null
+++ b/ROMFS/px4fmu_common/mixers/FMU_delta.mix
@@ -0,0 +1,50 @@
+Delta-wing mixer for PX4FMU
+===========================
+
+This file defines mixers suitable for controlling a delta wing aircraft using
+PX4FMU. The configuration assumes the elevon servos are connected to PX4FMU
+servo outputs 0 and 1 and the motor speed control to output 3. Output 2 is
+assumed to be unused.
+
+Inputs to the mixer come from channel group 0 (vehicle attitude), channels 0
+(roll), 1 (pitch) and 3 (thrust).
+
+See the README for more information on the scaler format.
+
+Elevon mixers
+-------------
+Three scalers total (output, roll, pitch).
+
+On the assumption that the two elevon servos are physically reversed, the pitch
+input is inverted between the two servos.
+
+The scaling factor for roll inputs is adjusted to implement differential travel
+for the elevons.
+
+M: 2
+O: 10000 10000 0 -10000 10000
+S: 0 0 3000 5000 0 -10000 10000
+S: 0 1 5000 5000 0 -10000 10000
+
+M: 2
+O: 10000 10000 0 -10000 10000
+S: 0 0 5000 3000 0 -10000 10000
+S: 0 1 -5000 -5000 0 -10000 10000
+
+Output 2
+--------
+This mixer is empty.
+
+Z:
+
+Motor speed mixer
+-----------------
+Two scalers total (output, thrust).
+
+This mixer generates a full-range output (-1 to 1) from an input in the (0 - 1)
+range. Inputs below zero are treated as zero.
+
+M: 1
+O: 10000 10000 0 -10000 10000
+S: 0 3 0 20000 -10000 -10000 10000
+
diff --git a/ROMFS/mixers/FMU_hex_+.mix b/ROMFS/px4fmu_common/mixers/FMU_hex_+.mix
similarity index 100%
rename from ROMFS/mixers/FMU_hex_+.mix
rename to ROMFS/px4fmu_common/mixers/FMU_hex_+.mix
diff --git a/ROMFS/mixers/FMU_hex_x.mix b/ROMFS/px4fmu_common/mixers/FMU_hex_x.mix
similarity index 100%
rename from ROMFS/mixers/FMU_hex_x.mix
rename to ROMFS/px4fmu_common/mixers/FMU_hex_x.mix
diff --git a/ROMFS/mixers/FMU_octo_+.mix b/ROMFS/px4fmu_common/mixers/FMU_octo_+.mix
similarity index 100%
rename from ROMFS/mixers/FMU_octo_+.mix
rename to ROMFS/px4fmu_common/mixers/FMU_octo_+.mix
diff --git a/ROMFS/mixers/FMU_octo_x.mix b/ROMFS/px4fmu_common/mixers/FMU_octo_x.mix
similarity index 100%
rename from ROMFS/mixers/FMU_octo_x.mix
rename to ROMFS/px4fmu_common/mixers/FMU_octo_x.mix
diff --git a/ROMFS/mixers/FMU_pass.mix b/ROMFS/px4fmu_common/mixers/FMU_pass.mix
similarity index 100%
rename from ROMFS/mixers/FMU_pass.mix
rename to ROMFS/px4fmu_common/mixers/FMU_pass.mix
diff --git a/ROMFS/mixers/FMU_quad_+.mix b/ROMFS/px4fmu_common/mixers/FMU_quad_+.mix
similarity index 100%
rename from ROMFS/mixers/FMU_quad_+.mix
rename to ROMFS/px4fmu_common/mixers/FMU_quad_+.mix
diff --git a/ROMFS/px4fmu_common/mixers/FMU_quad_v.mix b/ROMFS/px4fmu_common/mixers/FMU_quad_v.mix
new file mode 100644
index 0000000000..2a4a0f3419
--- /dev/null
+++ b/ROMFS/px4fmu_common/mixers/FMU_quad_v.mix
@@ -0,0 +1,7 @@
+Multirotor mixer for PX4FMU
+===========================
+
+This file defines a single mixer for a quadrotor in the V configuration. All controls
+are mixed 100%.
+
+R: 4v 10000 10000 10000 0
diff --git a/ROMFS/px4fmu_common/mixers/FMU_quad_w.mix b/ROMFS/px4fmu_common/mixers/FMU_quad_w.mix
new file mode 100644
index 0000000000..81b4af30b2
--- /dev/null
+++ b/ROMFS/px4fmu_common/mixers/FMU_quad_w.mix
@@ -0,0 +1,6 @@
+Multirotor mixer for PX4FMU
+===========================
+
+This file defines a single mixer for a quadrotor with a wide configuration. All controls are mixed 100%.
+
+R: 4w 10000 10000 10000 0
diff --git a/ROMFS/mixers/FMU_quad_x.mix b/ROMFS/px4fmu_common/mixers/FMU_quad_x.mix
similarity index 100%
rename from ROMFS/mixers/FMU_quad_x.mix
rename to ROMFS/px4fmu_common/mixers/FMU_quad_x.mix
diff --git a/ROMFS/mixers/README b/ROMFS/px4fmu_common/mixers/README
similarity index 100%
rename from ROMFS/mixers/README
rename to ROMFS/px4fmu_common/mixers/README
diff --git a/ROMFS/scripts/rc.PX4IO b/ROMFS/scripts/rc.PX4IO
deleted file mode 100644
index 1e3963b9ad..0000000000
--- a/ROMFS/scripts/rc.PX4IO
+++ /dev/null
@@ -1,80 +0,0 @@
-#!nsh
-
-# Disable USB and autostart
-set USB no
-set MODE camflyer
-
-#
-# Start the ORB
-#
-uorb start
-
-#
-# Load microSD params
-#
-echo "[init] loading microSD params"
-param select /fs/microsd/parameters
-if [ -f /fs/microsd/parameters ]
-then
- param load /fs/microsd/parameters
-fi
-
-#
-# Force some key parameters to sane values
-# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
-# see https://pixhawk.ethz.ch/mavlink/
-#
-param set MAV_TYPE 1
-
-#
-# Start the sensors.
-#
-sh /etc/init.d/rc.sensors
-
-#
-# Start MAVLink
-#
-mavlink start -d /dev/ttyS1 -b 57600
-usleep 5000
-
-#
-# Start the commander.
-#
-commander start
-
-#
-# Start GPS interface
-#
-gps start
-
-#
-# Start the attitude estimator
-#
-kalman_demo start
-
-#
-# Start PX4IO interface
-#
-px4io start
-
-#
-# Load mixer and start controllers
-#
-mixer load /dev/pwm_output /etc/mixers/FMU_Q.mix
-control_demo start
-
-#
-# Start logging
-#
-sdlog start -s 10
-
-#
-# Start system state
-#
-if blinkm start
-then
- echo "using BlinkM for state indication"
- blinkm systemstate
-else
- echo "no BlinkM found, OK."
-fi
diff --git a/Tools/px_uploader.py b/Tools/px_uploader.py
index cce388d710..d2ebf16987 100755
--- a/Tools/px_uploader.py
+++ b/Tools/px_uploader.py
@@ -41,20 +41,19 @@
# The uploader uses the following fields from the firmware file:
#
# image
-# The firmware that will be uploaded.
+# The firmware that will be uploaded.
# image_size
-# The size of the firmware in bytes.
+# The size of the firmware in bytes.
# board_id
-# The board for which the firmware is intended.
+# The board for which the firmware is intended.
# board_revision
-# Currently only used for informational purposes.
+# Currently only used for informational purposes.
#
import sys
import argparse
import binascii
import serial
-import os
import struct
import json
import zlib
@@ -64,292 +63,294 @@ import array
from sys import platform as _platform
+
class firmware(object):
- '''Loads a firmware file'''
+ '''Loads a firmware file'''
- desc = {}
- image = bytes()
- crctab = array.array('I', [
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d ])
- crcpad = bytearray('\xff\xff\xff\xff')
+ desc = {}
+ image = bytes()
+ crctab = array.array('I', [
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d])
+ crcpad = bytearray('\xff\xff\xff\xff')
- def __init__(self, path):
+ def __init__(self, path):
- # read the file
- f = open(path, "r")
- self.desc = json.load(f)
- f.close()
+ # read the file
+ f = open(path, "r")
+ self.desc = json.load(f)
+ f.close()
- self.image = bytearray(zlib.decompress(base64.b64decode(self.desc['image'])))
+ self.image = bytearray(zlib.decompress(base64.b64decode(self.desc['image'])))
- # pad image to 4-byte length
- while ((len(self.image) % 4) != 0):
- self.image.append('\xff')
+ # pad image to 4-byte length
+ while ((len(self.image) % 4) != 0):
+ self.image.append('\xff')
- def property(self, propname):
- return self.desc[propname]
+ def property(self, propname):
+ return self.desc[propname]
- def __crc32(self, bytes, state):
- for byte in bytes:
- index = (state ^ byte) & 0xff
- state = self.crctab[index] ^ (state >> 8)
- return state
+ def __crc32(self, bytes, state):
+ for byte in bytes:
+ index = (state ^ byte) & 0xff
+ state = self.crctab[index] ^ (state >> 8)
+ return state
+
+ def crc(self, padlen):
+ state = self.__crc32(self.image, int(0))
+ for i in range(len(self.image), (padlen - 1), 4):
+ state = self.__crc32(self.crcpad, state)
+ return state
- def crc(self, padlen):
- state = self.__crc32(self.image, int(0))
- for i in range(len(self.image), (padlen - 1), 4):
- state = self.__crc32(self.crcpad, state)
- return state
class uploader(object):
- '''Uploads a firmware file to the PX FMU bootloader'''
+ '''Uploads a firmware file to the PX FMU bootloader'''
- # protocol bytes
- INSYNC = chr(0x12)
- EOC = chr(0x20)
+ # protocol bytes
+ INSYNC = chr(0x12)
+ EOC = chr(0x20)
- # reply bytes
- OK = chr(0x10)
- FAILED = chr(0x11)
- INVALID = chr(0x13) # rev3+
+ # reply bytes
+ OK = chr(0x10)
+ FAILED = chr(0x11)
+ INVALID = chr(0x13) # rev3+
- # command bytes
- NOP = chr(0x00) # guaranteed to be discarded by the bootloader
- GET_SYNC = chr(0x21)
- GET_DEVICE = chr(0x22)
- CHIP_ERASE = chr(0x23)
- CHIP_VERIFY = chr(0x24) # rev2 only
- PROG_MULTI = chr(0x27)
- READ_MULTI = chr(0x28) # rev2 only
- GET_CRC = chr(0x29) # rev3+
- REBOOT = chr(0x30)
-
- INFO_BL_REV = chr(1) # bootloader protocol revision
- BL_REV_MIN = 2 # minimum supported bootloader protocol
- BL_REV_MAX = 3 # maximum supported bootloader protocol
- INFO_BOARD_ID = chr(2) # board type
- INFO_BOARD_REV = chr(3) # board revision
- INFO_FLASH_SIZE = chr(4) # max firmware size in bytes
+ # command bytes
+ NOP = chr(0x00) # guaranteed to be discarded by the bootloader
+ GET_SYNC = chr(0x21)
+ GET_DEVICE = chr(0x22)
+ CHIP_ERASE = chr(0x23)
+ CHIP_VERIFY = chr(0x24) # rev2 only
+ PROG_MULTI = chr(0x27)
+ READ_MULTI = chr(0x28) # rev2 only
+ GET_CRC = chr(0x29) # rev3+
+ REBOOT = chr(0x30)
+
+ INFO_BL_REV = chr(1) # bootloader protocol revision
+ BL_REV_MIN = 2 # minimum supported bootloader protocol
+ BL_REV_MAX = 3 # maximum supported bootloader protocol
+ INFO_BOARD_ID = chr(2) # board type
+ INFO_BOARD_REV = chr(3) # board revision
+ INFO_FLASH_SIZE = chr(4) # max firmware size in bytes
- PROG_MULTI_MAX = 60 # protocol max is 255, must be multiple of 4
- READ_MULTI_MAX = 60 # protocol max is 255, something overflows with >= 64
+ PROG_MULTI_MAX = 60 # protocol max is 255, must be multiple of 4
+ READ_MULTI_MAX = 60 # protocol max is 255, something overflows with >= 64
- def __init__(self, portname, baudrate):
- # open the port, keep the default timeout short so we can poll quickly
- self.port = serial.Serial(portname, baudrate, timeout=0.25)
+ def __init__(self, portname, baudrate):
+ # open the port, keep the default timeout short so we can poll quickly
+ self.port = serial.Serial(portname, baudrate, timeout=0.5)
- def close(self):
- if self.port is not None:
- self.port.close()
+ def close(self):
+ if self.port is not None:
+ self.port.close()
- def __send(self, c):
-# print("send " + binascii.hexlify(c))
- self.port.write(str(c))
+ def __send(self, c):
+# print("send " + binascii.hexlify(c))
+ self.port.write(str(c))
- def __recv(self, count = 1):
- c = self.port.read(count)
- if len(c) < 1:
- raise RuntimeError("timeout waiting for data")
-# print("recv " + binascii.hexlify(c))
- return c
+ def __recv(self, count=1):
+ c = self.port.read(count)
+ if len(c) < 1:
+ raise RuntimeError("timeout waiting for data")
+# print("recv " + binascii.hexlify(c))
+ return c
- def __recv_int(self):
- raw = self.__recv(4)
- val = struct.unpack("= 3:
- self.__getSync()
+ # send a PROG_MULTI command to write a collection of bytes
+ def __program_multi(self, data):
+ self.__send(uploader.PROG_MULTI
+ + chr(len(data)))
+ self.__send(data)
+ self.__send(uploader.EOC)
+ self.__getSync()
- # split a sequence into a list of size-constrained pieces
- def __split_len(self, seq, length):
- return [seq[i:i+length] for i in range(0, len(seq), length)]
+ # verify multiple bytes in flash
+ def __verify_multi(self, data):
+ self.__send(uploader.READ_MULTI
+ + chr(len(data))
+ + uploader.EOC)
+ self.port.flush()
+ programmed = self.__recv(len(data))
+ if programmed != data:
+ print("got " + binascii.hexlify(programmed))
+ print("expect " + binascii.hexlify(data))
+ return False
+ self.__getSync()
+ return True
- # upload code
- def __program(self, fw):
- code = fw.image
- groups = self.__split_len(code, uploader.PROG_MULTI_MAX)
- for bytes in groups:
- self.__program_multi(bytes)
+ # send the reboot command
+ def __reboot(self):
+ self.__send(uploader.REBOOT
+ + uploader.EOC)
+ self.port.flush()
- # verify code
- def __verify_v2(self, fw):
- self.__send(uploader.CHIP_VERIFY
- + uploader.EOC)
- self.__getSync()
- code = fw.image
- groups = self.__split_len(code, uploader.READ_MULTI_MAX)
- for bytes in groups:
- if (not self.__verify_multi(bytes)):
- raise RuntimeError("Verification failed")
+ # v3+ can report failure if the first word flash fails
+ if self.bl_rev >= 3:
+ self.__getSync()
- def __verify_v3(self, fw):
- expect_crc = fw.crc(self.fw_maxsize)
- self.__send(uploader.GET_CRC
- + uploader.EOC)
- report_crc = self.__recv_int()
- self.__getSync()
- if report_crc != expect_crc:
- print(("Expected 0x%x" % expect_crc))
- print(("Got 0x%x" % report_crc))
- raise RuntimeError("Program CRC failed")
+ # split a sequence into a list of size-constrained pieces
+ def __split_len(self, seq, length):
+ return [seq[i:i+length] for i in range(0, len(seq), length)]
- # get basic data about the board
- def identify(self):
- # make sure we are in sync before starting
- self.__sync()
+ # upload code
+ def __program(self, fw):
+ code = fw.image
+ groups = self.__split_len(code, uploader.PROG_MULTI_MAX)
+ for bytes in groups:
+ self.__program_multi(bytes)
- # get the bootloader protocol ID first
- self.bl_rev = self.__getInfo(uploader.INFO_BL_REV)
- if (self.bl_rev < uploader.BL_REV_MIN) or (self.bl_rev > uploader.BL_REV_MAX):
- print(("Unsupported bootloader protocol %d" % uploader.INFO_BL_REV))
- raise RuntimeError("Bootloader protocol mismatch")
+ # verify code
+ def __verify_v2(self, fw):
+ self.__send(uploader.CHIP_VERIFY
+ + uploader.EOC)
+ self.__getSync()
+ code = fw.image
+ groups = self.__split_len(code, uploader.READ_MULTI_MAX)
+ for bytes in groups:
+ if (not self.__verify_multi(bytes)):
+ raise RuntimeError("Verification failed")
- self.board_type = self.__getInfo(uploader.INFO_BOARD_ID)
- self.board_rev = self.__getInfo(uploader.INFO_BOARD_REV)
- self.fw_maxsize = self.__getInfo(uploader.INFO_FLASH_SIZE)
+ def __verify_v3(self, fw):
+ expect_crc = fw.crc(self.fw_maxsize)
+ self.__send(uploader.GET_CRC
+ + uploader.EOC)
+ report_crc = self.__recv_int()
+ self.__getSync()
+ if report_crc != expect_crc:
+ print("Expected 0x%x" % expect_crc)
+ print("Got 0x%x" % report_crc)
+ raise RuntimeError("Program CRC failed")
- # upload the firmware
- def upload(self, fw):
- # Make sure we are doing the right thing
- if self.board_type != fw.property('board_id'):
- raise RuntimeError("Firmware not suitable for this board (run 'make configure_px4fmu && make clean' or 'make configure_px4io && make clean' to reconfigure).")
- if self.fw_maxsize < fw.property('image_size'):
- raise RuntimeError("Firmware image is too large for this board")
+ # get basic data about the board
+ def identify(self):
+ # make sure we are in sync before starting
+ self.__sync()
- print("erase...")
- self.__erase()
+ # get the bootloader protocol ID first
+ self.bl_rev = self.__getInfo(uploader.INFO_BL_REV)
+ if (self.bl_rev < uploader.BL_REV_MIN) or (self.bl_rev > uploader.BL_REV_MAX):
+ print("Unsupported bootloader protocol %d" % uploader.INFO_BL_REV)
+ raise RuntimeError("Bootloader protocol mismatch")
- print("program...")
- self.__program(fw)
+ self.board_type = self.__getInfo(uploader.INFO_BOARD_ID)
+ self.board_rev = self.__getInfo(uploader.INFO_BOARD_REV)
+ self.fw_maxsize = self.__getInfo(uploader.INFO_FLASH_SIZE)
- print("verify...")
- if self.bl_rev == 2:
- self.__verify_v2(fw)
- else:
- self.__verify_v3(fw)
+ # upload the firmware
+ def upload(self, fw):
+ # Make sure we are doing the right thing
+ if self.board_type != fw.property('board_id'):
+ raise RuntimeError("Firmware not suitable for this board")
+ if self.fw_maxsize < fw.property('image_size'):
+ raise RuntimeError("Firmware image is too large for this board")
+
+ print("erase...")
+ self.__erase()
+
+ print("program...")
+ self.__program(fw)
+
+ print("verify...")
+ if self.bl_rev == 2:
+ self.__verify_v2(fw)
+ else:
+ self.__verify_v3(fw)
+
+ print("done, rebooting.")
+ self.__reboot()
+ self.port.close()
- print("done, rebooting.")
- self.__reboot()
- self.port.close()
-
# Parse commandline arguments
parser = argparse.ArgumentParser(description="Firmware uploader for the PX autopilot system.")
@@ -360,57 +361,57 @@ args = parser.parse_args()
# Load the firmware file
fw = firmware(args.firmware)
-print(("Loaded firmware for %x,%x, waiting for the bootloader..." % (fw.property('board_id'), fw.property('board_revision'))))
+print("Loaded firmware for %x,%x, waiting for the bootloader..." % (fw.property('board_id'), fw.property('board_revision')))
# Spin waiting for a device to show up
while True:
- for port in args.port.split(","):
+ for port in args.port.split(","):
- #print("Trying %s" % port)
+ #print("Trying %s" % port)
- # create an uploader attached to the port
- try:
- if "linux" in _platform:
- # Linux, don't open Mac OS and Win ports
- if not "COM" in port and not "tty.usb" in port:
- up = uploader(port, args.baud)
- elif "darwin" in _platform:
- # OS X, don't open Windows and Linux ports
- if not "COM" in port and not "ACM" in port:
- up = uploader(port, args.baud)
- elif "win" in _platform:
- # Windows, don't open POSIX ports
- if not "/" in port:
- up = uploader(port, args.baud)
- except:
- # open failed, rate-limit our attempts
- time.sleep(0.05)
+ # create an uploader attached to the port
+ try:
+ if "linux" in _platform:
+ # Linux, don't open Mac OS and Win ports
+ if not "COM" in port and not "tty.usb" in port:
+ up = uploader(port, args.baud)
+ elif "darwin" in _platform:
+ # OS X, don't open Windows and Linux ports
+ if not "COM" in port and not "ACM" in port:
+ up = uploader(port, args.baud)
+ elif "win" in _platform:
+ # Windows, don't open POSIX ports
+ if not "/" in port:
+ up = uploader(port, args.baud)
+ except:
+ # open failed, rate-limit our attempts
+ time.sleep(0.05)
- # and loop to the next port
- continue
+ # and loop to the next port
+ continue
- # port is open, try talking to it
- try:
- # identify the bootloader
- up.identify()
- print(("Found board %x,%x bootloader rev %x on %s" % (up.board_type, up.board_rev, up.bl_rev, port)))
+ # port is open, try talking to it
+ try:
+ # identify the bootloader
+ up.identify()
+ print("Found board %x,%x bootloader rev %x on %s" % (up.board_type, up.board_rev, up.bl_rev, port))
- except:
- # most probably a timeout talking to the port, no bootloader
- continue
+ except:
+ # most probably a timeout talking to the port, no bootloader
+ continue
- try:
- # ok, we have a bootloader, try flashing it
- up.upload(fw)
+ try:
+ # ok, we have a bootloader, try flashing it
+ up.upload(fw)
- except RuntimeError as ex:
+ except RuntimeError as ex:
- # print the error
- print(("ERROR: %s" % ex.args))
+ # print the error
+ print("ERROR: %s" % ex.args)
- finally:
- # always close the port
- up.close()
+ finally:
+ # always close the port
+ up.close()
- # we could loop here if we wanted to wait for more boards...
- sys.exit(0)
+ # we could loop here if we wanted to wait for more boards...
+ sys.exit(0)
diff --git a/apps/drivers/l3gd20/Makefile b/apps/drivers/l3gd20/Makefile
deleted file mode 100644
index 98e2d57c55..0000000000
--- a/apps/drivers/l3gd20/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build the L3GD20 driver.
-#
-
-APPNAME = l3gd20
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/drivers/mpu6000/Makefile b/apps/drivers/mpu6000/Makefile
deleted file mode 100644
index 32df1bdae7..0000000000
--- a/apps/drivers/mpu6000/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build the BMA180 driver.
-#
-
-APPNAME = mpu6000
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/drivers/stm32/adc/Makefile b/apps/drivers/stm32/adc/Makefile
deleted file mode 100644
index 443bc06239..0000000000
--- a/apps/drivers/stm32/adc/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# STM32 ADC driver
-#
-
-APPNAME = adc
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/drivers/stm32/tone_alarm/Makefile b/apps/drivers/stm32/tone_alarm/Makefile
deleted file mode 100644
index d2ddf95340..0000000000
--- a/apps/drivers/stm32/tone_alarm/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Tone alarm driver
-#
-
-APPNAME = tone_alarm
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/examples/Makefile b/apps/examples/Makefile
index 201be955b3..6b614b1aa3 100644
--- a/apps/examples/Makefile
+++ b/apps/examples/Makefile
@@ -38,7 +38,6 @@
# Sub-directories
SUBDIRS = adc can cdcacm nsh
-SUBDIRS += math_demo control_demo kalman_demo px4_deamon_app
#SUBDIRS = adc buttons can cdcacm composite cxxtest dhcpd discover elf ftpc
#SUBDIRS += ftpd hello helloxx hidkbd igmp json keypadtest lcdrw mm modbus mount
diff --git a/apps/examples/control_demo/Makefile b/apps/examples/control_demo/Makefile
deleted file mode 100644
index 6e40e645f8..0000000000
--- a/apps/examples/control_demo/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Basic example application
-#
-
-APPNAME = control_demo
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/examples/kalman_demo/Makefile b/apps/examples/kalman_demo/Makefile
deleted file mode 100644
index 99c34d934e..0000000000
--- a/apps/examples/kalman_demo/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Basic example application
-#
-
-APPNAME = kalman_demo
-PRIORITY = SCHED_PRIORITY_MAX - 30
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/examples/nsh/Makefile b/apps/examples/nsh/Makefile
index c7d212fc2c..ad687958f6 100644
--- a/apps/examples/nsh/Makefile
+++ b/apps/examples/nsh/Makefile
@@ -64,6 +64,8 @@ ROOTDEPPATH = --dep-path .
VPATH =
+MAXOPTIMIZATION = -Os
+
all: .built
.PHONY: clean depend distclean
diff --git a/apps/examples/px4_deamon_app/Makefile b/apps/examples/px4_deamon_app/Makefile
deleted file mode 100644
index e4c169872b..0000000000
--- a/apps/examples/px4_deamon_app/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Basic example application
-#
-
-APPNAME = px4_deamon_app
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/examples/px4_mavlink_debug/Makefile b/apps/examples/px4_mavlink_debug/Makefile
deleted file mode 100644
index f59aef16fb..0000000000
--- a/apps/examples/px4_mavlink_debug/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Basic example application
-#
-
-APPNAME = px4_mavlink_debug
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/examples/px4_simple_app/Makefile b/apps/examples/px4_simple_app/Makefile
deleted file mode 100644
index 102f51fd48..0000000000
--- a/apps/examples/px4_simple_app/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Basic example application
-#
-
-APPNAME = px4_simple_app
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/fixedwing_att_control/Makefile b/apps/fixedwing_att_control/Makefile
deleted file mode 100644
index 01465fa9ec..0000000000
--- a/apps/fixedwing_att_control/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Fixedwing Control application
-#
-
-APPNAME = fixedwing_att_control
-PRIORITY = SCHED_PRIORITY_MAX - 30
-STACKSIZE = 2048
-
-INCLUDES = $(TOPDIR)/../mavlink/include/mavlink
-
-include $(APPDIR)/mk/app.mk
-
diff --git a/apps/fixedwing_pos_control/Makefile b/apps/fixedwing_pos_control/Makefile
deleted file mode 100644
index bce391f499..0000000000
--- a/apps/fixedwing_pos_control/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Fixedwing Control application
-#
-
-APPNAME = fixedwing_pos_control
-PRIORITY = SCHED_PRIORITY_MAX - 30
-STACKSIZE = 2048
-
-INCLUDES = $(TOPDIR)/../mavlink/include/mavlink
-
-include $(APPDIR)/mk/app.mk
-
diff --git a/apps/hott_telemetry/Makefile b/apps/hott_telemetry/Makefile
deleted file mode 100644
index 8d5faa3b7f..0000000000
--- a/apps/hott_telemetry/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Graupner HoTT Telemetry application.
-#
-
-# The following line is required for accessing UARTs directly.
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
-
-APPNAME = hott_telemetry
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/mavlink/.context b/apps/mavlink/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/mavlink_onboard/Makefile b/apps/mavlink_onboard/Makefile
deleted file mode 100644
index 8b1cb9b2c7..0000000000
--- a/apps/mavlink_onboard/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Mavlink Application
-#
-
-APPNAME = mavlink_onboard
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-INCLUDES = $(TOPDIR)/../mavlink/include/mavlink
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/mk/app.mk b/apps/mk/app.mk
deleted file mode 100644
index fa4a12cab6..0000000000
--- a/apps/mk/app.mk
+++ /dev/null
@@ -1,237 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Common Makefile for nsh command modules and utility libraries; should be
-# included by the module-specific Makefile.
-#
-# To build an app that appears as an nsh external command, the caller
-# must define:
-#
-# APPNAME - the name of the application, defaults to the name
-# of the parent directory.
-#
-# If APPNAME is not defined, a utility library is built instead. The library
-# name is normally automatically determined, but it can be overridden by
-# setting:
-#
-# LIBNAME - the name of the library, defaults to the name of the
-# directory
-#
-# The calling makefile may also set:
-#
-# ASRCS - list of assembly source files, defaults to all .S
-# files in the directory
-#
-# CSRCS - list of C source files, defaults to all .c files
-# in the directory
-#
-# CXXSRCS - list of C++ source files, defaults to all .cpp
-# files in the directory
-#
-# INCLUDES - list of directories to be added to the include
-# search path
-#
-# PRIORITY - thread priority for the command (defaults to
-# SCHED_PRIORITY_DEFAULT)
-#
-# STACKSIZE - stack size for the command (defaults to
-# CONFIG_PTHREAD_STACK_DEFAULT)
-#
-# Symbols in the module are private to the module unless deliberately exported
-# using the __EXPORT tag, or DEFAULT_VISIBILITY is set
-#
-
-############################################################################
-# No user-serviceable parts below
-############################################################################
-
-
-############################################################################
-# Work out who included us so we can report decent errors
-#
-THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
-ifeq ($(APP_MAKEFILE),)
-APP_MAKEFILE := $(lastword $(filter-out $(THIS_MAKEFILE),$(MAKEFILE_LIST)))
-endif
-
-############################################################################
-# Get configuration
-#
--include $(TOPDIR)/.config
--include $(TOPDIR)/Make.defs
-include $(APPDIR)/Make.defs
-
-############################################################################
-# Sanity-check the information we've been given and set any defaults
-#
-SRCDIR ?= $(dir $(APP_MAKEFILE))
-PRIORITY ?= SCHED_PRIORITY_DEFAULT
-STACKSIZE ?= CONFIG_PTHREAD_STACK_DEFAULT
-
-INCLUDES += $(APPDIR)
-
-ASRCS ?= $(wildcard $(SRCDIR)/*.S)
-CSRCS ?= $(wildcard $(SRCDIR)/*.c)
-CHDRS ?= $(wildcard $(SRCDIR)/*.h)
-CXXSRCS ?= $(wildcard $(SRCDIR)/*.cpp)
-CXXHDRS ?= $(wildcard $(SRCDIR)/*.hpp)
-
-# if APPNAME is not set, this is a library
-ifeq ($(APPNAME),)
-LIBNAME ?= $(lastword $(subst /, ,$(realpath $(SRCDIR))))
-endif
-
-# there has to be a source file
-ifeq ($(ASRCS)$(CSRCS)$(CXXSRCS),)
-$(error $(realpath $(APP_MAKEFILE)): at least one of ASRCS, CSRCS or CXXSRCS must be set)
-endif
-
-# check that C++ is configured if we have C++ source files and we are building
-ifneq ($(CXXSRCS),)
-ifneq ($(CONFIG_HAVE_CXX),y)
-ifeq ($(MAKECMDGOALS),build)
-$(error $(realpath $(APP_MAKEFILE)): cannot set CXXSRCS if CONFIG_HAVE_CXX not set in configuration)
-endif
-endif
-endif
-
-############################################################################
-# Adjust compilation flags to implement EXPORT
-#
-
-ifeq ($(DEFAULT_VISIBILITY),)
-DEFAULT_VISIBILITY = hidden
-else
-DEFAULT_VISIBILITY = default
-endif
-
-CFLAGS += -fvisibility=$(DEFAULT_VISIBILITY) -include $(APPDIR)/systemlib/visibility.h
-CXXFLAGS += -fvisibility=$(DEFAULT_VISIBILITY) -include $(APPDIR)/systemlib/visibility.h
-
-############################################################################
-# Add extra include directories
-#
-CFLAGS += $(addprefix -I,$(INCLUDES))
-CXXFLAGS += $(addprefix -I,$(INCLUDES))
-
-############################################################################
-# Things we are going to build
-#
-
-SRCS = $(ASRCS) $(CSRCS) $(CXXSRCS)
-AOBJS = $(patsubst %.S,%.o,$(ASRCS))
-COBJS = $(patsubst %.c,%.o,$(CSRCS))
-CXXOBJS = $(patsubst %.cpp,%.o,$(CXXSRCS))
-OBJS = $(AOBJS) $(COBJS) $(CXXOBJS)
-
-# Automatic depdendency generation
-DEPS = $(OBJS:$(OBJEXT)=.d)
-CFLAGS += -MD
-CXXFLAGS += -MD
-
-# The prelinked object that we are ultimately going to build
-ifneq ($(APPNAME),)
-PRELINKOBJ = $(APPNAME).pre.o
-else
-PRELINKOBJ = $(LIBNAME).pre.o
-endif
-
-# The archive the prelinked object will be linked into
-# XXX does WINTOOL ever get set?
-ifeq ($(WINTOOL),y)
- INCDIROPT = -w
- BIN = "$(shell cygpath -w $(APPDIR)/libapps$(LIBEXT))"
-else
- BIN = "$(APPDIR)/libapps$(LIBEXT)"
-endif
-
-############################################################################
-# Rules for building things
-#
-
-all: .built
-.PHONY: clean depend distclean
-
-#
-# Top-level build; add prelinked object to the apps archive
-#
-.built: $(PRELINKOBJ)
- @$(call ARCHIVE, $(BIN), $(PRELINKOBJ))
- @touch $@
-
-#
-# Source dependencies
-#
-depend:
- @exit 0
-
-ifneq ($(APPNAME),)
-#
-# App registration
-#
-context: .context
-.context: $(MAKEFILE_LIST)
- $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
- @touch $@
-else
-context:
- @exit 0
-endif
-
-#
-# Object files
-#
-$(PRELINKOBJ): $(OBJS)
- $(call PRELINK, $@, $(OBJS))
-
-$(AOBJS): %.o : %.S $(MAKEFILE_LIST)
- $(call ASSEMBLE, $<, $@)
-
-$(COBJS): %.o : %.c $(MAKEFILE_LIST)
- $(call COMPILE, $<, $@)
-
-$(CXXOBJS): %.o : %.cpp $(MAKEFILE_LIST)
- $(call COMPILEXX, $<, $@)
-
-#
-# Tidying up
-#
-clean:
- @rm -f $(OBJS) $(DEPS) $(PRELINKOBJ) .built
- $(call CLEAN)
-
-distclean: clean
- @rm -f Make.dep .depend
-
--include $(DEPS)
diff --git a/apps/multirotor_pos_control/Makefile b/apps/multirotor_pos_control/Makefile
deleted file mode 100644
index c88c854356..0000000000
--- a/apps/multirotor_pos_control/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build multirotor position control
-#
-
-APPNAME = multirotor_pos_control
-PRIORITY = SCHED_PRIORITY_MAX - 25
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
index 76cdac40d5..4256a10918 100644
--- a/apps/nshlib/Makefile
+++ b/apps/nshlib/Makefile
@@ -107,6 +107,8 @@ endif
ROOTDEPPATH = --dep-path .
VPATH =
+MAXOPTIMIZATION = -Os
+
# Build targets
all: .built
diff --git a/apps/position_estimator/.context b/apps/position_estimator/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/px4/tests/.context b/apps/px4/tests/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/px4/tests/Makefile b/apps/px4/tests/Makefile
deleted file mode 100644
index cb1c3c6185..0000000000
--- a/apps/px4/tests/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build assorted test cases
-#
-
-APPNAME = tests
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 12000
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/sensors/.context b/apps/sensors/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/system/i2c/Makefile b/apps/system/i2c/Makefile
index 1ed7a2faef..7f0e6005b5 100644
--- a/apps/system/i2c/Makefile
+++ b/apps/system/i2c/Makefile
@@ -64,8 +64,9 @@ VPATH =
APPNAME = i2c
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = 2048
+MAXOPTIMIZATION = -Os
-# Build targets
+# Build Targets
all: .built
.PHONY: context .depend depend clean distclean
diff --git a/apps/systemcmds/bl_update/Makefile b/apps/systemcmds/bl_update/Makefile
deleted file mode 100644
index 9d0e156f60..0000000000
--- a/apps/systemcmds/bl_update/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Build the eeprom tool.
-#
-
-APPNAME = bl_update
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/boardinfo/.context b/apps/systemcmds/boardinfo/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/systemcmds/boardinfo/Makefile b/apps/systemcmds/boardinfo/Makefile
deleted file mode 100644
index 753a6843e5..0000000000
--- a/apps/systemcmds/boardinfo/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Build the boardinfo tool.
-#
-
-APPNAME = boardinfo
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/calibration/Makefile b/apps/systemcmds/calibration/Makefile
deleted file mode 100644
index aa1aa77610..0000000000
--- a/apps/systemcmds/calibration/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build the calibration tool
-#
-
-APPNAME = calibration
-PRIORITY = SCHED_PRIORITY_MAX - 1
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/calibration/calibration.c b/apps/systemcmds/calibration/calibration.c
deleted file mode 100755
index 7f8b9240f4..0000000000
--- a/apps/systemcmds/calibration/calibration.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
- * calibration.c
- *
- * Copyright (C) 2012 Ivan Ovinnikov. All rights reserved.
- * Authors: Nils Wenzler
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-#include
-#include
-#include
-#include "calibration.h"
-
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
-
-static int calibrate_help(int argc, char *argv[]);
-static int calibrate_all(int argc, char *argv[]);
-
-__EXPORT int calibration_main(int argc, char *argv[]);
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-struct {
- const char *name;
- int (* fn)(int argc, char *argv[]);
- unsigned options;
-#define OPT_NOHELP (1<<0)
-#define OPT_NOALLTEST (1<<1)
-} calibrates[] = {
- {"range", range_cal, 0},
- {"servo", servo_cal, 0},
- {"all", calibrate_all, OPT_NOALLTEST},
- {"help", calibrate_help, OPT_NOALLTEST | OPT_NOHELP},
- {NULL, NULL}
-};
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-static int
-calibrate_help(int argc, char *argv[])
-{
- unsigned i;
-
- printf("Available calibration routines:\n");
-
- for (i = 0; calibrates[i].name; i++)
- printf(" %s\n", calibrates[i].name);
-
- return 0;
-}
-
-static int
-calibrate_all(int argc, char *argv[])
-{
- unsigned i;
- char *args[2] = {"all", NULL};
-
- printf("Running all calibration routines...\n\n");
-
- for (i = 0; calibrates[i].name; i++) {
- printf(" %s:\n", calibrates[i].name);
-
- if (calibrates[i].fn(1, args)) {
- printf(" FAIL\n");
-
- } else {
- printf(" DONE\n");
- }
- }
-
- return 0;
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-void press_enter(void)
-{
- int c;
- printf("Press CTRL+ENTER to continue... \n");
- fflush(stdout);
-
- do c = getchar(); while ((c != '\n') && (c != EOF));
-}
-
-/****************************************************************************
- * Name: calibrate_main
- ****************************************************************************/
-
-int calibration_main(int argc, char *argv[])
-{
- unsigned i;
-
- if (argc < 2) {
- printf("calibration: missing name - 'calibration help' for a list of routines\n");
- return 1;
- }
-
- for (i = 0; calibrates[i].name; i++) {
- if (!strcmp(calibrates[i].name, argv[1]))
- return calibrates[i].fn(argc - 1, argv + 1);
- }
-
- printf("calibrate: no routines called '%s' - 'calibration help' for a list of routines\n", argv[1]);
- return 1;
-}
diff --git a/apps/systemcmds/calibration/channels_cal.c b/apps/systemcmds/calibration/channels_cal.c
deleted file mode 100755
index 575138b120..0000000000
--- a/apps/systemcmds/calibration/channels_cal.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/****************************************************************************
- * channels_cal.c
- *
- * Copyright (C) 2012 Nils Wenzler. All rights reserved.
- * Authors: Nils Wenzler
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-#include
-#include
-#include
-#include "calibration.h"
-
-/****************************************************************************
- * Defines
- ****************************************************************************/
-#define ABS(a) (((a) < 0) ? -(a) : (a))
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-//Store the values here before writing them to global_data_rc_channels
-uint16_t old_values[NR_CHANNELS];
-uint16_t cur_values[NR_CHANNELS];
-uint8_t function_map[NR_CHANNELS];
-char names[12][9];
-
-
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-void press_enter_2(void)
-{
- int c;
- printf("Press CTRL+ENTER to continue... \n");
- fflush(stdout);
-
- do c = getchar(); while ((c != '\n') && (c != EOF));
-}
-
-/**This gets all current values and writes them to min or max
- */
-uint8_t get_val(uint16_t *buffer)
-{
- if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) {
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- printf("Channel: %i\t RAW Value: %i: \n", i, global_data_rc_channels->chan[i].raw);
- buffer[i] = global_data_rc_channels->chan[i].raw;
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
- return 0;
-
- } else
- return -1;
-}
-
-void set_channel(void)
-{
- static uint8_t j = 0;
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- if (ABS(old_values - cur_values) > 50) {
- function_map[j] = i;
- strcpy(names[i], global_data_rc_channels->function_names[j]);
- j++;
- }
- }
-}
-
-void write_dat(void)
-{
- global_data_lock(&global_data_rc_channels->access_conf);
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- global_data_rc_channels->function[i] = function_map[i];
- strcpy(global_data_rc_channels->chan[i].name, names[i]);
-
- printf("Channel %i\t Function %s\n", i,
- global_data_rc_channels->chan[i].name);
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
-}
-
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-int channels_cal(int argc, char *argv[])
-{
-
- printf("This routine maps the input functions on the remote control\n");
- printf("to the corresponding function (Throttle, Roll,..)\n");
- printf("Always move the stick all the way\n");
- press_enter_2();
-
- printf("Pull the THROTTLE stick down\n");
- press_enter_2();
-
- while (get_val(old_values));
-
- printf("Move the THROTTLE stick up\n ");
- press_enter_2();
-
- while (get_val(cur_values));
-
- set_channel();
-
- printf("Pull the PITCH stick down\n");
- press_enter_2();
-
- while (get_val(old_values));
-
- printf("Move the PITCH stick up\n ");
- press_enter_2();
-
- while (get_val(cur_values));
-
- set_channel();
-
- printf("Put the ROLL stick to the left\n");
- press_enter_2();
-
- while (get_val(old_values));
-
- printf("Put the ROLL stick to the right\n ");
- press_enter_2();
-
- while (get_val(cur_values));
-
- set_channel();
-
- printf("Put the YAW stick to the left\n");
- press_enter_2();
-
- while (get_val(old_values));
-
- printf("Put the YAW stick to the right\n ");
- press_enter_2();
-
- while (get_val(cur_values));
-
- set_channel();
-
- uint8_t k;
-
- for (k = 5; k < NR_CHANNELS; k++) {
- function_map[k] = k;
- strcpy(names[k], global_data_rc_channels->function_names[k]);
- }
-
-//write the values to global_data_rc_channels
- write_dat();
-
- return 0;
-
-}
-
diff --git a/apps/systemcmds/calibration/range_cal.c b/apps/systemcmds/calibration/range_cal.c
deleted file mode 100755
index 159a0d06b7..0000000000
--- a/apps/systemcmds/calibration/range_cal.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/****************************************************************************
- * range_cal.c
- *
- * Copyright (C) 2012 Nils Wenzler. All rights reserved.
- * Authors: Nils Wenzler
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-#include
-#include
-#include "calibration.h"
-
-/****************************************************************************
- * Defines
- ****************************************************************************/
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-//Store the values here before writing them to global_data_rc_channels
-uint16_t max_values[NR_CHANNELS];
-uint16_t min_values[NR_CHANNELS];
-uint16_t mid_values[NR_CHANNELS];
-
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/**This sets the middle values
- */
-uint8_t set_mid(void)
-{
- if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) {
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- if (i == global_data_rc_channels->function[ROLL] ||
- i == global_data_rc_channels->function[YAW] ||
- i == global_data_rc_channels->function[PITCH]) {
-
- mid_values[i] = global_data_rc_channels->chan[i].raw;
-
- } else {
- mid_values[i] = (max_values[i] + min_values[i]) / 2;
- }
-
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
- return 0;
-
- } else
- return -1;
-}
-
-/**This gets all current values and writes them to min or max
- */
-uint8_t get_value(void)
-{
- if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) {
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- //see if the value is bigger or smaller than 1500 (roughly neutral)
- //and write to the appropriate array
- if (global_data_rc_channels->chan[i].raw != 0 &&
- global_data_rc_channels->chan[i].raw < 1500) {
- min_values[i] = global_data_rc_channels->chan[i].raw;
-
- } else if (global_data_rc_channels->chan[i].raw != 0 &&
- global_data_rc_channels->chan[i].raw > 1500) {
- max_values[i] = global_data_rc_channels->chan[i].raw;
-
- } else {
- max_values[i] = 0;
- min_values[i] = 0;
- }
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
- return 0;
-
- } else
- return -1;
-}
-
-
-void write_data(void)
-{
- // global_data_lock(&global_data_rc_channels->access_conf);
- // uint8_t i;
- // for(i=0; i < NR_CHANNELS; i++){
- // //Write the data to global_data_rc_channels (if not 0)
- // if(mid_values[i]!=0 && min_values[i]!=0 && max_values[i]!=0){
- // global_data_rc_channels->chan[i].scaling_factor =
- // 10000/((max_values[i] - min_values[i])/2);
- //
- // global_data_rc_channels->chan[i].mid = mid_values[i];
- // }
- //
- // printf("Channel %i\t Function %s \t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n",
- // i,
- // global_data_rc_channels->function_name[global_data_rc_channels->function[i]],
- // min_values[i], max_values[i],
- // global_data_rc_channels->chan[i].scaling_factor,
- // global_data_rc_channels->chan[i].mid);
- // }
- // global_data_unlock(&global_data_rc_channels->access_conf);
-
- //Write to the Parameter storage
-
- global_data_parameter_storage->pm.param_values[PARAM_RC1_MIN] = min_values[0];
- global_data_parameter_storage->pm.param_values[PARAM_RC2_MIN] = min_values[1];
- global_data_parameter_storage->pm.param_values[PARAM_RC3_MIN] = min_values[2];
- global_data_parameter_storage->pm.param_values[PARAM_RC4_MIN] = min_values[3];
- global_data_parameter_storage->pm.param_values[PARAM_RC5_MIN] = min_values[4];
- global_data_parameter_storage->pm.param_values[PARAM_RC6_MIN] = min_values[5];
- global_data_parameter_storage->pm.param_values[PARAM_RC7_MIN] = min_values[6];
- global_data_parameter_storage->pm.param_values[PARAM_RC8_MIN] = min_values[7];
-
-
- global_data_parameter_storage->pm.param_values[PARAM_RC1_MAX] = max_values[0];
- global_data_parameter_storage->pm.param_values[PARAM_RC2_MAX] = max_values[1];
- global_data_parameter_storage->pm.param_values[PARAM_RC3_MAX] = max_values[2];
- global_data_parameter_storage->pm.param_values[PARAM_RC4_MAX] = max_values[3];
- global_data_parameter_storage->pm.param_values[PARAM_RC5_MAX] = max_values[4];
- global_data_parameter_storage->pm.param_values[PARAM_RC6_MAX] = max_values[5];
- global_data_parameter_storage->pm.param_values[PARAM_RC7_MAX] = max_values[6];
- global_data_parameter_storage->pm.param_values[PARAM_RC8_MAX] = max_values[7];
-
-
- global_data_parameter_storage->pm.param_values[PARAM_RC1_TRIM] = mid_values[0];
- global_data_parameter_storage->pm.param_values[PARAM_RC2_TRIM] = mid_values[1];
- global_data_parameter_storage->pm.param_values[PARAM_RC3_TRIM] = mid_values[2];
- global_data_parameter_storage->pm.param_values[PARAM_RC4_TRIM] = mid_values[3];
- global_data_parameter_storage->pm.param_values[PARAM_RC5_TRIM] = mid_values[4];
- global_data_parameter_storage->pm.param_values[PARAM_RC6_TRIM] = mid_values[5];
- global_data_parameter_storage->pm.param_values[PARAM_RC7_TRIM] = mid_values[6];
- global_data_parameter_storage->pm.param_values[PARAM_RC8_TRIM] = mid_values[7];
-
- usleep(3e6);
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- printf("Channel %i:\t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n",
- i,
- min_values[i], max_values[i],
- global_data_rc_channels->chan[i].scaling_factor,
- global_data_rc_channels->chan[i].mid);
- }
-
-
-}
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-int range_cal(int argc, char *argv[])
-{
-
- printf("The range calibration routine assumes you already did the channel\n");
- printf("assignment\n");
- printf("This routine chooses the minimum, maximum and middle\n");
- printf("value for each channel separatly. The ROLL, PITCH and YAW function\n");
- printf("get their middle value from the RC direct, for the rest it is\n");
- printf("calculated out of the min and max values.\n");
- press_enter();
-
- printf("Hold both sticks in lower left corner and continue\n ");
- press_enter();
- usleep(500000);
-
- while (get_value());
-
- printf("Hold both sticks in upper right corner and continue\n");
- press_enter();
- usleep(500000);
-
- while (get_value());
-
- printf("Set the trim to 0 and leave the sticks in the neutral position\n");
- press_enter();
-
- //Loop until successfull
- while (set_mid());
-
- //write the values to global_data_rc_channels
- write_data();
-
- return 0;
-
-}
-
diff --git a/apps/systemcmds/calibration/servo_cal.c b/apps/systemcmds/calibration/servo_cal.c
deleted file mode 100644
index 96b3045a95..0000000000
--- a/apps/systemcmds/calibration/servo_cal.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/****************************************************************************
- * servo_cal.c
- *
- * Copyright (C) 2012 Nils Wenzler. All rights reserved.
- * Authors: Nils Wenzler
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-#include
-#include
-#include
-#include
-#include "calibration.h"
-
-/****************************************************************************
- * Defines
- ****************************************************************************/
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-//Store the values here before writing them to global_data_rc_channels
-uint16_t max_values_servo[PWM_SERVO_MAX_CHANNELS];
-uint16_t min_values_servo[PWM_SERVO_MAX_CHANNELS];
-uint16_t mid_values_servo[PWM_SERVO_MAX_CHANNELS];
-
-// Servo loop thread
-
-pthread_t servo_calib_thread;
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/**This sets the middle values
- */
-uint8_t set_mid_s(void)
-{
- if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) {
- uint8_t i;
-
- for (i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) {
- if (i == global_data_rc_channels->function[ROLL] ||
- i == global_data_rc_channels->function[YAW] ||
- i == global_data_rc_channels->function[PITCH]) {
-
- mid_values_servo[i] = global_data_rc_channels->chan[i].raw;
-
- } else {
- mid_values_servo[i] = (max_values_servo[i] + min_values_servo[i]) / 2;
- }
-
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
- return 0;
-
- } else
- return -1;
-}
-
-/**This gets all current values and writes them to min or max
- */
-uint8_t get_value_s(void)
-{
- if (0 == global_data_trylock(&global_data_rc_channels->access_conf)) {
- uint8_t i;
-
- for (i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) {
- //see if the value is bigger or smaller than 1500 (roughly neutral)
- //and write to the appropriate array
- if (global_data_rc_channels->chan[i].raw != 0 &&
- global_data_rc_channels->chan[i].raw < 1500) {
- min_values_servo[i] = global_data_rc_channels->chan[i].raw;
-
- } else if (global_data_rc_channels->chan[i].raw != 0 &&
- global_data_rc_channels->chan[i].raw > 1500) {
- max_values_servo[i] = global_data_rc_channels->chan[i].raw;
-
- } else {
- max_values_servo[i] = 0;
- min_values_servo[i] = 0;
- }
- }
-
- global_data_unlock(&global_data_rc_channels->access_conf);
- return 0;
-
- } else
- return -1;
-}
-
-
-void write_data_s(void)
-{
- // global_data_lock(&global_data_rc_channels->access_conf);
- // uint8_t i;
- // for(i=0; i < NR_CHANNELS; i++){
- // //Write the data to global_data_rc_channels (if not 0)
- // if(mid_values_servo[i]!=0 && min_values_servo[i]!=0 && max_values_servo[i]!=0){
- // global_data_rc_channels->chan[i].scaling_factor =
- // 10000/((max_values_servo[i] - min_values_servo[i])/2);
- //
- // global_data_rc_channels->chan[i].mid = mid_values_servo[i];
- // }
- //
- // printf("Channel %i\t Function %s \t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n",
- // i,
- // global_data_rc_channels->function_name[global_data_rc_channels->function[i]],
- // min_values_servo[i], max_values_servo[i],
- // global_data_rc_channels->chan[i].scaling_factor,
- // global_data_rc_channels->chan[i].mid);
- // }
- // global_data_unlock(&global_data_rc_channels->access_conf);
-
- //Write to the Parameter storage
-
-
-
- global_data_lock(&global_data_parameter_storage->access_conf);
-
- global_data_parameter_storage->pm.param_values[PARAM_SERVO1_MIN] = min_values_servo[0];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO2_MIN] = min_values_servo[1];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO3_MIN] = min_values_servo[2];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO4_MIN] = min_values_servo[3];
-
- global_data_parameter_storage->pm.param_values[PARAM_SERVO1_MAX] = max_values_servo[0];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO2_MAX] = max_values_servo[1];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO3_MAX] = max_values_servo[2];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO4_MAX] = max_values_servo[3];
-
- global_data_parameter_storage->pm.param_values[PARAM_SERVO1_TRIM] = mid_values_servo[0];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO2_TRIM] = mid_values_servo[1];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO3_TRIM] = mid_values_servo[2];
- global_data_parameter_storage->pm.param_values[PARAM_SERVO4_TRIM] = mid_values_servo[3];
-
- global_data_unlock(&global_data_parameter_storage->access_conf);
-
- usleep(3e6);
- uint8_t i;
-
- for (i = 0; i < NR_CHANNELS; i++) {
- printf("Channel %i:\t\t Min %i\t\t Max %i\t\t Scaling Factor: %i\t Middle Value %i\n",
- i,
- min_values_servo[i], max_values_servo[i],
- global_data_rc_channels->chan[i].scaling_factor,
- global_data_rc_channels->chan[i].mid);
- }
-
-}
-
-static void *servo_loop(void *arg)
-{
-
- // Set thread name
- prctl(1, "calibration servo", getpid());
-
- // initialize servos
- int fd;
- servo_position_t data[PWM_SERVO_MAX_CHANNELS];
-
- fd = open("/dev/pwm_servo", O_RDWR);
-
- if (fd < 0) {
- printf("failed opening /dev/pwm_servo\n");
- }
-
- ioctl(fd, PWM_SERVO_ARM, 0);
-
- while (1) {
- int i;
-
- for (i = 0; i < 4; i++) {
- data[i] = global_data_rc_channels->chan[global_data_rc_channels->function[THROTTLE]].raw;
- }
-
- int result = write(fd, &data, sizeof(data));
-
- if (result != sizeof(data)) {
- printf("failed bulk-reading channel values\n");
- }
-
- // 5Hz loop
- usleep(200000);
- }
-
- return NULL;
-}
-
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-int servo_cal(int argc, char *argv[])
-{
- // pthread_attr_t servo_loop_attr;
- // pthread_attr_init(&servo_loop_attr);
- // pthread_attr_setstacksize(&servo_loop_attr, 1024);
- pthread_create(&servo_calib_thread, NULL, servo_loop, NULL);
- pthread_join(servo_calib_thread, NULL);
-
- printf("The servo calibration routine assumes you already did the channel\n");
- printf("assignment with 'calibration channels'\n");
- printf("This routine chooses the minimum, maximum and middle\n");
- printf("value for each channel separately. The ROLL, PITCH and YAW function\n");
- printf("get their middle value from the RC direct, for the rest it is\n");
- printf("calculated out of the min and max values.\n");
- press_enter();
-
- printf("Hold both sticks in lower left corner and continue\n ");
- press_enter();
- usleep(500000);
-
- while (get_value_s());
-
- printf("Hold both sticks in upper right corner and continue\n");
- press_enter();
- usleep(500000);
-
- while (get_value_s());
-
- printf("Set the trim to 0 and leave the sticks in the neutral position\n");
- press_enter();
-
- //Loop until successfull
- while (set_mid_s());
-
- //write the values to global_data_rc_channels
- write_data_s();
-
- return 0;
-
-}
-
diff --git a/apps/systemcmds/delay_test/delay_test.c b/apps/systemcmds/delay_test/delay_test.c
deleted file mode 100644
index 51cce38fca..0000000000
--- a/apps/systemcmds/delay_test/delay_test.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/****************************************************************************
- *
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
- * Author: Lorenz Meier
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name PX4 nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
-
-/**
- * @file delay_test.c
- *
- * Simple but effective delay test using leds and a scope to measure
- * communication delays end-to-end accurately.
- *
- * @author Lorenz Meier
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-
-__EXPORT int delay_test_main(int argc, char *argv[]);
-static int led_on(int leds, int led);
-static int led_off(int leds, int led);
-
-int delay_test_main(int argc, char *argv[])
-{
- bool vicon_msg = false;
- bool command_msg = false;
-
- if (argc > 1 && !strcmp(argv[1], "--help")) {
- warnx("usage: delay_test [vicon] [command]\n");
- exit(1);
- }
-
- if (argc > 1 && !strcmp(argv[1], "vicon")) {
- vicon_msg = true;
- }
-
- if (argc > 1 && !strcmp(argv[1], "command")) {
- command_msg = true;
- }
-
- int buzzer = open("/dev/tone_alarm", O_WRONLY);
- int leds = open(LED_DEVICE_PATH, 0);
-
- /* prepare use of amber led */
- led_off(leds, LED_AMBER);
-
- int topic;
-
- /* subscribe to topic */
- if (vicon_msg) {
- topic = orb_subscribe(ORB_ID(vehicle_vicon_position));
- } else if (command_msg) {
- topic = orb_subscribe(ORB_ID(vehicle_command));
- } else {
- errx(1, "No topic selected for delay test, use --help for a list of topics.");
- }
-
- const int testcount = 20;
-
- warnx("running %d iterations..\n", testcount);
-
- struct pollfd fds[1];
- fds[0].fd = topic;
- fds[0].events = POLLIN;
-
- /* display and sound error */
- for (int i = 0; i < testcount; i++)
- {
- /* wait for topic */
- int ret = poll(&fds[0], 1, 2000);
-
- /* this would be bad... */
- if (ret < 0) {
- warnx("poll error %d", errno);
- usleep(1000000);
- continue;
- }
-
- /* do we have a topic update? */
- if (fds[0].revents & POLLIN) {
-
- /* copy object to disable poll ready state */
- if (vicon_msg) {
- struct vehicle_vicon_position_s vicon_position;
- orb_copy(ORB_ID(vehicle_vicon_position), topic, &vicon_position);
- } else if (command_msg) {
- struct vehicle_command_s vehicle_command;
- orb_copy(ORB_ID(vehicle_command), topic, &vehicle_command);
- }
-
- led_on(leds, LED_AMBER);
- ioctl(buzzer, TONE_SET_ALARM, 4);
- /* keep led on for 50 ms to make it barely visible */
- usleep(50000);
- led_off(leds, LED_AMBER);
- }
- }
-
- /* stop alarm */
- ioctl(buzzer, TONE_SET_ALARM, 0);
-
- /* switch on leds */
- led_on(leds, LED_BLUE);
- led_on(leds, LED_AMBER);
-
- exit(0);
-}
-
-static int led_off(int leds, int led)
-{
- return ioctl(leds, LED_OFF, led);
-}
-
-static int led_on(int leds, int led)
-{
- return ioctl(leds, LED_ON, led);
-}
\ No newline at end of file
diff --git a/apps/systemcmds/eeprom/Makefile b/apps/systemcmds/eeprom/Makefile
deleted file mode 100644
index 2f3db0fdce..0000000000
--- a/apps/systemcmds/eeprom/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Build the eeprom tool.
-#
-
-APPNAME = eeprom
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/perf/.context b/apps/systemcmds/perf/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/systemcmds/preflight_check/Makefile b/apps/systemcmds/preflight_check/Makefile
deleted file mode 100644
index f138e2640b..0000000000
--- a/apps/systemcmds/preflight_check/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Reboot command.
-#
-
-APPNAME = preflight_check
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/reboot/.context b/apps/systemcmds/reboot/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/systemcmds/reboot/Makefile b/apps/systemcmds/reboot/Makefile
deleted file mode 100644
index 9609a24fd0..0000000000
--- a/apps/systemcmds/reboot/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Reboot command.
-#
-
-APPNAME = reboot
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/systemcmds/top/.context b/apps/systemcmds/top/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/systemcmds/top/Makefile b/apps/systemcmds/top/Makefile
deleted file mode 100644
index c45775f4be..0000000000
--- a/apps/systemcmds/top/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# realtime system performance display
-#
-
-APPNAME = top
-PRIORITY = SCHED_PRIORITY_DEFAULT - 10
-STACKSIZE = 3000
-
-include $(APPDIR)/mk/app.mk
diff --git a/apps/uORB/.context b/apps/uORB/.context
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/apps/uORB/Makefile b/apps/uORB/Makefile
deleted file mode 100644
index 64ba52e9c5..0000000000
--- a/apps/uORB/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-############################################################################
-#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in
-# the documentation and/or other materials provided with the
-# distribution.
-# 3. Neither the name PX4 nor the names of its contributors may be
-# used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-#
-############################################################################
-
-#
-# Makefile to build uORB
-#
-
-APPNAME = uorb
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
diff --git a/makefiles/README.txt b/makefiles/README.txt
new file mode 100644
index 0000000000..8b84e4c40d
--- /dev/null
+++ b/makefiles/README.txt
@@ -0,0 +1,71 @@
+PX4 Build System
+================
+
+The files in this directory implement the PX4 runtime firmware build system
+and configuration for the standard PX4 boards and software, in conjunction
+with Makefile in the parent directory.
+
+../Makefile
+
+ Top-level makefile for the PX4 build system. This makefile supports
+ building NuttX archives, as well as supervising the building of all
+ of the defined PX4 firmware configurations.
+
+ Try 'make help' in the parent directory for documentation.
+
+firmware.mk
+
+ Manages the build for one specific firmware configuration.
+ See the comments at the top of this file for detailed documentation.
+
+ Builds modules, builtin command lists and the ROMFS (if configured).
+
+ This is the makefile directly used by external build systems; it can
+ be configured to compile modules both inside and outside the PX4
+ source tree. When used in this mode, at least BOARD, MODULES and
+ CONFIG_FILE must be set.
+
+module.mk
+
+ Called by firmware.mk to build individual modules.
+ See the comments at the top of this file for detailed documentation.
+
+ Not normally used other than by firmware.mk.
+
+nuttx.mk
+
+ Called by ../Makefile to build or download the NuttX archives.
+
+upload.mk
+
+ Called by ../Makefile to upload files to a target board. Can be used
+ by external build systems as well.
+
+setup.mk
+
+ Provides common path and tool definitions. Implements host system-specific
+ compatibility hacks.
+
+board_.mk
+
+ Board-specific configuration for . Typically sets CONFIG_ARCH
+ and then includes the toolchain definition for the board.
+
+config__.mk
+
+ Parameters for a specific configuration on a specific board.
+ The board name is derived from the filename. Sets MODULES to select
+ source modules to be included in the configuration, may also set
+ ROMFS_ROOT to build a ROMFS and BUILTIN_COMMANDS to include non-module
+ commands (e.g. from NuttX)
+
+toolchain_.mk
+
+ Provides macros used to compile and link source files.
+ Accepts EXTRADEFINES to add additional pre-processor symbol definitions,
+ EXTRACFLAGS, EXTRACXXFLAGS, EXTRAAFLAGS and EXTRALDFLAGS to pass
+ additional flags to the C compiler, C++ compiler, assembler and linker
+ respectively.
+
+ Defines the COMPILE, COMPILEXX, ASSEMBLE, PRELINK, ARCHIVE and LINK
+ macros that are used elsewhere in the build system.
diff --git a/makefiles/board_px4fmu.mk b/makefiles/board_px4fmu.mk
new file mode 100644
index 0000000000..8370696446
--- /dev/null
+++ b/makefiles/board_px4fmu.mk
@@ -0,0 +1,10 @@
+#
+# Board-specific definitions for the PX4FMU
+#
+
+#
+# Configure the toolchain
+#
+CONFIG_ARCH = CORTEXM4F
+
+include $(PX4_MK_DIR)/toolchain_gnu-arm-eabi.mk
diff --git a/makefiles/board_px4io.mk b/makefiles/board_px4io.mk
new file mode 100644
index 0000000000..b0eb2dae79
--- /dev/null
+++ b/makefiles/board_px4io.mk
@@ -0,0 +1,10 @@
+#
+# Board-specific definitions for the PX4IO
+#
+
+#
+# Configure the toolchain
+#
+CONFIG_ARCH = CORTEXM3
+
+include $(PX4_MK_DIR)/toolchain_gnu-arm-eabi.mk
diff --git a/makefiles/config_px4fmu_default.mk b/makefiles/config_px4fmu_default.mk
new file mode 100644
index 0000000000..ae62b70347
--- /dev/null
+++ b/makefiles/config_px4fmu_default.mk
@@ -0,0 +1,127 @@
+#
+# Makefile for the px4fmu_default configuration
+#
+
+#
+# Use the configuration's ROMFS.
+#
+ROMFS_ROOT = $(PX4_BASE)/ROMFS/px4fmu_common
+
+#
+# Board support modules
+#
+MODULES += drivers/device
+MODULES += drivers/stm32
+MODULES += drivers/stm32/adc
+MODULES += drivers/stm32/tone_alarm
+MODULES += drivers/led
+MODULES += drivers/px4io
+MODULES += drivers/px4fmu
+MODULES += drivers/boards/px4fmu
+MODULES += drivers/ardrone_interface
+MODULES += drivers/l3gd20
+MODULES += drivers/bma180
+MODULES += drivers/mpu6000
+MODULES += drivers/hmc5883
+MODULES += drivers/ms5611
+MODULES += drivers/mb12xx
+MODULES += drivers/gps
+MODULES += drivers/hil
+MODULES += drivers/hott_telemetry
+MODULES += drivers/blinkm
+MODULES += drivers/mkblctrl
+MODULES += drivers/md25
+MODULES += drivers/ets_airspeed
+MODULES += modules/sensors
+
+#
+# System commands
+#
+MODULES += systemcmds/eeprom
+MODULES += systemcmds/bl_update
+MODULES += systemcmds/boardinfo
+MODULES += systemcmds/i2c
+MODULES += systemcmds/mixer
+MODULES += systemcmds/param
+MODULES += systemcmds/perf
+MODULES += systemcmds/preflight_check
+MODULES += systemcmds/pwm
+MODULES += systemcmds/reboot
+MODULES += systemcmds/top
+MODULES += systemcmds/tests
+
+#
+# General system control
+#
+MODULES += modules/commander
+MODULES += modules/mavlink
+MODULES += modules/mavlink_onboard
+
+#
+# Estimation modules (EKF / other filters)
+#
+MODULES += modules/attitude_estimator_ekf
+MODULES += modules/position_estimator_mc
+MODULES += modules/position_estimator
+MODULES += modules/att_pos_estimator_ekf
+
+#
+# Vehicle Control
+#
+MODULES += modules/fixedwing_backside
+MODULES += modules/fixedwing_att_control
+MODULES += modules/fixedwing_pos_control
+MODULES += modules/multirotor_att_control
+MODULES += modules/multirotor_pos_control
+
+#
+# Logging
+#
+MODULES += modules/sdlog
+
+#
+# Libraries
+#
+MODULES += modules/systemlib
+MODULES += modules/systemlib/mixer
+MODULES += modules/mathlib
+MODULES += modules/mathlib/CMSIS
+MODULES += modules/controllib
+MODULES += modules/uORB
+
+#
+# Demo apps
+#
+#MODULES += examples/math_demo
+# Tutorial code from
+# https://pixhawk.ethz.ch/px4/dev/hello_sky
+#MODULES += examples/px4_simple_app
+
+# Tutorial code from
+# https://pixhawk.ethz.ch/px4/dev/daemon
+#MODULES += examples/px4_daemon_app
+
+# Tutorial code from
+# https://pixhawk.ethz.ch/px4/dev/debug_values
+#MODULES += examples/px4_mavlink_debug
+
+# Tutorial code from
+# https://pixhawk.ethz.ch/px4/dev/example_fixedwing_control
+MODULES += examples/fixedwing_control
+
+#
+# Transitional support - add commands from the NuttX export archive.
+#
+# In general, these should move to modules over time.
+#
+# Each entry here is ... but we use a helper macro
+# to make the table a bit more readable.
+#
+define _B
+ $(strip $1).$(or $(strip $2),SCHED_PRIORITY_DEFAULT).$(or $(strip $3),CONFIG_PTHREAD_STACK_DEFAULT).$(strip $4)
+endef
+
+# command priority stack entrypoint
+BUILTIN_COMMANDS := \
+ $(call _B, sercon, , 2048, sercon_main ) \
+ $(call _B, serdis, , 2048, serdis_main )
diff --git a/makefiles/config_px4io_default.mk b/makefiles/config_px4io_default.mk
new file mode 100644
index 0000000000..cf70391bcf
--- /dev/null
+++ b/makefiles/config_px4io_default.mk
@@ -0,0 +1,10 @@
+#
+# Makefile for the px4io_default configuration
+#
+
+#
+# Board support modules
+#
+MODULES += drivers/stm32
+MODULES += drivers/boards/px4io
+MODULES += modules/px4iofirmware
\ No newline at end of file
diff --git a/makefiles/firmware.mk b/makefiles/firmware.mk
new file mode 100644
index 0000000000..497e792376
--- /dev/null
+++ b/makefiles/firmware.mk
@@ -0,0 +1,450 @@
+#
+# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# Generic Makefile for PX4 firmware images.
+#
+# Requires:
+#
+# BOARD
+# Must be set to a board name known to the PX4 distribution (as
+# we need a corresponding NuttX export archive to link with).
+#
+# Optional:
+#
+# MODULES
+# Contains a list of module paths or path fragments used
+# to find modules. The names listed here are searched in
+# the following directories:
+#
+# $(MODULE_SEARCH_DIRS)
+# WORK_DIR
+# MODULE_SRC
+# PX4_MODULE_SRC
+#
+# Application directories are expected to contain a module.mk
+# file which provides build configuration for the module. See
+# makefiles/module.mk for more details.
+#
+# BUILTIN_COMMANDS
+# Contains a list of built-in commands not explicitly provided
+# by modules / libraries. Each entry in this list is formatted
+# as ...
+#
+# PX4_BASE:
+# Points to a PX4 distribution. Normally determined based on the
+# path to this file.
+#
+# CONFIG:
+# Used when searching for the configuration file, and available
+# to module Makefiles to select optional features.
+# If not set, CONFIG_FILE must be set and CONFIG will be derived
+# automatically from it.
+#
+# CONFIG_FILE:
+# If set, overrides the configuration file search logic. Sets
+# CONFIG to the name of the configuration file, strips any
+# leading config_ prefix and any suffix. e.g. config_board_foo.mk
+# results in CONFIG being set to 'board_foo'.
+#
+# WORK_DIR:
+# Sets the directory in which the firmware will be built. Defaults
+# to the directory 'build' under the directory containing the
+# parent Makefile.
+#
+# ROMFS_ROOT:
+# If set to the path to a directory, a ROMFS image will be generated
+# containing the files under the directory and linked into the final
+# image.
+#
+# MODULE_SEARCH_DIRS:
+# Extra directories to search first for MODULES before looking in the
+# usual places.
+#
+
+################################################################################
+# Paths and configuration
+################################################################################
+
+#
+# Work out where this file is, so we can find other makefiles in the
+# same directory.
+#
+# If PX4_BASE wasn't set previously, work out what it should be
+# and set it here now.
+#
+MK_DIR ?= $(dir $(lastword $(MAKEFILE_LIST)))
+ifeq ($(PX4_BASE),)
+export PX4_BASE := $(abspath $(MK_DIR)/..)
+endif
+$(info % PX4_BASE = $(PX4_BASE))
+ifneq ($(words $(PX4_BASE)),1)
+$(error Cannot build when the PX4_BASE path contains one or more space characters.)
+endif
+
+#
+# Set a default target so that included makefiles or errors here don't
+# cause confusion.
+#
+# XXX We could do something cute here with $(DEFAULT_GOAL) if it's not one
+# of the maintenance targets and set CONFIG based on it.
+#
+all: firmware
+
+#
+# Get path and tool config
+#
+include $(MK_DIR)/setup.mk
+
+#
+# Locate the configuration file
+#
+ifneq ($(CONFIG_FILE),)
+CONFIG := $(subst config_,,$(basename $(notdir $(CONFIG_FILE))))
+else
+CONFIG_FILE := $(wildcard $(PX4_MK_DIR)/config_$(CONFIG).mk)
+endif
+ifeq ($(CONFIG),)
+$(error Missing configuration name or file (specify with CONFIG=))
+endif
+export CONFIG
+include $(CONFIG_FILE)
+$(info % CONFIG = $(CONFIG))
+
+#
+# Sanity-check the BOARD variable and then get the board config.
+# If BOARD was not set by the configuration, extract it automatically.
+#
+# The board config in turn will fetch the toolchain configuration.
+#
+ifeq ($(BOARD),)
+BOARD := $(firstword $(subst _, ,$(CONFIG)))
+endif
+BOARD_FILE := $(wildcard $(PX4_MK_DIR)/board_$(BOARD).mk)
+ifeq ($(BOARD_FILE),)
+$(error Config $(CONFIG) references board $(BOARD), but no board definition file found)
+endif
+export BOARD
+include $(BOARD_FILE)
+$(info % BOARD = $(BOARD))
+
+#
+# If WORK_DIR is not set, create a 'build' directory next to the
+# parent Makefile.
+#
+PARENT_MAKEFILE := $(lastword $(filter-out $(lastword $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))
+ifeq ($(WORK_DIR),)
+export WORK_DIR := $(dir $(PARENT_MAKEFILE))build/
+endif
+$(info % WORK_DIR = $(WORK_DIR))
+
+#
+# Things that, if they change, might affect everything
+#
+GLOBAL_DEPS += $(MAKEFILE_LIST)
+
+#
+# Extra things we should clean
+#
+EXTRA_CLEANS =
+
+################################################################################
+# Modules
+################################################################################
+
+#
+# We don't actually know what a module is called; all we have is a path fragment
+# that we can search for, and where we expect to find a module.mk file.
+#
+# As such, we replicate the successfully-found path inside WORK_DIR for the
+# module's build products in order to keep modules separated from each other.
+#
+# XXX If this becomes unwieldy or breaks for other reasons, we will need to
+# move to allocating directory names and keeping tabs on makefiles via
+# the directory name. That will involve arithmetic (it'd probably be time
+# for GMSL).
+
+# where to look for modules
+MODULE_SEARCH_DIRS += $(WORK_DIR) $(MODULE_SRC) $(PX4_MODULE_SRC)
+
+# sort and unique the modules list
+MODULES := $(sort $(MODULES))
+
+# locate the first instance of a module by full path or by looking on the
+# module search path
+define MODULE_SEARCH
+ $(firstword $(abspath $(wildcard $(1)/module.mk)) \
+ $(abspath $(foreach search_dir,$(MODULE_SEARCH_DIRS),$(wildcard $(search_dir)/$(1)/module.mk))) \
+ MISSING_$1)
+endef
+
+# make a list of module makefiles and check that we found them all
+MODULE_MKFILES := $(foreach module,$(MODULES),$(call MODULE_SEARCH,$(module)))
+MISSING_MODULES := $(subst MISSING_,,$(filter MISSING_%,$(MODULE_MKFILES)))
+ifneq ($(MISSING_MODULES),)
+$(error Can't find module(s): $(MISSING_MODULES))
+endif
+
+# Make a list of the object files we expect to build from modules
+# Note that this path will typically contain a double-slash at the WORK_DIR boundary; this must be
+# preserved as it is used below to get the absolute path for the module.mk file correct.
+#
+MODULE_OBJS := $(foreach path,$(dir $(MODULE_MKFILES)),$(WORK_DIR)$(path)module.pre.o)
+
+# rules to build module objects
+.PHONY: $(MODULE_OBJS)
+$(MODULE_OBJS): relpath = $(patsubst $(WORK_DIR)%,%,$@)
+$(MODULE_OBJS): mkfile = $(patsubst %module.pre.o,%module.mk,$(relpath))
+$(MODULE_OBJS): workdir = $(@D)
+$(MODULE_OBJS): $(GLOBAL_DEPS) $(NUTTX_CONFIG_HEADER)
+ $(Q) $(MKDIR) -p $(workdir)
+ $(Q) $(MAKE) -r -f $(PX4_MK_DIR)module.mk \
+ -C $(workdir) \
+ MODULE_WORK_DIR=$(workdir) \
+ MODULE_OBJ=$@ \
+ MODULE_MK=$(mkfile) \
+ MODULE_NAME=$(lastword $(subst /, ,$(workdir))) \
+ module
+
+# make a list of phony clean targets for modules
+MODULE_CLEANS := $(foreach path,$(dir $(MODULE_MKFILES)),$(WORK_DIR)$(path)/clean)
+
+# rules to clean modules
+.PHONY: $(MODULE_CLEANS)
+$(MODULE_CLEANS): relpath = $(patsubst $(WORK_DIR)%,%,$@)
+$(MODULE_CLEANS): mkfile = $(patsubst %clean,%module.mk,$(relpath))
+$(MODULE_CLEANS):
+ @$(ECHO) %% cleaning using $(mkfile)
+ $(Q) $(MAKE) -r -f $(PX4_MK_DIR)module.mk \
+ MODULE_WORK_DIR=$(dir $@) \
+ MODULE_MK=$(mkfile) \
+ clean
+
+################################################################################
+# NuttX libraries and paths
+################################################################################
+
+include $(PX4_MK_DIR)/nuttx.mk
+
+################################################################################
+# ROMFS generation
+################################################################################
+
+ifneq ($(ROMFS_ROOT),)
+ifeq ($(wildcard $(ROMFS_ROOT)),)
+$(error ROMFS_ROOT specifies a directory that does not exist)
+endif
+
+#
+# Note that there is no support for more than one root directory or constructing
+# a root from several templates. That would be a nice feature.
+#
+
+# Add dependencies on anything in the ROMFS root
+ROMFS_FILES += $(wildcard \
+ $(ROMFS_ROOT)/* \
+ $(ROMFS_ROOT)/*/* \
+ $(ROMFS_ROOT)/*/*/* \
+ $(ROMFS_ROOT)/*/*/*/* \
+ $(ROMFS_ROOT)/*/*/*/*/* \
+ $(ROMFS_ROOT)/*/*/*/*/*/*)
+ifeq ($(ROMFS_FILES),)
+$(error ROMFS_ROOT $(ROMFS_ROOT) specifies a directory containing no files)
+endif
+ROMFS_DEPS += $(ROMFS_FILES)
+ROMFS_IMG = romfs.img
+ROMFS_CSRC = $(ROMFS_IMG:.img=.c)
+ROMFS_OBJ = $(ROMFS_CSRC:.c=.o)
+LIBS += $(ROMFS_OBJ)
+LINK_DEPS += $(ROMFS_OBJ)
+
+# Turn the ROMFS image into an object file
+$(ROMFS_OBJ): $(ROMFS_IMG) $(GLOBAL_DEPS)
+ $(call BIN_TO_OBJ,$<,$@,romfs_img)
+
+# Generate the ROMFS image from the root
+$(ROMFS_IMG): $(ROMFS_DEPS) $(GLOBAL_DEPS)
+ @$(ECHO) "ROMFS: $@"
+ $(Q) $(GENROMFS) -f $@ -d $(ROMFS_ROOT) -V "NSHInitVol"
+
+EXTRA_CLEANS += $(ROMGS_OBJ) $(ROMFS_IMG)
+
+endif
+
+################################################################################
+# Builtin command list generation
+################################################################################
+
+#
+# Builtin commands can be generated by the configuration, in which case they
+# must refer to commands that already exist, or indirectly generated by modules
+# when they are built.
+#
+# The configuration supplies builtin command information in the BUILTIN_COMMANDS
+# variable. Applications make empty files in $(WORK_DIR)/builtin_commands whose
+# filename contains the same information.
+#
+# In each case, the command information consists of four fields separated with a
+# period. These fields are the command's name, its thread priority, its stack size
+# and the name of the function to call when starting the thread.
+#
+BUILTIN_CSRC = $(WORK_DIR)builtin_commands.c
+
+# command definitions from modules (may be empty at Makefile parsing time...)
+MODULE_COMMANDS = $(subst COMMAND.,,$(notdir $(wildcard $(WORK_DIR)builtin_commands/COMMAND.*)))
+
+# We must have at least one pre-defined builtin command in order to generate
+# any of this.
+#
+ifneq ($(BUILTIN_COMMANDS),)
+
+# (BUILTIN_PROTO,,)
+define BUILTIN_PROTO
+ $(ECHO) 'extern int $(word 4,$1)(int argc, char *argv[]);' >> $2;
+endef
+
+# (BUILTIN_DEF,,)
+define BUILTIN_DEF
+ $(ECHO) ' {"$(word 1,$1)", $(word 2,$1), $(word 3,$1), $(word 4,$1)},' >> $2;
+endef
+
+# Don't generate until modules have updated their command files
+$(BUILTIN_CSRC): $(GLOBAL_DEPS) $(MODULE_OBJS) $(BUILTIN_COMMAND_FILES)
+ @$(ECHO) "CMDS: $@"
+ $(Q) $(ECHO) '/* builtin command list - automatically generated, do not edit */' > $@
+ $(Q) $(ECHO) '#include ' >> $@
+ $(Q) $(ECHO) '#include ' >> $@
+ $(Q) $(foreach spec,$(BUILTIN_COMMANDS),$(call BUILTIN_PROTO,$(subst ., ,$(spec)),$@))
+ $(Q) $(foreach spec,$(MODULE_COMMANDS),$(call BUILTIN_PROTO,$(subst ., ,$(spec)),$@))
+ $(Q) $(ECHO) 'const struct builtin_s g_builtins[] = {' >> $@
+ $(Q) $(foreach spec,$(BUILTIN_COMMANDS),$(call BUILTIN_DEF,$(subst ., ,$(spec)),$@))
+ $(Q) $(foreach spec,$(MODULE_COMMANDS),$(call BUILTIN_DEF,$(subst ., ,$(spec)),$@))
+ $(Q) $(ECHO) ' {NULL, 0, 0, NULL}' >> $@
+ $(Q) $(ECHO) '};' >> $@
+ $(Q) $(ECHO) 'const int g_builtin_count = $(words $(BUILTIN_COMMANDS) $(MODULE_COMMANDS));' >> $@
+
+SRCS += $(BUILTIN_CSRC)
+
+EXTRA_CLEANS += $(BUILTIN_CSRC)
+
+endif
+
+################################################################################
+# Default SRCS generation
+################################################################################
+
+#
+# If there are no SRCS, the build will fail; in that case, generate an empty
+# source file.
+#
+ifeq ($(SRCS),)
+EMPTY_SRC = $(WORK_DIR)empty.c
+$(EMPTY_SRC):
+ $(Q) $(ECHO) '/* this is an empty file */' > $@
+
+SRCS += $(EMPTY_SRC)
+endif
+
+################################################################################
+# Build rules
+################################################################################
+
+#
+# What we're going to build.
+#
+PRODUCT_BUNDLE = $(WORK_DIR)firmware.px4
+PRODUCT_BIN = $(WORK_DIR)firmware.bin
+PRODUCT_ELF = $(WORK_DIR)firmware.elf
+
+.PHONY: firmware
+firmware: $(PRODUCT_BUNDLE)
+
+#
+# Object files we will generate from sources
+#
+OBJS := $(foreach src,$(SRCS),$(WORK_DIR)$(src).o)
+
+#
+# SRCS -> OBJS rules
+#
+
+$(OBJS): $(GLOBAL_DEPS)
+
+$(filter %.c.o,$(OBJS)): $(WORK_DIR)%.c.o: %.c $(GLOBAL_DEPS)
+ $(call COMPILE,$<,$@)
+
+$(filter %.cpp.o,$(OBJS)): $(WORK_DIR)%.cpp.o: %.cpp $(GLOBAL_DEPS)
+ $(call COMPILEXX,$<,$@)
+
+$(filter %.S.o,$(OBJS)): $(WORK_DIR)%.S.o: %.S $(GLOBAL_DEPS)
+ $(call ASSEMBLE,$<,$@)
+
+#
+# Built product rules
+#
+
+$(PRODUCT_BUNDLE): $(PRODUCT_BIN)
+ @$(ECHO) %% Generating $@
+ $(Q) $(MKFW) --prototype $(IMAGE_DIR)/$(BOARD).prototype \
+ --git_identity $(PX4_BASE) \
+ --image $< > $@
+
+$(PRODUCT_BIN): $(PRODUCT_ELF)
+ $(call SYM_TO_BIN,$<,$@)
+
+$(PRODUCT_ELF): $(OBJS) $(MODULE_OBJS) $(GLOBAL_DEPS) $(LINK_DEPS) $(MODULE_MKFILES)
+ $(call LINK,$@,$(OBJS) $(MODULE_OBJS))
+
+#
+# Utility rules
+#
+
+.PHONY: upload
+upload: $(PRODUCT_BUNDLE) $(PRODUCT_BIN)
+ $(Q) $(MAKE) -f $(PX4_MK_DIR)/upload.mk \
+ METHOD=serial \
+ CONFIG=$(CONFIG) \
+ BOARD=$(BOARD) \
+ BUNDLE=$(PRODUCT_BUNDLE) \
+ BIN=$(PRODUCT_BIN)
+
+.PHONY: clean
+clean: $(MODULE_CLEANS)
+ @$(ECHO) %% cleaning
+ $(Q) $(REMOVE) $(PRODUCT_BUNDLE) $(PRODUCT_BIN) $(PRODUCT_ELF)
+ $(Q) $(REMOVE) $(OBJS) $(DEP_INCLUDES) $(EXTRA_CLEANS)
+ $(Q) $(RMDIR) $(NUTTX_EXPORT_DIR)
+
+
+#
+# DEP_INCLUDES is defined by the toolchain include in terms of $(OBJS)
+#
+-include $(DEP_INCLUDES)
diff --git a/makefiles/module.mk b/makefiles/module.mk
new file mode 100644
index 0000000000..db6f4e15ec
--- /dev/null
+++ b/makefiles/module.mk
@@ -0,0 +1,241 @@
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# Framework makefile for PX4 modules
+#
+# This makefile is invoked by firmware.mk to build each of the modules
+# that will subsequently be linked into the firmware image.
+#
+# Applications are built as prelinked objects with a limited set of exported
+# symbols, as the global namespace is shared between all modules. Normally an
+# module will just export one or more _main functions.
+#
+# IMPORTANT NOTE:
+#
+# This makefile assumes it is being invoked in the module's output directory.
+#
+
+#
+# Variables that can be set by the module's module.mk:
+#
+#
+# SRCS (required)
+#
+# Lists the .c, cpp and .S files that should be compiled/assembled to
+# produce the module.
+#
+# MODULE_COMMAND (optional)
+# MODULE_ENTRYPOINT (optional if MODULE_COMMAND is set)
+# MODULE_STACKSIZE (optional if MODULE_COMMAND is set)
+# MODULE_PRIORITY (optional if MODULE_COMMAND is set)
+#
+# Defines a single builtin command exported by the module.
+# MODULE_COMMAND must be unique for any configuration, but need not be the
+# same as the module directory name.
+#
+# If MODULE_ENTRYPOINT is set, it names the function (which must be exported)
+# that will be the entrypoint for the builtin command. It defaults to
+# $(MODULE_COMMAND)_main.
+#
+# If MODULE_STACKSIZE is set, it is the size in bytes of the stack to be
+# allocated for the builtin command. If it is not set, it defaults
+# to CONFIG_PTHREAD_STACK_DEFAULT.
+#
+# If MODULE_PRIORITY is set, it is the thread priority for the builtin
+# command. If it is not set, it defaults to SCHED_PRIORITY_DEFAULT.
+#
+# MODULE_COMMANDS (optional if MODULE_COMMAND is not set)
+#
+# Defines builtin commands exported by the module. Each word in
+# the list should be formatted as:
+# ...
+#
+# INCLUDE_DIRS (optional, must be appended)
+#
+# The list of directories searched for include files. If non-standard
+# includes (e.g. those from another module) are required, paths to search
+# can be added here.
+#
+# DEFAULT_VISIBILITY (optional)
+#
+# If not set, global symbols defined in a module will not be visible
+# outside the module. Symbols that should be globally visible must be
+# marked __EXPORT.
+# If set, global symbols defined in a module will be globally visible.
+#
+
+#
+# Variables visible to the module's module.mk:
+#
+# CONFIG
+# BOARD
+# MODULE_WORK_DIR
+# MODULE_OBJ
+# MODULE_MK
+# Anything set in setup.mk, board_$(BOARD).mk and the toolchain file.
+# Anything exported from config_$(CONFIG).mk
+#
+
+################################################################################
+# No user-serviceable parts below.
+################################################################################
+
+ifeq ($(MODULE_MK),)
+$(error No module makefile specified)
+endif
+$(info %% MODULE_MK = $(MODULE_MK))
+
+#
+# Get the board/toolchain config
+#
+include $(PX4_MK_DIR)/board_$(BOARD).mk
+
+#
+# Get the module's config
+#
+include $(MODULE_MK)
+MODULE_SRC := $(dir $(MODULE_MK))
+$(info % MODULE_NAME = $(MODULE_NAME))
+$(info % MODULE_SRC = $(MODULE_SRC))
+$(info % MODULE_OBJ = $(MODULE_OBJ))
+$(info % MODULE_WORK_DIR = $(MODULE_WORK_DIR))
+
+#
+# Things that, if they change, might affect everything
+#
+GLOBAL_DEPS += $(MAKEFILE_LIST)
+
+################################################################################
+# Builtin command definitions
+################################################################################
+
+ifneq ($(MODULE_COMMAND),)
+MODULE_ENTRYPOINT ?= $(MODULE_COMMAND)_main
+MODULE_STACKSIZE ?= CONFIG_PTHREAD_STACK_DEFAULT
+MODULE_PRIORITY ?= SCHED_PRIORITY_DEFAULT
+MODULE_COMMANDS += $(MODULE_COMMAND).$(MODULE_PRIORITY).$(MODULE_STACKSIZE).$(MODULE_ENTRYPOINT)
+endif
+
+ifneq ($(MODULE_COMMANDS),)
+MODULE_COMMAND_FILES := $(addprefix $(WORK_DIR)/builtin_commands/COMMAND.,$(MODULE_COMMANDS))
+
+# Create the command files
+# Ensure that there is only one entry for each command
+#
+.PHONY: $(MODULE_COMMAND_FILES)
+$(MODULE_COMMAND_FILES): command = $(word 2,$(subst ., ,$(notdir $(@))))
+$(MODULE_COMMAND_FILES): exclude = $(dir $@)COMMAND.$(command).*
+$(MODULE_COMMAND_FILES): $(GLOBAL_DEPS)
+ @$(REMOVE) -f $(exclude)
+ @$(MKDIR) -p $(dir $@)
+ @$(ECHO) "CMD: $(command)"
+ $(Q) $(TOUCH) $@
+endif
+
+################################################################################
+# Adjust compilation flags to implement EXPORT
+################################################################################
+
+ifeq ($(DEFAULT_VISIBILITY),)
+DEFAULT_VISIBILITY = hidden
+else
+DEFAULT_VISIBILITY = default
+endif
+
+CFLAGS += -fvisibility=$(DEFAULT_VISIBILITY) -include $(PX4_INCLUDE_DIR)visibility.h
+CXXFLAGS += -fvisibility=$(DEFAULT_VISIBILITY) -include $(PX4_INCLUDE_DIR)visibility.h
+
+################################################################################
+# Build rules
+################################################################################
+
+#
+# What we're going to build
+#
+module: $(MODULE_OBJ) $(MODULE_COMMAND_FILES)
+
+##
+## Locate sources (allows relative source paths in module.mk)
+##
+#define SRC_SEARCH
+# $(abspath $(firstword $(wildcard $1) $(wildcard $(MODULE_SRC)/$1) MISSING_$1))
+#endef
+#
+#ABS_SRCS ?= $(foreach src,$(SRCS),$(call SRC_SEARCH,$(src)))
+#MISSING_SRCS := $(subst MISSING_,,$(filter MISSING_%,$(ABS_SRCS)))
+#ifneq ($(MISSING_SRCS),)
+#$(error $(MODULE_MK): missing in SRCS: $(MISSING_SRCS))
+#endif
+#ifeq ($(ABS_SRCS),)
+#$(error $(MODULE_MK): nothing to compile in SRCS)
+#endif
+#
+##
+## Object files we will generate from sources
+##
+#OBJS := $(foreach src,$(ABS_SRCS),$(MODULE_WORK_DIR)$(src).o)
+
+OBJS = $(addsuffix .o,$(SRCS))
+$(info SRCS $(SRCS))
+$(info OBJS $(OBJS))
+
+#
+# SRCS -> OBJS rules
+#
+
+$(OBJS): $(GLOBAL_DEPS)
+
+vpath %.c $(MODULE_SRC)
+$(filter %.c.o,$(OBJS)): %.c.o: %.c $(GLOBAL_DEPS)
+ $(call COMPILE,$<,$@)
+
+vpath %.cpp $(MODULE_SRC)
+$(filter %.cpp.o,$(OBJS)): %.cpp.o: %.cpp $(GLOBAL_DEPS)
+ $(call COMPILEXX,$<,$@)
+
+vpath %.S $(MODULE_SRC)
+$(filter %.S.o,$(OBJS)): %.S.o: %.S $(GLOBAL_DEPS)
+ $(call ASSEMBLE,$<,$@)
+
+#
+# Built product rules
+#
+
+$(MODULE_OBJ): $(OBJS) $(GLOBAL_DEPS)
+ $(call PRELINK,$@,$(OBJS))
+
+#
+# Utility rules
+#
+
+clean:
+ $(Q) $(REMOVE) $(MODULE_PRELINK) $(OBJS)
diff --git a/apps/px4io/Makefile b/makefiles/nuttx.mk
similarity index 52%
rename from apps/px4io/Makefile
rename to makefiles/nuttx.mk
index 0eb3ffcf7a..346735a02a 100644
--- a/apps/px4io/Makefile
+++ b/makefiles/nuttx.mk
@@ -1,4 +1,3 @@
-############################################################################
#
# Copyright (C) 2012 PX4 Development Team. All rights reserved.
#
@@ -29,30 +28,51 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
-############################################################################
#
-# Build the px4io application.
+# Rules and definitions related to handling the NuttX export archives when
+# building firmware.
#
#
-# Note that we pull a couple of specific files from the systemlib, since
-# we can't support it all.
+# Check that the NuttX archive for the selected board is available.
#
-CSRCS = adc.c \
- controls.c \
- dsm.c \
- i2c.c \
- px4io.c \
- registers.c \
- safety.c \
- sbus.c \
- ../systemlib/hx_stream.c \
- ../systemlib/perf_counter.c \
- ../systemlib/up_cxxinitialize.c
+NUTTX_ARCHIVE := $(wildcard $(ARCHIVE_DIR)$(BOARD).export)
+ifeq ($(NUTTX_ARCHIVE),)
+$(error The NuttX export archive for $(BOARD) is missing from $(ARCHIVE_DIR) - try 'make archives' in $(PX4_BASE))
+endif
-CXXSRCS = mixer.cpp
+#
+# The NuttX config header should always be present in the NuttX archive, and
+# if it changes, everything should be rebuilt. So, use it as the trigger to
+# unpack the NuttX archive.
+#
+NUTTX_EXPORT_DIR = $(WORK_DIR)nuttx-export/
+NUTTX_CONFIG_HEADER = $(NUTTX_EXPORT_DIR)include/nuttx/config.h
+$(info % NUTTX_EXPORT_DIR = $(NUTTX_EXPORT_DIR))
+$(info % NUTTX_CONFIG_HEADER = $(NUTTX_CONFIG_HEADER))
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
-include $(APPDIR)/mk/app.mk
+GLOBAL_DEPS += $(NUTTX_CONFIG_HEADER)
+
+#
+# Use the linker script from the NuttX export
+#
+LDSCRIPT += $(NUTTX_EXPORT_DIR)build/ld.script
+
+#
+# Add directories from the NuttX export to the relevant search paths
+#
+INCLUDE_DIRS += $(NUTTX_EXPORT_DIR)include \
+ $(NUTTX_EXPORT_DIR)arch/chip \
+ $(NUTTX_EXPORT_DIR)arch/common
+
+LIB_DIRS += $(NUTTX_EXPORT_DIR)libs
+LIBS += -lapps -lnuttx
+LINK_DEPS += $(NUTTX_EXPORT_DIR)libs/libapps.a \
+ $(NUTTX_EXPORT_DIR)libs/libnuttx.a
+
+$(NUTTX_CONFIG_HEADER): $(NUTTX_ARCHIVE)
+ @$(ECHO) %% Unpacking $(NUTTX_ARCHIVE)
+ $(Q) $(UNZIP_CMD) -q -o -d $(WORK_DIR) $(NUTTX_ARCHIVE)
+ $(Q) $(TOUCH) $@
diff --git a/makefiles/setup.mk b/makefiles/setup.mk
new file mode 100644
index 0000000000..1111930937
--- /dev/null
+++ b/makefiles/setup.mk
@@ -0,0 +1,91 @@
+#
+# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# Path and tool setup
+#
+
+#
+# Some useful paths.
+#
+# Note that in general we always keep directory paths with the separator
+# at the end, and join paths without explicit separators. This reduces
+# the number of duplicate slashes we have lying around in paths,
+# and is consistent with joining the results of $(dir) and $(notdir).
+#
+export PX4_INCLUDE_DIR = $(abspath $(PX4_BASE)/src/include)/
+export PX4_MODULE_SRC = $(abspath $(PX4_BASE)/src)/
+export PX4_MK_DIR = $(abspath $(PX4_BASE)/makefiles)/
+export NUTTX_SRC = $(abspath $(PX4_BASE)/nuttx)/
+export NUTTX_APP_SRC = $(abspath $(PX4_BASE)/apps)/
+export MAVLINK_SRC = $(abspath $(PX4_BASE)/mavlink)/
+export ROMFS_SRC = $(abspath $(PX4_BASE)/ROMFS)/
+export IMAGE_DIR = $(abspath $(PX4_BASE)/Images)/
+export BUILD_DIR = $(abspath $(PX4_BASE)/Build)/
+export ARCHIVE_DIR = $(abspath $(PX4_BASE)/Archives)/
+
+#
+# Default include paths
+#
+export INCLUDE_DIRS := $(PX4_MODULE_SRC) \
+ $(PX4_MODULE_SRC)/modules/ \
+ $(PX4_INCLUDE_DIR)
+
+#
+# Tools
+#
+export MKFW = $(PX4_BASE)/Tools/px_mkfw.py
+export UPLOADER = $(PX4_BASE)/Tools/px_uploader.py
+export COPY = cp
+export REMOVE = rm -f
+export RMDIR = rm -rf
+export GENROMFS = genromfs
+export TOUCH = touch
+export MKDIR = mkdir
+export ECHO = echo
+export UNZIP_CMD = unzip
+export PYTHON = python
+export OPENOCD = openocd
+
+#
+# Host-specific paths, hacks and fixups
+#
+export SYSTYPE := $(shell uname -s)
+
+ifeq ($(SYSTYPE),Darwin)
+# Eclipse may not have the toolchain on its path.
+export PATH := $(PATH):/usr/local/bin
+endif
+
+#
+# Makefile debugging.
+#
+export Q := $(if $(V),,@)
diff --git a/makefiles/toolchain_gnu-arm-eabi.mk b/makefiles/toolchain_gnu-arm-eabi.mk
new file mode 100644
index 0000000000..874e7154c7
--- /dev/null
+++ b/makefiles/toolchain_gnu-arm-eabi.mk
@@ -0,0 +1,285 @@
+#
+# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# Definitions for a generic GNU ARM-EABI toolchain
+#
+
+#$(info TOOLCHAIN gnu-arm-eabi)
+
+# Toolchain commands. Normally only used inside this file.
+#
+CROSSDEV = arm-none-eabi-
+
+CC = $(CROSSDEV)gcc
+CXX = $(CROSSDEV)g++
+CPP = $(CROSSDEV)gcc -E
+LD = $(CROSSDEV)ld
+AR = $(CROSSDEV)ar rcs
+NM = $(CROSSDEV)nm
+OBJCOPY = $(CROSSDEV)objcopy
+OBJDUMP = $(CROSSDEV)objdump
+
+# XXX this is pulled pretty directly from the fmu Make.defs - needs cleanup
+
+MAXOPTIMIZATION = -O3
+
+# Base CPU flags for each of the supported architectures.
+#
+ARCHCPUFLAGS_CORTEXM4F = -mcpu=cortex-m4 \
+ -mthumb \
+ -march=armv7e-m \
+ -mfpu=fpv4-sp-d16 \
+ -mfloat-abi=hard
+
+ARCHCPUFLAGS_CORTEXM4 = -mcpu=cortex-m4 \
+ -mthumb \
+ -march=armv7e-m \
+ -mfloat-abi=soft
+
+ARCHCPUFLAGS_CORTEXM3 = -mcpu=cortex-m3 \
+ -mthumb \
+ -march=armv7-m \
+ -mfloat-abi=soft
+
+# Pick the right set of flags for the architecture.
+#
+ARCHCPUFLAGS = $(ARCHCPUFLAGS_$(CONFIG_ARCH))
+ifeq ($(ARCHCPUFLAGS),)
+$(error Must set CONFIG_ARCH to one of CORTEXM4F, CORTEXM4 or CORTEXM3)
+endif
+
+# optimisation flags
+#
+ARCHOPTIMIZATION = $(MAXOPTIMIZATION) \
+ -g \
+ -fno-strict-aliasing \
+ -fno-strength-reduce \
+ -fomit-frame-pointer \
+ -funsafe-math-optimizations \
+ -fno-builtin-printf \
+ -ffunction-sections \
+ -fdata-sections
+
+# enable precise stack overflow tracking
+# note - requires corresponding support in NuttX
+INSTRUMENTATIONDEFINES = -finstrument-functions \
+ -ffixed-r10
+# Language-specific flags
+#
+ARCHCFLAGS = -std=gnu99
+ARCHCXXFLAGS = -fno-exceptions -fno-rtti -std=gnu++0x
+
+# Generic warnings
+#
+ARCHWARNINGS = -Wall \
+ -Wextra \
+ -Wdouble-promotion \
+ -Wshadow \
+ -Wfloat-equal \
+ -Wframe-larger-than=1024 \
+ -Wpointer-arith \
+ -Wlogical-op \
+ -Wmissing-declarations \
+ -Wpacked \
+ -Wno-unused-parameter
+# -Wcast-qual - generates spurious noreturn attribute warnings, try again later
+# -Wconversion - would be nice, but too many "risky-but-safe" conversions in the code
+# -Wcast-align - would help catch bad casts in some cases, but generates too many false positives
+
+# C-specific warnings
+#
+ARCHCWARNINGS = $(ARCHWARNINGS) \
+ -Wbad-function-cast \
+ -Wstrict-prototypes \
+ -Wold-style-declaration \
+ -Wmissing-parameter-type \
+ -Wmissing-prototypes \
+ -Wnested-externs \
+ -Wunsuffixed-float-constants
+
+# C++-specific warnings
+#
+ARCHWARNINGSXX = $(ARCHWARNINGS)
+
+# pull in *just* libm from the toolchain ... this is grody
+LIBM := $(shell $(CC) $(ARCHCPUFLAGS) -print-file-name=libm.a)
+EXTRA_LIBS += $(LIBM)
+
+# Flags we pass to the C compiler
+#
+CFLAGS = $(ARCHCFLAGS) \
+ $(ARCHCWARNINGS) \
+ $(ARCHOPTIMIZATION) \
+ $(ARCHCPUFLAGS) \
+ $(ARCHINCLUDES) \
+ $(INSTRUMENTATIONDEFINES) \
+ $(ARCHDEFINES) \
+ $(EXTRADEFINES) \
+ $(EXTRACFLAGS) \
+ -fno-common \
+ $(addprefix -I,$(INCLUDE_DIRS))
+
+# Flags we pass to the C++ compiler
+#
+CXXFLAGS = $(ARCHCXXFLAGS) \
+ $(ARCHWARNINGSXX) \
+ $(ARCHOPTIMIZATION) \
+ $(ARCHCPUFLAGS) \
+ $(ARCHXXINCLUDES) \
+ $(INSTRUMENTATIONDEFINES) \
+ $(ARCHDEFINES) \
+ -DCONFIG_WCHAR_BUILTIN \
+ $(EXTRADEFINES) \
+ $(EXTRACXXFLAGS) \
+ $(addprefix -I,$(INCLUDE_DIRS))
+
+# Flags we pass to the assembler
+#
+AFLAGS = $(CFLAGS) -D__ASSEMBLY__ \
+ $(EXTRADEFINES) \
+ $(EXTRAAFLAGS)
+
+# Flags we pass to the linker
+#
+LDFLAGS += --warn-common \
+ --gc-sections \
+ $(EXTRALDFLAGS) \
+ $(addprefix -T,$(LDSCRIPT)) \
+ $(addprefix -L,$(LIB_DIRS))
+
+# Compiler support library
+#
+LIBGCC := $(shell $(CC) $(ARCHCPUFLAGS) -print-libgcc-file-name)
+
+# Files that the final link depends on
+#
+LINK_DEPS += $(LDSCRIPT)
+
+# Files to include to get automated dependencies
+#
+DEP_INCLUDES = $(subst .o,.d,$(OBJS))
+
+# Compile C source $1 to object $2
+# as a side-effect, generate a dependency file
+#
+define COMPILE
+ @$(ECHO) "CC: $1"
+ @$(MKDIR) -p $(dir $2)
+ $(Q) $(CC) -MD -c $(CFLAGS) $(abspath $1) -o $2
+endef
+
+# Compile C++ source $1 to $2
+# as a side-effect, generate a dependency file
+#
+define COMPILEXX
+ @$(ECHO) "CXX: $1"
+ @$(MKDIR) -p $(dir $2)
+ $(Q) $(CXX) -MD -c $(CXXFLAGS) $(abspath $1) -o $2
+endef
+
+# Assemble $1 into $2
+#
+define ASSEMBLE
+ @$(ECHO) "AS: $1"
+ @$(MKDIR) -p $(dir $2)
+ $(Q) $(CC) -c $(AFLAGS) $(abspath $1) -o $2
+endef
+
+# Produce partially-linked $1 from files in $2
+#
+define PRELINK
+ @$(ECHO) "PRELINK: $1"
+ @$(MKDIR) -p $(dir $1)
+ $(Q) $(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1
+endef
+
+# Update the archive $1 with the files in $2
+#
+define ARCHIVE
+ @$(ECHO) "AR: $2"
+ @$(MKDIR) -p $(dir $1)
+ $(Q) $(AR) $1 $2
+endef
+
+# Link the objects in $2 into the binary $1
+#
+define LINK
+ @$(ECHO) "LINK: $1"
+ @$(MKDIR) -p $(dir $1)
+ $(Q) $(LD) $(LDFLAGS) -o $1 --start-group $2 $(LIBS) $(EXTRA_LIBS) $(LIBGCC) --end-group
+endef
+
+# Convert $1 from a linked object to a raw binary in $2
+#
+define SYM_TO_BIN
+ @$(ECHO) "BIN: $2"
+ @$(MKDIR) -p $(dir $2)
+ $(Q) $(OBJCOPY) -O binary $1 $2
+endef
+
+# Take the raw binary $1 and make it into an object file $2.
+# The symbol $3 points to the beginning of the file, and $3_len
+# gives its length.
+#
+# - compile an empty file to generate a suitable object file
+# - relink the object and insert the binary file
+# - edit symbol names to suit
+#
+# NOTE: exercise caution using this with absolute pathnames; it looks
+# like the MinGW tools insert an extra _ in the binary symbol name; e.g.
+# the path:
+#
+# /d/px4/firmware/Build/px4fmu_default.build/romfs.img
+#
+# is assigned symbols like:
+#
+# _binary_d__px4_firmware_Build_px4fmu_default_build_romfs_img_size
+#
+# when we would expect
+#
+# _binary__d_px4_firmware_Build_px4fmu_default_build_romfs_img_size
+#
+define BIN_SYM_PREFIX
+ _binary_$(subst /,_,$(subst .,_,$1))
+endef
+define BIN_TO_OBJ
+ @$(ECHO) "OBJ: $2"
+ @$(MKDIR) -p $(dir $2)
+ $(Q) $(ECHO) > $2.c
+ $(call COMPILE,$2.c,$2.c.o)
+ $(Q) $(LD) -r -o $2 $2.c.o -b binary $1
+ $(Q) $(OBJCOPY) $2 \
+ --redefine-sym $(call BIN_SYM_PREFIX,$1)_start=$3 \
+ --redefine-sym $(call BIN_SYM_PREFIX,$1)_size=$3_len \
+ --strip-symbol $(call BIN_SYM_PREFIX,$1)_end
+ $(Q) $(REMOVE) $2.c $2.c.o
+endef
diff --git a/makefiles/upload.mk b/makefiles/upload.mk
new file mode 100644
index 0000000000..5ef92728fe
--- /dev/null
+++ b/makefiles/upload.mk
@@ -0,0 +1,44 @@
+#
+# Rules and tools for uploading firmware to various PX4 boards.
+#
+
+UPLOADER = $(PX4_BASE)/Tools/px_uploader.py
+
+SYSTYPE := $(shell uname -s)
+
+#
+# Serial port defaults.
+#
+# XXX The uploader should be smarter than this.
+#
+ifeq ($(SYSTYPE),Darwin)
+SERIAL_PORTS ?= "/dev/tty.usbmodemPX1,/dev/tty.usbmodemPX2,/dev/tty.usbmodemPX3,/dev/tty.usbmodemPX4,/dev/tty.usbmodem1,/dev/tty.usbmodem2,/dev/tty.usbmodem3,/dev/tty.usbmodem4"
+endif
+ifeq ($(SYSTYPE),Linux)
+SERIAL_PORTS ?= "/dev/ttyACM5,/dev/ttyACM4,/dev/ttyACM3,/dev/ttyACM2,/dev/ttyACM1,/dev/ttyACM0"
+endif
+ifeq ($(SERIAL_PORTS),)
+SERIAL_PORTS = "\\\\.\\COM32,\\\\.\\COM31,\\\\.\\COM30,\\\\.\\COM29,\\\\.\\COM28,\\\\.\\COM27,\\\\.\\COM26,\\\\.\\COM25,\\\\.\\COM24,\\\\.\\COM23,\\\\.\\COM22,\\\\.\\COM21,\\\\.\\COM20,\\\\.\\COM19,\\\\.\\COM18,\\\\.\\COM17,\\\\.\\COM16,\\\\.\\COM15,\\\\.\\COM14,\\\\.\\COM13,\\\\.\\COM12,\\\\.\\COM11,\\\\.\\COM10,\\\\.\\COM9,\\\\.\\COM8,\\\\.\\COM7,\\\\.\\COM6,\\\\.\\COM5,\\\\.\\COM4,\\\\.\\COM3,\\\\.\\COM2,\\\\.\\COM1,\\\\.\\COM0"
+endif
+
+.PHONY: all upload-$(METHOD)-$(BOARD)
+all: upload-$(METHOD)-$(BOARD)
+
+upload-serial-px4fmu: $(BUNDLE) $(UPLOADER)
+ $(Q) $(PYTHON) -u $(UPLOADER) --port $(SERIAL_PORTS) $(BUNDLE)
+
+upload-serial-px4fmuv2: $(BUNDLE) $(UPLOADER)
+ $(Q) $(PYTHON) -u $(UPLOADER) --port $(SERIAL_PORTS) $(BUNDLE)
+
+#
+# JTAG firmware uploading with OpenOCD
+#
+JTAGCONFIG ?= interface/olimex-jtag-tiny.cfg
+
+upload-jtag-px4fmu: all
+ @$(ECHO) Attempting to flash PX4FMU board via JTAG
+ $(Q) $(OPENOCD) -f $(JTAGCONFIG) -f ../Bootloader/stm32f4x.cfg -c init -c "reset halt" -c "flash write_image erase nuttx/nuttx" -c "flash write_image erase ../Bootloader/px4fmu_bl.elf" -c "reset run" -c shutdown
+
+upload-jtag-px4io: all
+ @$(ECHO) Attempting to flash PX4IO board via JTAG
+ $(Q) $(OPENOCD) -f $(JTAGCONFIG) -f ../Bootloader/stm32f1x.cfg -c init -c "reset halt" -c "flash write_image erase nuttx/nuttx" -c "flash write_image erase ../Bootloader/px4io_bl.elf" -c "reset run" -c shutdown
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
index 2c9ae4cacb..0fcd463e05 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
@@ -1512,7 +1512,6 @@ static inline void stm32_ep0out_receive(FAR struct stm32_ep_s *privep, int bcnt)
DEBUGASSERT(privep && privep->ep.priv);
priv = (FAR struct stm32_usbdev_s *)privep->ep.priv;
- DEBUGASSERT(priv->ep0state == EP0STATE_SETUP_OUT);
ullvdbg("EP0: bcnt=%d\n", bcnt);
usbtrace(TRACE_READ(EP0), bcnt);
diff --git a/nuttx/configs/px4fmu/include/board.h b/nuttx/configs/px4fmu/include/board.h
index 8ad56a4c6a..294b6c3984 100755
--- a/nuttx/configs/px4fmu/include/board.h
+++ b/nuttx/configs/px4fmu/include/board.h
@@ -308,6 +308,10 @@
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
+#define GPIO_SPI2_MISO GPIO_SPI2_MISO_2
+#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_2
+#define GPIO_SPI2_SCK GPIO_SPI2_SCK_2
+
#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2
#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_1
#define GPIO_SPI3_SCK GPIO_SPI3_SCK_2
@@ -321,11 +325,14 @@
#define PX4_SPIDEV_ACCEL 2
#define PX4_SPIDEV_MPU 3
+#define PX4_SPIDEV_ACCEL_MAG 2 // external for anti vibration test
+
/*
* Tone alarm output
*/
#define TONE_ALARM_TIMER 3 /* timer 3 */
#define TONE_ALARM_CHANNEL 3 /* channel 3 */
+#define GPIO_TONE_ALARM_IDLE (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_2MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN8)
#define GPIO_TONE_ALARM (GPIO_ALT|GPIO_AF2|GPIO_SPEED_2MHz|GPIO_FLOAT|GPIO_PUSHPULL|GPIO_PORTC|GPIO_PIN8)
/************************************************************************************
diff --git a/nuttx/configs/px4fmu/include/nsh_romfsimg.h b/nuttx/configs/px4fmu/include/nsh_romfsimg.h
new file mode 100644
index 0000000000..15e4e7a8d5
--- /dev/null
+++ b/nuttx/configs/px4fmu/include/nsh_romfsimg.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * nsh_romfsetc.h
+ *
+ * This file is a stub for 'make export' purposes; the actual ROMFS
+ * must be supplied by the library client.
+ */
+
+extern unsigned char romfs_img[];
+extern unsigned int romfs_img_len;
diff --git a/nuttx/configs/px4fmu/nsh/appconfig b/nuttx/configs/px4fmu/nsh/appconfig
index 80cf6f312c..0e18aa8ef1 100644
--- a/nuttx/configs/px4fmu/nsh/appconfig
+++ b/nuttx/configs/px4fmu/nsh/appconfig
@@ -41,97 +41,6 @@ CONFIGURED_APPS += examples/nsh
CONFIGURED_APPS += nshlib
CONFIGURED_APPS += system/readline
-# System library - utility functions
-CONFIGURED_APPS += systemlib
-CONFIGURED_APPS += systemlib/mixer
-
-# Math library
-ifneq ($(CONFIG_APM),y)
-CONFIGURED_APPS += mathlib
-CONFIGURED_APPS += mathlib/CMSIS
-CONFIGURED_APPS += examples/math_demo
-endif
-
-# Control library
-ifneq ($(CONFIG_APM),y)
-CONFIGURED_APPS += controllib
-CONFIGURED_APPS += examples/control_demo
-CONFIGURED_APPS += examples/kalman_demo
-endif
-
-# System utility commands
-CONFIGURED_APPS += systemcmds/reboot
-CONFIGURED_APPS += systemcmds/perf
-CONFIGURED_APPS += systemcmds/top
-CONFIGURED_APPS += systemcmds/boardinfo
-CONFIGURED_APPS += systemcmds/mixer
-CONFIGURED_APPS += systemcmds/eeprom
-CONFIGURED_APPS += systemcmds/param
-CONFIGURED_APPS += systemcmds/pwm
-CONFIGURED_APPS += systemcmds/bl_update
-CONFIGURED_APPS += systemcmds/preflight_check
-CONFIGURED_APPS += systemcmds/delay_test
-
-# Tutorial code from
-# https://pixhawk.ethz.ch/px4/dev/hello_sky
-# CONFIGURED_APPS += examples/px4_simple_app
-
-# Tutorial code from
-# https://pixhawk.ethz.ch/px4/dev/deamon
-# CONFIGURED_APPS += examples/px4_deamon_app
-
-# Tutorial code from
-# https://pixhawk.ethz.ch/px4/dev/debug_values
-# CONFIGURED_APPS += examples/px4_mavlink_debug
-
-# Shared object broker; required by many parts of the system.
-CONFIGURED_APPS += uORB
-
-CONFIGURED_APPS += mavlink
-CONFIGURED_APPS += mavlink_onboard
-CONFIGURED_APPS += commander
-CONFIGURED_APPS += sdlog
-CONFIGURED_APPS += sensors
-
-ifneq ($(CONFIG_APM),y)
-CONFIGURED_APPS += ardrone_interface
-CONFIGURED_APPS += multirotor_att_control
-CONFIGURED_APPS += multirotor_pos_control
-#CONFIGURED_APPS += fixedwing_control
-CONFIGURED_APPS += fixedwing_att_control
-CONFIGURED_APPS += fixedwing_pos_control
-CONFIGURED_APPS += position_estimator
-CONFIGURED_APPS += attitude_estimator_ekf
-CONFIGURED_APPS += hott_telemetry
-endif
-
-# Hacking tools
-#CONFIGURED_APPS += system/i2c
-CONFIGURED_APPS += systemcmds/i2c
-
-# Communication and Drivers
-CONFIGURED_APPS += drivers/boards/px4fmu
-CONFIGURED_APPS += drivers/device
-CONFIGURED_APPS += drivers/ms5611
-CONFIGURED_APPS += drivers/hmc5883
-CONFIGURED_APPS += drivers/mpu6000
-CONFIGURED_APPS += drivers/bma180
-CONFIGURED_APPS += drivers/l3gd20
-CONFIGURED_APPS += drivers/px4io
-CONFIGURED_APPS += drivers/stm32
-CONFIGURED_APPS += drivers/led
-CONFIGURED_APPS += drivers/blinkm
-CONFIGURED_APPS += drivers/stm32/tone_alarm
-CONFIGURED_APPS += drivers/stm32/adc
-CONFIGURED_APPS += drivers/px4fmu
-CONFIGURED_APPS += drivers/hil
-CONFIGURED_APPS += drivers/gps
-CONFIGURED_APPS += drivers/mb12xx
-
-# Testing stuff
-CONFIGURED_APPS += px4/sensors_bringup
-CONFIGURED_APPS += px4/tests
-
ifeq ($(CONFIG_CAN),y)
#CONFIGURED_APPS += examples/can
endif
diff --git a/nuttx/configs/px4fmu/nsh/defconfig b/nuttx/configs/px4fmu/nsh/defconfig
index 130886aac2..02e2243020 100755
--- a/nuttx/configs/px4fmu/nsh/defconfig
+++ b/nuttx/configs/px4fmu/nsh/defconfig
@@ -85,7 +85,7 @@ CONFIG_ARCH_FPU=y
CONFIG_ARCH_INTERRUPTSTACK=n
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_BOOTLOADER=n
-CONFIG_ARCH_LEDS=y
+CONFIG_ARCH_LEDS=n
CONFIG_ARCH_BUTTONS=n
CONFIG_ARCH_CALIBRATION=n
CONFIG_ARCH_DMA=y
@@ -647,10 +647,14 @@ CONFIG_DISABLE_POLL=n
# CONFIG_LIBC_FIXEDPRECISION - Sets 7 digits after dot for printing:
# 5.1234567
# CONFIG_HAVE_LONG_LONG - Enabled printf("%llu)
+# CONFIG_LIBC_STRERR - allow printing of error text
+# CONFIG_LIBC_STRERR_SHORT - allow printing of short error text
#
CONFIG_NOPRINTF_FIELDWIDTH=n
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_HAVE_LONG_LONG=y
+CONFIG_LIBC_STRERROR=n
+CONFIG_LIBC_STRERROR_SHORT=n
#
# Allow for architecture optimized implementations
diff --git a/nuttx/configs/px4io/common/Make.defs b/nuttx/configs/px4io/common/Make.defs
index 4958f70926..7f782b5b22 100644
--- a/nuttx/configs/px4io/common/Make.defs
+++ b/nuttx/configs/px4io/common/Make.defs
@@ -112,7 +112,6 @@ ARCHOPTIMIZATION = $(MAXOPTIMIZATION) \
ifeq ("${CONFIG_DEBUG_SYMBOLS}","y")
ARCHOPTIMIZATION += -g
-ARCHSCRIPT += -g
endif
ARCHCFLAGS = -std=gnu99
@@ -145,7 +144,7 @@ ARCHDEFINES =
ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
# this seems to be the only way to add linker flags
-ARCHSCRIPT += --warn-common \
+EXTRA_LIBS += --warn-common \
--gc-sections
CFLAGS = $(ARCHCFLAGS) $(ARCHCWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(INSTRUMENTATIONDEFINES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe -fno-common
diff --git a/nuttx/configs/px4io/include/board.h b/nuttx/configs/px4io/include/board.h
index d941985b47..fcbc936209 100755
--- a/nuttx/configs/px4io/include/board.h
+++ b/nuttx/configs/px4io/include/board.h
@@ -100,12 +100,19 @@
* Some of the USART pins are not available; override the GPIO
* definitions with an invalid pin configuration.
*/
+#undef GPIO_USART2_CTS
#define GPIO_USART2_CTS 0xffffffff
+#undef GPIO_USART2_RTS
#define GPIO_USART2_RTS 0xffffffff
+#undef GPIO_USART2_CK
#define GPIO_USART2_CK 0xffffffff
+#undef GPIO_USART3_TX
#define GPIO_USART3_TX 0xffffffff
+#undef GPIO_USART3_CK
#define GPIO_USART3_CK 0xffffffff
+#undef GPIO_USART3_CTS
#define GPIO_USART3_CTS 0xffffffff
+#undef GPIO_USART3_RTS
#define GPIO_USART3_RTS 0xffffffff
/*
@@ -156,6 +163,10 @@ extern "C" {
************************************************************************************/
EXTERN void stm32_boardinitialize(void);
+
+#if defined(__cplusplus)
+}
+#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_BOARD_BOARD_H */
diff --git a/nuttx/configs/px4io/io/appconfig b/nuttx/configs/px4io/io/appconfig
index 628607a515..48a41bcdb8 100644
--- a/nuttx/configs/px4io/io/appconfig
+++ b/nuttx/configs/px4io/io/appconfig
@@ -30,11 +30,3 @@
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
-
-CONFIGURED_APPS += drivers/boards/px4io
-CONFIGURED_APPS += drivers/stm32
-
-CONFIGURED_APPS += px4io
-
-# Mixer library from systemlib
-CONFIGURED_APPS += systemlib/mixer
diff --git a/nuttx/libc/stdio/lib_libdtoa.c b/nuttx/libc/stdio/lib_libdtoa.c
index 29f61fd76e..395a55b61b 100644
--- a/nuttx/libc/stdio/lib_libdtoa.c
+++ b/nuttx/libc/stdio/lib_libdtoa.c
@@ -43,6 +43,7 @@
/****************************************************************************
* Included Files
****************************************************************************/
+#include
/****************************************************************************
* Pre-processor Definitions
@@ -104,6 +105,13 @@ static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes)
* Private Functions
****************************************************************************/
+static void lib_dtoa_string(FAR struct lib_outstream_s *obj, const char *str)
+{
+ while (*str) {
+ obj->put(obj, *str++);
+ }
+}
+
/****************************************************************************
* Name: lib_dtoa
*
@@ -137,9 +145,23 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
int nchars; /* Number of characters to print */
int dsgn; /* Unused sign indicator */
int i;
+ bool done_decimal_point = false;
+
+ /* special handling for NaN and Infinity */
+ if (isnan(value)) {
+ lib_dtoa_string(obj, "NaN");
+ return;
+ }
+ if (isinf(value)) {
+ if (value < 0.0d) {
+ obj->put(obj, '-');
+ }
+ lib_dtoa_string(obj, "Infinity");
+ return;
+ }
/* Non-zero... positive or negative */
-
+
if (value < 0)
{
value = -value;
@@ -178,6 +200,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
if (prec > 0 || IS_ALTFORM(flags))
{
obj->put(obj, '.');
+ done_decimal_point = true;
/* Always print at least one digit to the right of the decimal point. */
@@ -203,6 +226,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
/* Print the decimal point */
obj->put(obj, '.');
+ done_decimal_point = true;
/* Print any leading zeros to the right of the decimal point */
@@ -249,6 +273,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
/* Print the decimal point */
obj->put(obj, '.');
+ done_decimal_point = true;
/* Always print at least one digit to the right of the decimal
* point.
@@ -285,8 +310,9 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
}
/* Finally, print any trailing zeroes */
-
- zeroes(obj, prec);
+ if (done_decimal_point) {
+ zeroes(obj, prec);
+ }
/* Is this memory supposed to be freed or not? */
diff --git a/nuttx/libc/stdio/lib_libvsprintf.c b/nuttx/libc/stdio/lib_libvsprintf.c
index 9a391610dc..2cc7950f7b 100644
--- a/nuttx/libc/stdio/lib_libvsprintf.c
+++ b/nuttx/libc/stdio/lib_libvsprintf.c
@@ -1215,7 +1215,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
fmt = FMT_RJUST;
width = 0;
#ifdef CONFIG_LIBC_FLOATINGPOINT
- trunc = 0;
+ trunc = 6;
#endif
#endif
@@ -1245,6 +1245,11 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
{
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
fmt = FMT_RJUST0;
+#ifdef CONFIG_LIBC_FLOATINGPOINT
+ if (IS_HASDOT(flags)) {
+ trunc = 0;
+ }
+#endif
#endif
}
#if 0
diff --git a/platforms/empty.c b/platforms/empty.c
new file mode 100644
index 0000000000..1395313542
--- /dev/null
+++ b/platforms/empty.c
@@ -0,0 +1,3 @@
+/*
+ * This is an empty C source file, used when building default firmware configurations.
+ */
diff --git a/apps/ardrone_interface/ardrone_interface.c b/src/drivers/ardrone_interface/ardrone_interface.c
similarity index 100%
rename from apps/ardrone_interface/ardrone_interface.c
rename to src/drivers/ardrone_interface/ardrone_interface.c
diff --git a/apps/ardrone_interface/ardrone_motor_control.c b/src/drivers/ardrone_interface/ardrone_motor_control.c
similarity index 98%
rename from apps/ardrone_interface/ardrone_motor_control.c
rename to src/drivers/ardrone_interface/ardrone_motor_control.c
index f15c74a22d..ecd31a073d 100644
--- a/apps/ardrone_interface/ardrone_motor_control.c
+++ b/src/drivers/ardrone_interface/ardrone_motor_control.c
@@ -482,10 +482,10 @@ void ardrone_mixing_and_output(int ardrone_write, const struct actuator_controls
motor_pwm[3] = (motor_pwm[3] > 0) ? motor_pwm[3] : 10;
/* Failsafe logic - should never be necessary */
- motor_pwm[0] = (motor_pwm[0] <= 512) ? motor_pwm[0] : 512;
- motor_pwm[1] = (motor_pwm[1] <= 512) ? motor_pwm[1] : 512;
- motor_pwm[2] = (motor_pwm[2] <= 512) ? motor_pwm[2] : 512;
- motor_pwm[3] = (motor_pwm[3] <= 512) ? motor_pwm[3] : 512;
+ motor_pwm[0] = (motor_pwm[0] <= 511) ? motor_pwm[0] : 511;
+ motor_pwm[1] = (motor_pwm[1] <= 511) ? motor_pwm[1] : 511;
+ motor_pwm[2] = (motor_pwm[2] <= 511) ? motor_pwm[2] : 511;
+ motor_pwm[3] = (motor_pwm[3] <= 511) ? motor_pwm[3] : 511;
/* send motors via UART */
ardrone_write_motor_commands(ardrone_write, motor_pwm[0], motor_pwm[1], motor_pwm[2], motor_pwm[3]);
diff --git a/apps/ardrone_interface/ardrone_motor_control.h b/src/drivers/ardrone_interface/ardrone_motor_control.h
similarity index 100%
rename from apps/ardrone_interface/ardrone_motor_control.h
rename to src/drivers/ardrone_interface/ardrone_motor_control.h
diff --git a/src/drivers/ardrone_interface/module.mk b/src/drivers/ardrone_interface/module.mk
new file mode 100644
index 0000000000..058bd1397d
--- /dev/null
+++ b/src/drivers/ardrone_interface/module.mk
@@ -0,0 +1,40 @@
+############################################################################
+#
+# Copyright (C) 2012-2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# AR.Drone motor driver
+#
+
+MODULE_COMMAND = ardrone_interface
+SRCS = ardrone_interface.c \
+ ardrone_motor_control.c
diff --git a/apps/drivers/blinkm/blinkm.cpp b/src/drivers/blinkm/blinkm.cpp
similarity index 99%
rename from apps/drivers/blinkm/blinkm.cpp
rename to src/drivers/blinkm/blinkm.cpp
index 60d51f9afc..7a64b72a4e 100644
--- a/apps/drivers/blinkm/blinkm.cpp
+++ b/src/drivers/blinkm/blinkm.cpp
@@ -92,6 +92,7 @@
#include
+#include
#include
#include
@@ -842,7 +843,7 @@ int
blinkm_main(int argc, char *argv[])
{
- int i2cdevice = 3;
+ int i2cdevice = PX4_I2C_BUS_EXPANSION;
int blinkmadr = 9;
int x;
diff --git a/apps/drivers/device/Makefile b/src/drivers/blinkm/module.mk
similarity index 92%
rename from apps/drivers/device/Makefile
rename to src/drivers/blinkm/module.mk
index f7b1fff888..b48b90f3f4 100644
--- a/apps/drivers/device/Makefile
+++ b/src/drivers/blinkm/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,7 +32,9 @@
############################################################################
#
-# Build the device driver framework.
+# BlinkM I2C LED driver
#
-include $(APPDIR)/mk/app.mk
+MODULE_COMMAND = blinkm
+
+SRCS = blinkm.cpp
diff --git a/apps/drivers/bma180/bma180.cpp b/src/drivers/bma180/bma180.cpp
similarity index 100%
rename from apps/drivers/bma180/bma180.cpp
rename to src/drivers/bma180/bma180.cpp
diff --git a/apps/drivers/bma180/Makefile b/src/drivers/bma180/module.mk
similarity index 91%
rename from apps/drivers/bma180/Makefile
rename to src/drivers/bma180/module.mk
index cc01b629e6..4c60ee082c 100644
--- a/apps/drivers/bma180/Makefile
+++ b/src/drivers/bma180/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -35,8 +35,6 @@
# Makefile to build the BMA180 driver.
#
-APPNAME = bma180
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = bma180
-include $(APPDIR)/mk/app.mk
+SRCS = bma180.cpp
diff --git a/src/drivers/boards/px4fmu/module.mk b/src/drivers/boards/px4fmu/module.mk
new file mode 100644
index 0000000000..66b7769173
--- /dev/null
+++ b/src/drivers/boards/px4fmu/module.mk
@@ -0,0 +1,10 @@
+#
+# Board-specific startup code for the PX4FMU
+#
+
+SRCS = px4fmu_can.c \
+ px4fmu_init.c \
+ px4fmu_pwm_servo.c \
+ px4fmu_spi.c \
+ px4fmu_usb.c \
+ px4fmu_led.c
diff --git a/apps/drivers/boards/px4fmu/px4fmu_can.c b/src/drivers/boards/px4fmu/px4fmu_can.c
similarity index 99%
rename from apps/drivers/boards/px4fmu/px4fmu_can.c
rename to src/drivers/boards/px4fmu/px4fmu_can.c
index 0d0b5fcd36..187689ff9a 100644
--- a/apps/drivers/boards/px4fmu/px4fmu_can.c
+++ b/src/drivers/boards/px4fmu/px4fmu_can.c
@@ -37,7 +37,6 @@
* Board-specific CAN functions.
*/
-
/************************************************************************************
* Included Files
************************************************************************************/
@@ -57,6 +56,8 @@
#include "stm32_can.h"
#include "px4fmu_internal.h"
+#ifdef CONFIG_CAN
+
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
@@ -139,3 +140,5 @@ int can_devinit(void)
return OK;
}
+
+#endif
diff --git a/apps/drivers/boards/px4fmu/px4fmu_init.c b/src/drivers/boards/px4fmu/px4fmu_init.c
similarity index 81%
rename from apps/drivers/boards/px4fmu/px4fmu_init.c
rename to src/drivers/boards/px4fmu/px4fmu_init.c
index 9960c6bbd5..69edc23ab2 100644
--- a/apps/drivers/boards/px4fmu/px4fmu_init.c
+++ b/src/drivers/boards/px4fmu/px4fmu_init.c
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -91,6 +91,19 @@
# endif
#endif
+/*
+ * Ideally we'd be able to get these from up_internal.h,
+ * but since we want to be able to disable the NuttX use
+ * of leds for system indication at will and there is no
+ * separate switch, we need to build independent of the
+ * CONFIG_ARCH_LEDS configuration switch.
+ */
+__BEGIN_DECLS
+extern void led_init();
+extern void led_on(int led);
+extern void led_off(int led);
+__END_DECLS
+
/****************************************************************************
* Protected Functions
****************************************************************************/
@@ -114,7 +127,7 @@ __EXPORT void stm32_boardinitialize(void)
/* configure SPI interfaces */
stm32_spiinitialize();
- /* configure LEDs */
+ /* configure LEDs (empty call to NuttX' ledinit) */
up_ledinit();
}
@@ -127,6 +140,7 @@ __EXPORT void stm32_boardinitialize(void)
****************************************************************************/
static struct spi_dev_s *spi1;
+static struct spi_dev_s *spi2;
static struct spi_dev_s *spi3;
#include
@@ -147,6 +161,11 @@ __EXPORT int nsh_archinitialize(void)
{
int result;
+ /* configure always-on ADC pins */
+ stm32_configgpio(GPIO_ADC1_IN10);
+ stm32_configgpio(GPIO_ADC1_IN11);
+ /* IN12 and IN13 further below */
+
/* configure the high-resolution time/callout interface */
hrt_init();
@@ -172,11 +191,11 @@ __EXPORT int nsh_archinitialize(void)
(hrt_callout)stm32_serial_dma_poll,
NULL);
- // initial LED state
+ /* initial LED state */
drv_led_start();
- up_ledoff(LED_BLUE);
- up_ledoff(LED_AMBER);
- up_ledon(LED_BLUE);
+ led_off(LED_AMBER);
+ led_on(LED_BLUE);
+
/* Configure SPI-based devices */
@@ -188,7 +207,7 @@ __EXPORT int nsh_archinitialize(void)
return -ENODEV;
}
- // Default SPI1 to 1MHz and de-assert the known chip selects.
+ /* Default SPI1 to 1MHz and de-assert the known chip selects. */
SPI_SETFREQUENCY(spi1, 10000000);
SPI_SETBITS(spi1, 8);
SPI_SETMODE(spi1, SPIDEV_MODE3);
@@ -199,6 +218,28 @@ __EXPORT int nsh_archinitialize(void)
message("[boot] Successfully initialized SPI port 1\r\n");
+ /*
+ * If SPI2 is enabled in the defconfig, we loose some ADC pins as chip selects.
+ * Keep the SPI2 init optional and conditionally initialize the ADC pins
+ */
+ spi2 = up_spiinitialize(2);
+
+ if (!spi2) {
+ message("[boot] Enabling IN12/13 instead of SPI2\n");
+ /* no SPI2, use pins for ADC */
+ stm32_configgpio(GPIO_ADC1_IN12);
+ stm32_configgpio(GPIO_ADC1_IN13); // jumperable to MPU6000 DRDY on some boards
+ } else {
+ /* Default SPI2 to 1MHz and de-assert the known chip selects. */
+ SPI_SETFREQUENCY(spi2, 10000000);
+ SPI_SETBITS(spi2, 8);
+ SPI_SETMODE(spi2, SPIDEV_MODE3);
+ SPI_SELECT(spi2, PX4_SPIDEV_GYRO, false);
+ SPI_SELECT(spi2, PX4_SPIDEV_ACCEL_MAG, false);
+
+ message("[boot] Initialized SPI port2 (ADC IN12/13 blocked)\n");
+ }
+
/* Get the SPI port for the microSD slot */
message("[boot] Initializing SPI port 3\n");
@@ -223,10 +264,5 @@ __EXPORT int nsh_archinitialize(void)
message("[boot] Successfully bound SPI port 3 to the MMCSD driver\n");
- stm32_configgpio(GPIO_ADC1_IN10);
- stm32_configgpio(GPIO_ADC1_IN11);
- stm32_configgpio(GPIO_ADC1_IN12);
- stm32_configgpio(GPIO_ADC1_IN13); // jumperable to MPU6000 DRDY on some boards
-
return OK;
}
diff --git a/apps/drivers/boards/px4fmu/px4fmu_internal.h b/src/drivers/boards/px4fmu/px4fmu_internal.h
similarity index 98%
rename from apps/drivers/boards/px4fmu/px4fmu_internal.h
rename to src/drivers/boards/px4fmu/px4fmu_internal.h
index 6550fdf3da..671a58f8f6 100644
--- a/apps/drivers/boards/px4fmu/px4fmu_internal.h
+++ b/src/drivers/boards/px4fmu/px4fmu_internal.h
@@ -58,9 +58,9 @@ __BEGIN_DECLS
****************************************************************************************************/
/* Configuration ************************************************************************************/
-#ifdef CONFIG_STM32_SPI2
-# error "SPI2 is not supported on this board"
-#endif
+//#ifdef CONFIG_STM32_SPI2
+//# error "SPI2 is not supported on this board"
+//#endif
#if defined(CONFIG_STM32_CAN1)
# warning "CAN1 is not supported on this board"
@@ -77,6 +77,7 @@ __BEGIN_DECLS
// XXX MPU6000 DRDY?
/* SPI chip selects */
+
#define GPIO_SPI_CS_GYRO (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN14)
#define GPIO_SPI_CS_ACCEL (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN15)
#define GPIO_SPI_CS_MPU (GPIO_OUTPUT|GPIO_PUSHPULL|GPIO_SPEED_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN0)
diff --git a/apps/drivers/boards/px4fmu/px4fmu_led.c b/src/drivers/boards/px4fmu/px4fmu_led.c
similarity index 83%
rename from apps/drivers/boards/px4fmu/px4fmu_led.c
rename to src/drivers/boards/px4fmu/px4fmu_led.c
index fd1e159aa7..34fd194c33 100644
--- a/apps/drivers/boards/px4fmu/px4fmu_led.c
+++ b/src/drivers/boards/px4fmu/px4fmu_led.c
@@ -39,19 +39,27 @@
#include
-#include
#include
-#include
-#include
-
-#include "chip.h"
-#include "up_arch.h"
-#include "up_internal.h"
#include "stm32_internal.h"
#include "px4fmu_internal.h"
-__EXPORT void up_ledinit()
+#include
+
+/*
+ * Ideally we'd be able to get these from up_internal.h,
+ * but since we want to be able to disable the NuttX use
+ * of leds for system indication at will and there is no
+ * separate switch, we need to build independent of the
+ * CONFIG_ARCH_LEDS configuration switch.
+ */
+__BEGIN_DECLS
+extern void led_init();
+extern void led_on(int led);
+extern void led_off(int led);
+__END_DECLS
+
+__EXPORT void led_init()
{
/* Configure LED1-2 GPIOs for output */
@@ -59,7 +67,7 @@ __EXPORT void up_ledinit()
stm32_configgpio(GPIO_LED2);
}
-__EXPORT void up_ledon(int led)
+__EXPORT void led_on(int led)
{
if (led == 0)
{
@@ -73,7 +81,7 @@ __EXPORT void up_ledon(int led)
}
}
-__EXPORT void up_ledoff(int led)
+__EXPORT void led_off(int led)
{
if (led == 0)
{
diff --git a/apps/drivers/boards/px4fmu/px4fmu_pwm_servo.c b/src/drivers/boards/px4fmu/px4fmu_pwm_servo.c
similarity index 100%
rename from apps/drivers/boards/px4fmu/px4fmu_pwm_servo.c
rename to src/drivers/boards/px4fmu/px4fmu_pwm_servo.c
diff --git a/apps/drivers/boards/px4fmu/px4fmu_spi.c b/src/drivers/boards/px4fmu/px4fmu_spi.c
similarity index 93%
rename from apps/drivers/boards/px4fmu/px4fmu_spi.c
rename to src/drivers/boards/px4fmu/px4fmu_spi.c
index 7a02eaeb7d..b5d00eac0d 100644
--- a/apps/drivers/boards/px4fmu/px4fmu_spi.c
+++ b/src/drivers/boards/px4fmu/px4fmu_spi.c
@@ -121,6 +121,24 @@ __EXPORT uint8_t stm32_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devi
return SPI_STATUS_PRESENT;
}
+__EXPORT void stm32_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected)
+{
+ /* SPI select is active low, so write !selected to select the device */
+
+ switch (devid) {
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+__EXPORT uint8_t stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid)
+{
+ return SPI_STATUS_PRESENT;
+}
+
__EXPORT void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected)
{
diff --git a/apps/drivers/boards/px4fmu/px4fmu_usb.c b/src/drivers/boards/px4fmu/px4fmu_usb.c
similarity index 100%
rename from apps/drivers/boards/px4fmu/px4fmu_usb.c
rename to src/drivers/boards/px4fmu/px4fmu_usb.c
diff --git a/src/drivers/boards/px4io/module.mk b/src/drivers/boards/px4io/module.mk
new file mode 100644
index 0000000000..2601a1c15a
--- /dev/null
+++ b/src/drivers/boards/px4io/module.mk
@@ -0,0 +1,6 @@
+#
+# Board-specific startup code for the PX4IO
+#
+
+SRCS = px4io_init.c \
+ px4io_pwm_servo.c
diff --git a/apps/drivers/boards/px4io/px4io_init.c b/src/drivers/boards/px4io/px4io_init.c
similarity index 95%
rename from apps/drivers/boards/px4io/px4io_init.c
rename to src/drivers/boards/px4io/px4io_init.c
index 14e8dc13a9..d36353c6f5 100644
--- a/apps/drivers/boards/px4io/px4io_init.c
+++ b/src/drivers/boards/px4io/px4io_init.c
@@ -86,9 +86,17 @@ __EXPORT void stm32_boardinitialize(void)
stm32_configgpio(GPIO_SERVO_PWR_EN);
stm32_configgpio(GPIO_RELAY1_EN);
stm32_configgpio(GPIO_RELAY2_EN);
+
+ /* turn off - all leds are active low */
+ stm32_gpiowrite(GPIO_LED1, true);
+ stm32_gpiowrite(GPIO_LED2, true);
+ stm32_gpiowrite(GPIO_LED3, true);
+
+ /* LED config */
stm32_configgpio(GPIO_LED1);
stm32_configgpio(GPIO_LED2);
stm32_configgpio(GPIO_LED3);
+
stm32_configgpio(GPIO_ACC_OC_DETECT);
stm32_configgpio(GPIO_SERVO_OC_DETECT);
stm32_configgpio(GPIO_BTN_SAFETY);
diff --git a/apps/drivers/boards/px4io/px4io_internal.h b/src/drivers/boards/px4io/px4io_internal.h
similarity index 98%
rename from apps/drivers/boards/px4io/px4io_internal.h
rename to src/drivers/boards/px4io/px4io_internal.h
index 44bb98513b..eb2820bb7b 100644
--- a/apps/drivers/boards/px4io/px4io_internal.h
+++ b/src/drivers/boards/px4io/px4io_internal.h
@@ -32,7 +32,9 @@
****************************************************************************/
/**
- * @file PX4IO hardware definitions.
+ * @file px4io_internal.h
+ *
+ * PX4IO hardware definitions.
*/
#pragma once
diff --git a/apps/drivers/boards/px4io/px4io_pwm_servo.c b/src/drivers/boards/px4io/px4io_pwm_servo.c
similarity index 100%
rename from apps/drivers/boards/px4io/px4io_pwm_servo.c
rename to src/drivers/boards/px4io/px4io_pwm_servo.c
diff --git a/apps/drivers/device/cdev.cpp b/src/drivers/device/cdev.cpp
similarity index 100%
rename from apps/drivers/device/cdev.cpp
rename to src/drivers/device/cdev.cpp
diff --git a/apps/drivers/device/device.cpp b/src/drivers/device/device.cpp
similarity index 100%
rename from apps/drivers/device/device.cpp
rename to src/drivers/device/device.cpp
diff --git a/apps/drivers/device/device.h b/src/drivers/device/device.h
similarity index 100%
rename from apps/drivers/device/device.h
rename to src/drivers/device/device.h
diff --git a/apps/drivers/device/i2c.cpp b/src/drivers/device/i2c.cpp
similarity index 100%
rename from apps/drivers/device/i2c.cpp
rename to src/drivers/device/i2c.cpp
diff --git a/apps/drivers/device/i2c.h b/src/drivers/device/i2c.h
similarity index 95%
rename from apps/drivers/device/i2c.h
rename to src/drivers/device/i2c.h
index 66c34dd7c4..b4a9cdd536 100644
--- a/apps/drivers/device/i2c.h
+++ b/src/drivers/device/i2c.h
@@ -53,6 +53,15 @@ namespace device __EXPORT
class __EXPORT I2C : public CDev
{
+public:
+
+ /**
+ * Get the address
+ */
+ uint16_t get_address() {
+ return _address;
+ }
+
protected:
/**
* The number of times a read or write operation will be retried on
@@ -60,6 +69,11 @@ protected:
*/
unsigned _retries;
+ /**
+ * The I2C bus number the device is attached to.
+ */
+ int _bus;
+
/**
* @ Constructor
*
@@ -123,7 +137,6 @@ protected:
}
private:
- int _bus;
uint16_t _address;
uint32_t _frequency;
struct i2c_dev_s *_dev;
diff --git a/apps/drivers/hmc5883/Makefile b/src/drivers/device/module.mk
similarity index 89%
rename from apps/drivers/hmc5883/Makefile
rename to src/drivers/device/module.mk
index 4d7cb4e7b9..8c716d9cdb 100644
--- a/apps/drivers/hmc5883/Makefile
+++ b/src/drivers/device/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,11 +32,11 @@
############################################################################
#
-# HMC5883 driver
+# Build the device driver framework.
#
-APPNAME = hmc5883
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 4096
-
-include $(APPDIR)/mk/app.mk
+SRCS = cdev.cpp \
+ device.cpp \
+ i2c.cpp \
+ pio.cpp \
+ spi.cpp
diff --git a/apps/drivers/device/pio.cpp b/src/drivers/device/pio.cpp
similarity index 100%
rename from apps/drivers/device/pio.cpp
rename to src/drivers/device/pio.cpp
diff --git a/apps/drivers/device/spi.cpp b/src/drivers/device/spi.cpp
similarity index 100%
rename from apps/drivers/device/spi.cpp
rename to src/drivers/device/spi.cpp
diff --git a/apps/drivers/device/spi.h b/src/drivers/device/spi.h
similarity index 100%
rename from apps/drivers/device/spi.h
rename to src/drivers/device/spi.h
diff --git a/apps/drivers/drv_accel.h b/src/drivers/drv_accel.h
similarity index 100%
rename from apps/drivers/drv_accel.h
rename to src/drivers/drv_accel.h
diff --git a/apps/drivers/drv_adc.h b/src/drivers/drv_adc.h
similarity index 100%
rename from apps/drivers/drv_adc.h
rename to src/drivers/drv_adc.h
diff --git a/src/drivers/drv_airspeed.h b/src/drivers/drv_airspeed.h
new file mode 100644
index 0000000000..bffc35c62c
--- /dev/null
+++ b/src/drivers/drv_airspeed.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file Airspeed driver interface.
+ * @author Simon Wilks
+ */
+
+#ifndef _DRV_AIRSPEED_H
+#define _DRV_AIRSPEED_H
+
+#include
+#include
+
+#include "drv_sensor.h"
+#include "drv_orb_dev.h"
+
+#define AIRSPEED_DEVICE_PATH "/dev/airspeed"
+
+/*
+ * ioctl() definitions
+ *
+ * Airspeed drivers also implement the generic sensor driver
+ * interfaces from drv_sensor.h
+ */
+
+#define _AIRSPEEDIOCBASE (0x7700)
+#define __AIRSPEEDIOC(_n) (_IOC(_AIRSPEEDIOCBASE, _n))
+
+
+#endif /* _DRV_AIRSPEED_H */
diff --git a/apps/drivers/drv_baro.h b/src/drivers/drv_baro.h
similarity index 100%
rename from apps/drivers/drv_baro.h
rename to src/drivers/drv_baro.h
diff --git a/apps/drivers/drv_blinkm.h b/src/drivers/drv_blinkm.h
similarity index 100%
rename from apps/drivers/drv_blinkm.h
rename to src/drivers/drv_blinkm.h
diff --git a/apps/drivers/drv_gpio.h b/src/drivers/drv_gpio.h
similarity index 100%
rename from apps/drivers/drv_gpio.h
rename to src/drivers/drv_gpio.h
diff --git a/apps/drivers/drv_gps.h b/src/drivers/drv_gps.h
similarity index 100%
rename from apps/drivers/drv_gps.h
rename to src/drivers/drv_gps.h
diff --git a/apps/drivers/drv_gyro.h b/src/drivers/drv_gyro.h
similarity index 100%
rename from apps/drivers/drv_gyro.h
rename to src/drivers/drv_gyro.h
diff --git a/apps/drivers/drv_hrt.h b/src/drivers/drv_hrt.h
similarity index 100%
rename from apps/drivers/drv_hrt.h
rename to src/drivers/drv_hrt.h
diff --git a/apps/drivers/drv_led.h b/src/drivers/drv_led.h
similarity index 100%
rename from apps/drivers/drv_led.h
rename to src/drivers/drv_led.h
diff --git a/apps/drivers/drv_mag.h b/src/drivers/drv_mag.h
similarity index 100%
rename from apps/drivers/drv_mag.h
rename to src/drivers/drv_mag.h
diff --git a/apps/drivers/drv_mixer.h b/src/drivers/drv_mixer.h
similarity index 100%
rename from apps/drivers/drv_mixer.h
rename to src/drivers/drv_mixer.h
diff --git a/apps/drivers/drv_orb_dev.h b/src/drivers/drv_orb_dev.h
similarity index 98%
rename from apps/drivers/drv_orb_dev.h
rename to src/drivers/drv_orb_dev.h
index 8495780d56..713618545d 100644
--- a/apps/drivers/drv_orb_dev.h
+++ b/src/drivers/drv_orb_dev.h
@@ -43,7 +43,7 @@
#include
/* XXX for ORB_DECLARE used in many drivers */
-#include "../uORB/uORB.h"
+#include "../modules/uORB/uORB.h"
/*
* ioctl() definitions
diff --git a/apps/drivers/drv_pwm_output.h b/src/drivers/drv_pwm_output.h
similarity index 96%
rename from apps/drivers/drv_pwm_output.h
rename to src/drivers/drv_pwm_output.h
index 07831f20cf..56af710592 100644
--- a/apps/drivers/drv_pwm_output.h
+++ b/src/drivers/drv_pwm_output.h
@@ -109,6 +109,12 @@ ORB_DECLARE(output_pwm);
/** selects servo update rates, one bit per servo. 0 = default (50Hz), 1 = alternate */
#define PWM_SERVO_SELECT_UPDATE_RATE _IOC(_PWM_SERVO_BASE, 4)
+/** set the 'ARM ok' bit, which activates the safety switch */
+#define PWM_SERVO_SET_ARM_OK _IOC(_PWM_SERVO_BASE, 5)
+
+/** clear the 'ARM ok' bit, which deactivates the safety switch */
+#define PWM_SERVO_CLEAR_ARM_OK _IOC(_PWM_SERVO_BASE, 6)
+
/** set a single servo to a specific value */
#define PWM_SERVO_SET(_servo) _IOC(_PWM_SERVO_BASE, 0x20 + _servo)
diff --git a/apps/drivers/drv_range_finder.h b/src/drivers/drv_range_finder.h
similarity index 100%
rename from apps/drivers/drv_range_finder.h
rename to src/drivers/drv_range_finder.h
diff --git a/apps/drivers/drv_rc_input.h b/src/drivers/drv_rc_input.h
similarity index 100%
rename from apps/drivers/drv_rc_input.h
rename to src/drivers/drv_rc_input.h
diff --git a/apps/drivers/drv_sensor.h b/src/drivers/drv_sensor.h
similarity index 100%
rename from apps/drivers/drv_sensor.h
rename to src/drivers/drv_sensor.h
diff --git a/apps/drivers/drv_tone_alarm.h b/src/drivers/drv_tone_alarm.h
similarity index 100%
rename from apps/drivers/drv_tone_alarm.h
rename to src/drivers/drv_tone_alarm.h
diff --git a/src/drivers/ets_airspeed/ets_airspeed.cpp b/src/drivers/ets_airspeed/ets_airspeed.cpp
new file mode 100644
index 0000000000..e50395e479
--- /dev/null
+++ b/src/drivers/ets_airspeed/ets_airspeed.cpp
@@ -0,0 +1,832 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file ets_airspeed.cpp
+ * @author Simon Wilks
+ *
+ * Driver for the Eagle Tree Airspeed V3 connected via I2C.
+ */
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+/* Default I2C bus */
+#define PX4_I2C_BUS_DEFAULT PX4_I2C_BUS_EXPANSION
+
+/* I2C bus address */
+#define I2C_ADDRESS 0x75 /* 7-bit address. 8-bit address is 0xEA */
+
+/* Register address */
+#define READ_CMD 0x07 /* Read the data */
+
+/**
+ * The Eagle Tree Airspeed V3 cannot provide accurate reading below speeds of 15km/h.
+ */
+#define MIN_ACCURATE_DIFF_PRES_PA 12
+
+/* Measurement rate is 100Hz */
+#define CONVERSION_INTERVAL (1000000 / 100) /* microseconds */
+
+/* Oddly, ERROR is not defined for C++ */
+#ifdef ERROR
+# undef ERROR
+#endif
+static const int ERROR = -1;
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+# error This requires CONFIG_SCHED_WORKQUEUE.
+#endif
+
+class ETSAirspeed : public device::I2C
+{
+public:
+ ETSAirspeed(int bus, int address = I2C_ADDRESS);
+ virtual ~ETSAirspeed();
+
+ virtual int init();
+
+ virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
+ virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
+
+ /**
+ * Diagnostics - print some basic information about the driver.
+ */
+ void print_info();
+
+protected:
+ virtual int probe();
+
+private:
+ work_s _work;
+ unsigned _num_reports;
+ volatile unsigned _next_report;
+ volatile unsigned _oldest_report;
+ differential_pressure_s *_reports;
+ bool _sensor_ok;
+ int _measure_ticks;
+ bool _collect_phase;
+ int _diff_pres_offset;
+
+ orb_advert_t _airspeed_pub;
+
+ perf_counter_t _sample_perf;
+ perf_counter_t _comms_errors;
+ perf_counter_t _buffer_overflows;
+
+
+ /**
+ * Test whether the device supported by the driver is present at a
+ * specific address.
+ *
+ * @param address The I2C bus address to probe.
+ * @return True if the device is present.
+ */
+ int probe_address(uint8_t address);
+
+ /**
+ * Initialise the automatic measurement state machine and start it.
+ *
+ * @note This function is called at open and error time. It might make sense
+ * to make it more aggressive about resetting the bus in case of errors.
+ */
+ void start();
+
+ /**
+ * Stop the automatic measurement state machine.
+ */
+ void stop();
+
+ /**
+ * Perform a poll cycle; collect from the previous measurement
+ * and start a new one.
+ */
+ void cycle();
+ int measure();
+ int collect();
+
+ /**
+ * Static trampoline from the workq context; because we don't have a
+ * generic workq wrapper yet.
+ *
+ * @param arg Instance pointer for the driver that is polling.
+ */
+ static void cycle_trampoline(void *arg);
+
+
+};
+
+/* helper macro for handling report buffer indices */
+#define INCREMENT(_x, _lim) do { _x++; if (_x >= _lim) _x = 0; } while(0)
+
+/*
+ * Driver 'main' command.
+ */
+extern "C" __EXPORT int ets_airspeed_main(int argc, char *argv[]);
+
+ETSAirspeed::ETSAirspeed(int bus, int address) :
+ I2C("ETSAirspeed", AIRSPEED_DEVICE_PATH, bus, address, 100000),
+ _num_reports(0),
+ _next_report(0),
+ _oldest_report(0),
+ _reports(nullptr),
+ _sensor_ok(false),
+ _measure_ticks(0),
+ _collect_phase(false),
+ _diff_pres_offset(0),
+ _airspeed_pub(-1),
+ _sample_perf(perf_alloc(PC_ELAPSED, "ets_airspeed_read")),
+ _comms_errors(perf_alloc(PC_COUNT, "ets_airspeed_comms_errors")),
+ _buffer_overflows(perf_alloc(PC_COUNT, "ets_airspeed_buffer_overflows"))
+{
+ // enable debug() calls
+ _debug_enabled = true;
+
+ // work_cancel in the dtor will explode if we don't do this...
+ memset(&_work, 0, sizeof(_work));
+}
+
+ETSAirspeed::~ETSAirspeed()
+{
+ /* make sure we are truly inactive */
+ stop();
+
+ /* free any existing reports */
+ if (_reports != nullptr)
+ delete[] _reports;
+}
+
+int
+ETSAirspeed::init()
+{
+ int ret = ERROR;
+
+ /* do I2C init (and probe) first */
+ if (I2C::init() != OK)
+ goto out;
+
+ /* allocate basic report buffers */
+ _num_reports = 2;
+ _reports = new struct differential_pressure_s[_num_reports];
+ for (unsigned i = 0; i < _num_reports; i++)
+ _reports[i].max_differential_pressure_pa = 0;
+
+ if (_reports == nullptr)
+ goto out;
+
+ _oldest_report = _next_report = 0;
+
+ /* get a publish handle on the airspeed topic */
+ memset(&_reports[0], 0, sizeof(_reports[0]));
+ _airspeed_pub = orb_advertise(ORB_ID(differential_pressure), &_reports[0]);
+
+ if (_airspeed_pub < 0)
+ debug("failed to create airspeed sensor object. Did you start uOrb?");
+
+ ret = OK;
+ /* sensor is ok, but we don't really know if it is within range */
+ _sensor_ok = true;
+out:
+ return ret;
+}
+
+int
+ETSAirspeed::probe()
+{
+ return measure();
+}
+
+int
+ETSAirspeed::ioctl(struct file *filp, int cmd, unsigned long arg)
+{
+ switch (cmd) {
+
+ case SENSORIOCSPOLLRATE: {
+ switch (arg) {
+
+ /* switching to manual polling */
+ case SENSOR_POLLRATE_MANUAL:
+ stop();
+ _measure_ticks = 0;
+ return OK;
+
+ /* external signalling (DRDY) not supported */
+ case SENSOR_POLLRATE_EXTERNAL:
+
+ /* zero would be bad */
+ case 0:
+ return -EINVAL;
+
+ /* set default/max polling rate */
+ case SENSOR_POLLRATE_MAX:
+ case SENSOR_POLLRATE_DEFAULT: {
+ /* do we need to start internal polling? */
+ bool want_start = (_measure_ticks == 0);
+
+ /* set interval for next measurement to minimum legal value */
+ _measure_ticks = USEC2TICK(CONVERSION_INTERVAL);
+
+ /* if we need to start the poll state machine, do it */
+ if (want_start)
+ start();
+
+ return OK;
+ }
+
+ /* adjust to a legal polling interval in Hz */
+ default: {
+ /* do we need to start internal polling? */
+ bool want_start = (_measure_ticks == 0);
+
+ /* convert hz to tick interval via microseconds */
+ unsigned ticks = USEC2TICK(1000000 / arg);
+
+ /* check against maximum rate */
+ if (ticks < USEC2TICK(CONVERSION_INTERVAL))
+ return -EINVAL;
+
+ /* update interval for next measurement */
+ _measure_ticks = ticks;
+
+ /* if we need to start the poll state machine, do it */
+ if (want_start)
+ start();
+
+ return OK;
+ }
+ }
+ }
+
+ case SENSORIOCGPOLLRATE:
+ if (_measure_ticks == 0)
+ return SENSOR_POLLRATE_MANUAL;
+
+ return (1000 / _measure_ticks);
+
+ case SENSORIOCSQUEUEDEPTH: {
+ /* add one to account for the sentinel in the ring */
+ arg++;
+
+ /* lower bound is mandatory, upper bound is a sanity check */
+ if ((arg < 2) || (arg > 100))
+ return -EINVAL;
+
+ /* allocate new buffer */
+ struct differential_pressure_s *buf = new struct differential_pressure_s[arg];
+
+ if (nullptr == buf)
+ return -ENOMEM;
+
+ /* reset the measurement state machine with the new buffer, free the old */
+ stop();
+ delete[] _reports;
+ _num_reports = arg;
+ _reports = buf;
+ start();
+
+ return OK;
+ }
+
+ case SENSORIOCGQUEUEDEPTH:
+ return _num_reports - 1;
+
+ case SENSORIOCRESET:
+ /* XXX implement this */
+ return -EINVAL;
+
+ default:
+ /* give it to the superclass */
+ return I2C::ioctl(filp, cmd, arg);
+ }
+}
+
+ssize_t
+ETSAirspeed::read(struct file *filp, char *buffer, size_t buflen)
+{
+ unsigned count = buflen / sizeof(struct differential_pressure_s);
+ int ret = 0;
+
+ /* buffer must be large enough */
+ if (count < 1)
+ return -ENOSPC;
+
+ /* if automatic measurement is enabled */
+ if (_measure_ticks > 0) {
+
+ /*
+ * While there is space in the caller's buffer, and reports, copy them.
+ * Note that we may be pre-empted by the workq thread while we are doing this;
+ * we are careful to avoid racing with them.
+ */
+ while (count--) {
+ if (_oldest_report != _next_report) {
+ memcpy(buffer, _reports + _oldest_report, sizeof(*_reports));
+ ret += sizeof(_reports[0]);
+ INCREMENT(_oldest_report, _num_reports);
+ }
+ }
+
+ /* if there was no data, warn the caller */
+ return ret ? ret : -EAGAIN;
+ }
+
+ /* manual measurement - run one conversion */
+ /* XXX really it'd be nice to lock against other readers here */
+ do {
+ _oldest_report = _next_report = 0;
+
+ /* trigger a measurement */
+ if (OK != measure()) {
+ ret = -EIO;
+ break;
+ }
+
+ /* wait for it to complete */
+ usleep(CONVERSION_INTERVAL);
+
+ /* run the collection phase */
+ if (OK != collect()) {
+ ret = -EIO;
+ break;
+ }
+
+ /* state machine will have generated a report, copy it out */
+ memcpy(buffer, _reports, sizeof(*_reports));
+ ret = sizeof(*_reports);
+
+ } while (0);
+
+ return ret;
+}
+
+int
+ETSAirspeed::measure()
+{
+ int ret;
+
+ /*
+ * Send the command to begin a measurement.
+ */
+ uint8_t cmd = READ_CMD;
+ ret = transfer(&cmd, 1, nullptr, 0);
+
+ if (OK != ret)
+ {
+ perf_count(_comms_errors);
+ log("i2c::transfer returned %d", ret);
+ return ret;
+ }
+ ret = OK;
+
+ return ret;
+}
+
+int
+ETSAirspeed::collect()
+{
+ int ret = -EIO;
+
+ /* read from the sensor */
+ uint8_t val[2] = {0, 0};
+
+ perf_begin(_sample_perf);
+
+ ret = transfer(nullptr, 0, &val[0], 2);
+
+ if (ret < 0) {
+ log("error reading from sensor: %d", ret);
+ return ret;
+ }
+
+ uint16_t diff_pres_pa = val[1] << 8 | val[0];
+
+ param_get(param_find("SENS_DPRES_OFF"), &_diff_pres_offset);
+
+ if (diff_pres_pa < _diff_pres_offset + MIN_ACCURATE_DIFF_PRES_PA) {
+ diff_pres_pa = 0;
+ } else {
+ diff_pres_pa -= _diff_pres_offset;
+ }
+
+ // XXX we may want to smooth out the readings to remove noise.
+
+ _reports[_next_report].timestamp = hrt_absolute_time();
+ _reports[_next_report].differential_pressure_pa = diff_pres_pa;
+
+ // Track maximum differential pressure measured (so we can work out top speed).
+ if (diff_pres_pa > _reports[_next_report].max_differential_pressure_pa) {
+ _reports[_next_report].max_differential_pressure_pa = diff_pres_pa;
+ }
+
+ /* announce the airspeed if needed, just publish else */
+ orb_publish(ORB_ID(differential_pressure), _airspeed_pub, &_reports[_next_report]);
+
+ /* post a report to the ring - note, not locked */
+ INCREMENT(_next_report, _num_reports);
+
+ /* if we are running up against the oldest report, toss it */
+ if (_next_report == _oldest_report) {
+ perf_count(_buffer_overflows);
+ INCREMENT(_oldest_report, _num_reports);
+ }
+
+ /* notify anyone waiting for data */
+ poll_notify(POLLIN);
+
+ ret = OK;
+
+ perf_end(_sample_perf);
+
+ return ret;
+}
+
+void
+ETSAirspeed::start()
+{
+ /* reset the report ring and state machine */
+ _collect_phase = false;
+ _oldest_report = _next_report = 0;
+
+ /* schedule a cycle to start things */
+ work_queue(HPWORK, &_work, (worker_t)&ETSAirspeed::cycle_trampoline, this, 1);
+
+ /* notify about state change */
+ struct subsystem_info_s info = {
+ true,
+ true,
+ true,
+ SUBSYSTEM_TYPE_DIFFPRESSURE};
+ static orb_advert_t pub = -1;
+
+ if (pub > 0) {
+ orb_publish(ORB_ID(subsystem_info), pub, &info);
+ } else {
+ pub = orb_advertise(ORB_ID(subsystem_info), &info);
+ }
+}
+
+void
+ETSAirspeed::stop()
+{
+ work_cancel(HPWORK, &_work);
+}
+
+void
+ETSAirspeed::cycle_trampoline(void *arg)
+{
+ ETSAirspeed *dev = (ETSAirspeed *)arg;
+
+ dev->cycle();
+}
+
+void
+ETSAirspeed::cycle()
+{
+ /* collection phase? */
+ if (_collect_phase) {
+
+ /* perform collection */
+ if (OK != collect()) {
+ log("collection error");
+ /* restart the measurement state machine */
+ start();
+ return;
+ }
+
+ /* next phase is measurement */
+ _collect_phase = false;
+
+ /*
+ * Is there a collect->measure gap?
+ */
+ if (_measure_ticks > USEC2TICK(CONVERSION_INTERVAL)) {
+
+ /* schedule a fresh cycle call when we are ready to measure again */
+ work_queue(HPWORK,
+ &_work,
+ (worker_t)&ETSAirspeed::cycle_trampoline,
+ this,
+ _measure_ticks - USEC2TICK(CONVERSION_INTERVAL));
+
+ return;
+ }
+ }
+
+ /* measurement phase */
+ if (OK != measure())
+ log("measure error");
+
+ /* next phase is collection */
+ _collect_phase = true;
+
+ /* schedule a fresh cycle call when the measurement is done */
+ work_queue(HPWORK,
+ &_work,
+ (worker_t)&ETSAirspeed::cycle_trampoline,
+ this,
+ USEC2TICK(CONVERSION_INTERVAL));
+}
+
+void
+ETSAirspeed::print_info()
+{
+ perf_print_counter(_sample_perf);
+ perf_print_counter(_comms_errors);
+ perf_print_counter(_buffer_overflows);
+ printf("poll interval: %u ticks\n", _measure_ticks);
+ printf("report queue: %u (%u/%u @ %p)\n",
+ _num_reports, _oldest_report, _next_report, _reports);
+}
+
+/**
+ * Local functions in support of the shell command.
+ */
+namespace ets_airspeed
+{
+
+/* oddly, ERROR is not defined for c++ */
+#ifdef ERROR
+# undef ERROR
+#endif
+const int ERROR = -1;
+
+ETSAirspeed *g_dev;
+
+void start(int i2c_bus);
+void stop();
+void test();
+void reset();
+void info();
+
+/**
+ * Start the driver.
+ */
+void
+start(int i2c_bus)
+{
+ int fd;
+
+ if (g_dev != nullptr)
+ errx(1, "already started");
+
+ /* create the driver */
+ g_dev = new ETSAirspeed(i2c_bus);
+
+ if (g_dev == nullptr)
+ goto fail;
+
+ if (OK != g_dev->init())
+ goto fail;
+
+ /* set the poll rate to default, starts automatic data collection */
+ fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);
+
+ if (fd < 0)
+ goto fail;
+
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
+ goto fail;
+
+ exit(0);
+
+fail:
+
+ if (g_dev != nullptr)
+ {
+ delete g_dev;
+ g_dev = nullptr;
+ }
+
+ errx(1, "driver start failed");
+}
+
+/**
+ * Stop the driver
+ */
+void
+stop()
+{
+ if (g_dev != nullptr)
+ {
+ delete g_dev;
+ g_dev = nullptr;
+ }
+ else
+ {
+ errx(1, "driver not running");
+ }
+ exit(0);
+}
+
+/**
+ * Perform some basic functional tests on the driver;
+ * make sure we can collect data from the sensor in polled
+ * and automatic modes.
+ */
+void
+test()
+{
+ struct differential_pressure_s report;
+ ssize_t sz;
+ int ret;
+
+ int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);
+
+ if (fd < 0)
+ err(1, "%s open failed (try 'ets_airspeed start' if the driver is not running", AIRSPEED_DEVICE_PATH);
+
+ /* do a simple demand read */
+ sz = read(fd, &report, sizeof(report));
+
+ if (sz != sizeof(report))
+ err(1, "immediate read failed");
+
+ warnx("single read");
+ warnx("diff pressure: %d pa", report.differential_pressure_pa);
+
+ /* start the sensor polling at 2Hz */
+ if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2))
+ errx(1, "failed to set 2Hz poll rate");
+
+ /* read the sensor 5x and report each value */
+ for (unsigned i = 0; i < 5; i++) {
+ struct pollfd fds;
+
+ /* wait for data to be ready */
+ fds.fd = fd;
+ fds.events = POLLIN;
+ ret = poll(&fds, 1, 2000);
+
+ if (ret != 1)
+ errx(1, "timed out waiting for sensor data");
+
+ /* now go get it */
+ sz = read(fd, &report, sizeof(report));
+
+ if (sz != sizeof(report))
+ err(1, "periodic read failed");
+
+ warnx("periodic read %u", i);
+ warnx("diff pressure: %d pa", report.differential_pressure_pa);
+ }
+
+ errx(0, "PASS");
+}
+
+/**
+ * Reset the driver.
+ */
+void
+reset()
+{
+ int fd = open(AIRSPEED_DEVICE_PATH, O_RDONLY);
+
+ if (fd < 0)
+ err(1, "failed ");
+
+ if (ioctl(fd, SENSORIOCRESET, 0) < 0)
+ err(1, "driver reset failed");
+
+ if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0)
+ err(1, "driver poll restart failed");
+
+ exit(0);
+}
+
+/**
+ * Print a little info about the driver.
+ */
+void
+info()
+{
+ if (g_dev == nullptr)
+ errx(1, "driver not running");
+
+ printf("state @ %p\n", g_dev);
+ g_dev->print_info();
+
+ exit(0);
+}
+
+} // namespace
+
+
+static void
+ets_airspeed_usage()
+{
+ fprintf(stderr, "usage: ets_airspeed [options] command\n");
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, "\t-b --bus i2cbus (%d)\n", PX4_I2C_BUS_DEFAULT);
+ fprintf(stderr, "command:\n");
+ fprintf(stderr, "\tstart|stop|reset|test|info\n");
+}
+
+int
+ets_airspeed_main(int argc, char *argv[])
+{
+ int i2c_bus = PX4_I2C_BUS_DEFAULT;
+
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--bus") == 0) {
+ if (argc > i + 1) {
+ i2c_bus = atoi(argv[i + 1]);
+ }
+ }
+ }
+
+ /*
+ * Start/load the driver.
+ */
+ if (!strcmp(argv[1], "start"))
+ ets_airspeed::start(i2c_bus);
+
+ /*
+ * Stop the driver
+ */
+ if (!strcmp(argv[1], "stop"))
+ ets_airspeed::stop();
+
+ /*
+ * Test the driver/device.
+ */
+ if (!strcmp(argv[1], "test"))
+ ets_airspeed::test();
+
+ /*
+ * Reset the driver.
+ */
+ if (!strcmp(argv[1], "reset"))
+ ets_airspeed::reset();
+
+ /*
+ * Print driver information.
+ */
+ if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status"))
+ ets_airspeed::info();
+
+ ets_airspeed_usage();
+ exit(0);
+}
diff --git a/src/drivers/ets_airspeed/module.mk b/src/drivers/ets_airspeed/module.mk
new file mode 100644
index 0000000000..cb5d3b1ed0
--- /dev/null
+++ b/src/drivers/ets_airspeed/module.mk
@@ -0,0 +1,41 @@
+############################################################################
+#
+# Copyright (c) 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Makefile to build the Eagle Tree Airspeed V3 driver.
+#
+
+MODULE_COMMAND = ets_airspeed
+MODULE_STACKSIZE = 1024
+
+SRCS = ets_airspeed.cpp
diff --git a/apps/drivers/gps/gps.cpp b/src/drivers/gps/gps.cpp
similarity index 96%
rename from apps/drivers/gps/gps.cpp
rename to src/drivers/gps/gps.cpp
index e35bdb944a..38835418b0 100644
--- a/apps/drivers/gps/gps.cpp
+++ b/src/drivers/gps/gps.cpp
@@ -285,6 +285,10 @@ GPS::task_main()
unlock();
if (_Helper->configure(_baudrate) == 0) {
unlock();
+
+ // GPS is obviously detected successfully, reset statistics
+ _Helper->reset_update_rates();
+
while (_Helper->receive(TIMEOUT_5HZ) > 0 && !_task_should_exit) {
// lock();
/* opportunistic publishing - else invalid data would end up on the bus */
@@ -301,6 +305,8 @@ GPS::task_main()
_rate = last_rate_count / ((float)((hrt_absolute_time() - last_rate_measurement)) / 1000000.0f);
last_rate_measurement = hrt_absolute_time();
last_rate_count = 0;
+ _Helper->store_update_rates();
+ _Helper->reset_update_rates();
}
if (!_healthy) {
@@ -372,7 +378,10 @@ GPS::print_info()
warnx("position lock: %dD, last update %4.2f seconds ago", (int)_report.fix_type,
(double)((float)(hrt_absolute_time() - _report.timestamp_position) / 1000000.0f));
warnx("lat: %d, lon: %d, alt: %d", _report.lat, _report.lon, _report.alt);
- warnx("update rate: %6.2f Hz", (double)_rate);
+ warnx("rate position: \t%6.2f Hz", (double)_Helper->get_position_update_rate());
+ warnx("rate velocity: \t%6.2f Hz", (double)_Helper->get_velocity_update_rate());
+ warnx("rate publication:\t%6.2f Hz", (double)_rate);
+
}
usleep(100000);
diff --git a/apps/drivers/gps/gps_helper.cpp b/src/drivers/gps/gps_helper.cpp
similarity index 82%
rename from apps/drivers/gps/gps_helper.cpp
rename to src/drivers/gps/gps_helper.cpp
index 9c1fad5691..ba86d370a8 100644
--- a/apps/drivers/gps/gps_helper.cpp
+++ b/src/drivers/gps/gps_helper.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
+ * Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
* Author: Thomas Gubler
* Julian Oes
*
@@ -36,9 +36,39 @@
#include
#include
#include
+#include
#include "gps_helper.h"
-/* @file gps_helper.cpp */
+/**
+ * @file gps_helper.cpp
+ */
+
+float
+GPS_Helper::get_position_update_rate()
+{
+ return _rate_lat_lon;
+}
+
+float
+GPS_Helper::get_velocity_update_rate()
+{
+ return _rate_vel;
+}
+
+float
+GPS_Helper::reset_update_rates()
+{
+ _rate_count_vel = 0;
+ _rate_count_lat_lon = 0;
+ _interval_rate_start = hrt_absolute_time();
+}
+
+float
+GPS_Helper::store_update_rates()
+{
+ _rate_vel = _rate_count_vel / (((float)(hrt_absolute_time() - _interval_rate_start)) / 1000000.0f);
+ _rate_lat_lon = _rate_count_lat_lon / (((float)(hrt_absolute_time() - _interval_rate_start)) / 1000000.0f);
+}
int
GPS_Helper::set_baudrate(const int &fd, unsigned baud)
diff --git a/apps/drivers/gps/gps_helper.h b/src/drivers/gps/gps_helper.h
similarity index 80%
rename from apps/drivers/gps/gps_helper.h
rename to src/drivers/gps/gps_helper.h
index f3d3bc40b3..defc1a074a 100644
--- a/apps/drivers/gps/gps_helper.h
+++ b/src/drivers/gps/gps_helper.h
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2008-2013 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
* Author: Thomas Gubler
* Julian Oes
*
@@ -33,7 +33,9 @@
*
****************************************************************************/
-/* @file gps_helper.h */
+/**
+ * @file gps_helper.h
+ */
#ifndef GPS_HELPER_H
#define GPS_HELPER_H
@@ -44,9 +46,22 @@
class GPS_Helper
{
public:
- virtual int configure(unsigned &baud) = 0;
+ virtual int configure(unsigned &baud) = 0;
virtual int receive(unsigned timeout) = 0;
- int set_baudrate(const int &fd, unsigned baud);
+ int set_baudrate(const int &fd, unsigned baud);
+ float get_position_update_rate();
+ float get_velocity_update_rate();
+ float reset_update_rates();
+ float store_update_rates();
+
+protected:
+ uint8_t _rate_count_lat_lon;
+ uint8_t _rate_count_vel;
+
+ float _rate_lat_lon;
+ float _rate_vel;
+
+ uint64_t _interval_rate_start;
};
#endif /* GPS_HELPER_H */
diff --git a/apps/drivers/gps/Makefile b/src/drivers/gps/module.mk
similarity index 91%
rename from apps/drivers/gps/Makefile
rename to src/drivers/gps/module.mk
index 3859a88a5a..097db2abfc 100644
--- a/apps/drivers/gps/Makefile
+++ b/src/drivers/gps/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -35,8 +35,9 @@
# GPS driver
#
-APPNAME = gps
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = gps
-include $(APPDIR)/mk/app.mk
+SRCS = gps.cpp \
+ gps_helper.cpp \
+ mtk.cpp \
+ ubx.cpp
diff --git a/apps/drivers/gps/mtk.cpp b/src/drivers/gps/mtk.cpp
similarity index 98%
rename from apps/drivers/gps/mtk.cpp
rename to src/drivers/gps/mtk.cpp
index 4762bd503a..62941d74b3 100644
--- a/apps/drivers/gps/mtk.cpp
+++ b/src/drivers/gps/mtk.cpp
@@ -263,6 +263,10 @@ MTK::handle_message(gps_mtk_packet_t &packet)
_gps_position->time_gps_usec += timeinfo_conversion_temp * 1e3;
_gps_position->timestamp_position = _gps_position->timestamp_time = hrt_absolute_time();
+ // Position and velocity update always at the same time
+ _rate_count_vel++;
+ _rate_count_lat_lon++;
+
return;
}
diff --git a/apps/drivers/gps/mtk.h b/src/drivers/gps/mtk.h
similarity index 96%
rename from apps/drivers/gps/mtk.h
rename to src/drivers/gps/mtk.h
index d4e390b01b..b5cfbf0a6d 100644
--- a/apps/drivers/gps/mtk.h
+++ b/src/drivers/gps/mtk.h
@@ -87,14 +87,14 @@ class MTK : public GPS_Helper
public:
MTK(const int &fd, struct vehicle_gps_position_s *gps_position);
~MTK();
- int receive(unsigned timeout);
- int configure(unsigned &baudrate);
+ int receive(unsigned timeout);
+ int configure(unsigned &baudrate);
private:
/**
* Parse the binary MTK packet
*/
- int parse_char(uint8_t b, gps_mtk_packet_t &packet);
+ int parse_char(uint8_t b, gps_mtk_packet_t &packet);
/**
* Handle the package once it has arrived
diff --git a/apps/drivers/gps/ubx.cpp b/src/drivers/gps/ubx.cpp
similarity index 83%
rename from apps/drivers/gps/ubx.cpp
rename to src/drivers/gps/ubx.cpp
index 74cbc5aaf3..b3093b0f6f 100644
--- a/apps/drivers/gps/ubx.cpp
+++ b/src/drivers/gps/ubx.cpp
@@ -33,7 +33,14 @@
*
****************************************************************************/
-/* @file U-Blox protocol implementation */
+/**
+ * @file ubx.cpp
+ *
+ * U-Blox protocol implementation. Following u-blox 6/7 Receiver Description
+ * including Prototol Specification.
+ *
+ * @see http://www.u-blox.com/images/downloads/Product_Docs/u-blox6_ReceiverDescriptionProtocolSpec_%28GPS.G6-SW-10018%29.pdf
+ */
#include
#include
@@ -53,7 +60,8 @@
UBX::UBX(const int &fd, struct vehicle_gps_position_s *gps_position) :
_fd(fd),
_gps_position(gps_position),
-_waiting_for_ack(false)
+_waiting_for_ack(false),
+_disable_cmd_counter(0)
{
decode_init();
}
@@ -113,13 +121,15 @@ UBX::configure(unsigned &baudrate)
cfg_prt_packet.outProtoMask = UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK;
send_config_packet(_fd, (uint8_t*)&cfg_prt_packet, sizeof(cfg_prt_packet));
+
+ /* no ACK is expected here, but read the buffer anyway in case we actually get an ACK */
+ receive(UBX_CONFIG_TIMEOUT);
+
if (UBX_CFG_PRT_PAYLOAD_BAUDRATE != baudrate) {
set_baudrate(_fd, UBX_CFG_PRT_PAYLOAD_BAUDRATE);
baudrate = UBX_CFG_PRT_PAYLOAD_BAUDRATE;
}
- /* no ack is ecpected here, keep going configuring */
-
/* send a CFT-RATE message to define update rate */
type_gps_bin_cfg_rate_packet_t cfg_rate_packet;
memset(&cfg_rate_packet, 0, sizeof(cfg_rate_packet));
@@ -130,12 +140,12 @@ UBX::configure(unsigned &baudrate)
cfg_rate_packet.clsID = UBX_CLASS_CFG;
cfg_rate_packet.msgID = UBX_MESSAGE_CFG_RATE;
cfg_rate_packet.length = UBX_CFG_RATE_LENGTH;
- cfg_rate_packet.measRate = UBX_CFG_RATE_PAYLOAD_MEASRATE;
+ cfg_rate_packet.measRate = UBX_CFG_RATE_PAYLOAD_MEASINTERVAL;
cfg_rate_packet.navRate = UBX_CFG_RATE_PAYLOAD_NAVRATE;
cfg_rate_packet.timeRef = UBX_CFG_RATE_PAYLOAD_TIMEREF;
send_config_packet(_fd, (uint8_t*)&cfg_rate_packet, sizeof(cfg_rate_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
+ if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0) {
/* try next baudrate */
continue;
}
@@ -155,74 +165,41 @@ UBX::configure(unsigned &baudrate)
cfg_nav5_packet.fixMode = UBX_CFG_NAV5_PAYLOAD_FIXMODE;
send_config_packet(_fd, (uint8_t*)&cfg_nav5_packet, sizeof(cfg_nav5_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
+ if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0) {
/* try next baudrate */
continue;
}
- type_gps_bin_cfg_msg_packet_t cfg_msg_packet;
- memset(&cfg_msg_packet, 0, sizeof(cfg_msg_packet));
-
- _clsID_needed = UBX_CLASS_CFG;
- _msgID_needed = UBX_MESSAGE_CFG_MSG;
-
- cfg_msg_packet.clsID = UBX_CLASS_CFG;
- cfg_msg_packet.msgID = UBX_MESSAGE_CFG_MSG;
- cfg_msg_packet.length = UBX_CFG_MSG_LENGTH;
- /* Choose fast 5Hz rate for all messages except SVINFO which is big and not important */
- cfg_msg_packet.rate[1] = UBX_CFG_MSG_PAYLOAD_RATE1_5HZ;
-
- cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
- cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_POSLLH;
-
- send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
- /* try next baudrate */
- continue;
- }
-
- cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
- cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_TIMEUTC;
-
- send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
- /* try next baudrate */
- continue;
- }
-
- cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
- cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SVINFO;
- /* For satelites info 1Hz is enough */
- cfg_msg_packet.rate[1] = UBX_CFG_MSG_PAYLOAD_RATE1_1HZ;
-
- send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
- /* try next baudrate */
- continue;
- }
-
- cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
- cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_SOL;
-
- send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
- /* try next baudrate */
- continue;
- }
-
- cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
- cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_VELNED;
-
- send_config_packet(_fd, (uint8_t*)&cfg_msg_packet, sizeof(cfg_msg_packet));
- if (receive(UBX_CONFIG_TIMEOUT) < 0) {
- /* try next baudrate */
- continue;
- }
-// cfg_msg_packet.msgClass_payload = UBX_CLASS_NAV;
-// cfg_msg_packet.msgID_payload = UBX_MESSAGE_NAV_DOP;
-
-// cfg_msg_packet.msgClass_payload = UBX_CLASS_RXM;
-// cfg_msg_packet.msgID_payload = UBX_MESSAGE_RXM_SVSI;
+ configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_POSLLH,
+ UBX_CFG_MSG_PAYLOAD_RATE1_5HZ);
+ /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
+ configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_TIMEUTC,
+ 1);
+ // /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
+ configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_SOL,
+ 1);
+ // /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
+ configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_VELNED,
+ 1);
+ // /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
+ // configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_DOP,
+ // 0);
+ // /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
+ configure_message_rate(UBX_CLASS_NAV, UBX_MESSAGE_NAV_SVINFO,
+ 0);
+ // /* insist of receiving the ACK for this packet */
+ // if (wait_for_ack(UBX_CONFIG_TIMEOUT) < 0)
+ // continue;
_waiting_for_ack = false;
return 0;
@@ -230,6 +207,15 @@ UBX::configure(unsigned &baudrate)
return -1;
}
+int
+UBX::wait_for_ack(unsigned timeout)
+{
+ _waiting_for_ack = true;
+ int ret = receive(timeout);
+ _waiting_for_ack = false;
+ return ret;
+}
+
int
UBX::receive(unsigned timeout)
{
@@ -489,6 +475,8 @@ UBX::handle_message()
_gps_position->eph_m = (float)packet->hAcc * 1e-3f; // from mm to m
_gps_position->epv_m = (float)packet->vAcc * 1e-3f; // from mm to m
+ _rate_count_lat_lon++;
+
/* Add timestamp to finish the report */
_gps_position->timestamp_position = hrt_absolute_time();
/* only return 1 when new position is available */
@@ -631,18 +619,21 @@ UBX::handle_message()
}
case NAV_VELNED: {
-// printf("GOT NAV_VELNED MESSAGE\n");
if (!_waiting_for_ack) {
+ /* 35.15 NAV-VELNED (0x01 0x12) message (page 181 / 210 of reference manual */
gps_bin_nav_velned_packet_t *packet = (gps_bin_nav_velned_packet_t *) _rx_buffer;
_gps_position->vel_m_s = (float)packet->speed * 1e-2f;
- _gps_position->vel_n_m_s = (float)packet->velN * 1e-2f;
- _gps_position->vel_e_m_s = (float)packet->velE * 1e-2f;
- _gps_position->vel_d_m_s = (float)packet->velD * 1e-2f;
+ _gps_position->vel_n_m_s = (float)packet->velN * 1e-2f; /* NED NORTH velocity */
+ _gps_position->vel_e_m_s = (float)packet->velE * 1e-2f; /* NED EAST velocity */
+ _gps_position->vel_d_m_s = (float)packet->velD * 1e-2f; /* NED DOWN velocity */
_gps_position->cog_rad = (float)packet->heading * M_DEG_TO_RAD_F * 1e-5f;
+ _gps_position->c_variance_rad = (float)packet->cAcc * M_DEG_TO_RAD_F * 1e-5f;
_gps_position->vel_ned_valid = true;
_gps_position->timestamp_velocity = hrt_absolute_time();
+
+ _rate_count_vel++;
}
break;
@@ -683,6 +674,12 @@ UBX::handle_message()
default: //we don't know the message
warnx("UBX: Unknown message received: %d-%d\n",_message_class,_message_id);
+ if (_disable_cmd_counter++ == 0) {
+ // Don't attempt for every message to disable, some might not be disabled */
+ warnx("Disabling message 0x%02x 0x%02x", (unsigned)_message_class, (unsigned)_message_id);
+ configure_message_rate(_message_class, _message_id, 0);
+ }
+ return ret;
ret = -1;
break;
}
@@ -726,6 +723,25 @@ UBX::add_checksum_to_message(uint8_t* message, const unsigned length)
message[length-1] = ck_b;
}
+void
+UBX::add_checksum(uint8_t* message, const unsigned length, uint8_t &ck_a, uint8_t &ck_b)
+{
+ for (unsigned i = 0; i < length; i++) {
+ ck_a = ck_a + message[i];
+ ck_b = ck_b + ck_a;
+ }
+}
+
+void
+UBX::configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate)
+{
+ struct ubx_cfg_msg_rate msg;
+ msg.msg_class = msg_class;
+ msg.msg_id = msg_id;
+ msg.rate = rate;
+ send_message(CFG, UBX_MESSAGE_CFG_MSG, &msg, sizeof(msg));
+}
+
void
UBX::send_config_packet(const int &fd, uint8_t *packet, const unsigned length)
{
@@ -743,3 +759,27 @@ UBX::send_config_packet(const int &fd, uint8_t *packet, const unsigned length)
if (ret != (int)length + (int)sizeof(sync_bytes)) // XXX is there a neater way to get rid of the unsigned signed warning?
warnx("ubx: config write fail");
}
+
+void
+UBX::send_message(uint8_t msg_class, uint8_t msg_id, void *msg, uint8_t size)
+{
+ struct ubx_header header;
+ uint8_t ck_a=0, ck_b=0;
+ header.sync1 = UBX_SYNC1;
+ header.sync2 = UBX_SYNC2;
+ header.msg_class = msg_class;
+ header.msg_id = msg_id;
+ header.length = size;
+
+ add_checksum((uint8_t *)&header.msg_class, sizeof(header)-2, ck_a, ck_b);
+ add_checksum((uint8_t *)msg, size, ck_a, ck_b);
+
+ // Configure receive check
+ _clsID_needed = msg_class;
+ _msgID_needed = msg_id;
+
+ write(_fd, (const char *)&header, sizeof(header));
+ write(_fd, (const char *)msg, size);
+ write(_fd, (const char *)&ck_a, 1);
+ write(_fd, (const char *)&ck_b, 1);
+}
diff --git a/apps/drivers/gps/ubx.h b/src/drivers/gps/ubx.h
similarity index 85%
rename from apps/drivers/gps/ubx.h
rename to src/drivers/gps/ubx.h
index e3dd1c7ea9..5a433642ce 100644
--- a/apps/drivers/gps/ubx.h
+++ b/src/drivers/gps/ubx.h
@@ -65,26 +65,27 @@
#define UBX_MESSAGE_CFG_RATE 0x08
#define UBX_CFG_PRT_LENGTH 20
-#define UBX_CFG_PRT_PAYLOAD_PORTID 0x01 /**< UART1 */
-#define UBX_CFG_PRT_PAYLOAD_MODE 0x000008D0 /**< 0b0000100011010000: 8N1 */
-#define UBX_CFG_PRT_PAYLOAD_BAUDRATE 38400 /**< always choose 38400 as GPS baudrate */
-#define UBX_CFG_PRT_PAYLOAD_INPROTOMASK 0x01 /**< UBX in */
-#define UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK 0x01 /**< UBX out */
+#define UBX_CFG_PRT_PAYLOAD_PORTID 0x01 /**< UART1 */
+#define UBX_CFG_PRT_PAYLOAD_MODE 0x000008D0 /**< 0b0000100011010000: 8N1 */
+#define UBX_CFG_PRT_PAYLOAD_BAUDRATE 38400 /**< always choose 38400 as GPS baudrate */
+#define UBX_CFG_PRT_PAYLOAD_INPROTOMASK 0x01 /**< UBX in */
+#define UBX_CFG_PRT_PAYLOAD_OUTPROTOMASK 0x01 /**< UBX out */
#define UBX_CFG_RATE_LENGTH 6
-#define UBX_CFG_RATE_PAYLOAD_MEASRATE 200 /**< 200ms for 5Hz */
+#define UBX_CFG_RATE_PAYLOAD_MEASINTERVAL 200 /**< 200ms for 5Hz */
#define UBX_CFG_RATE_PAYLOAD_NAVRATE 1 /**< cannot be changed */
#define UBX_CFG_RATE_PAYLOAD_TIMEREF 0 /**< 0: UTC, 1: GPS time */
#define UBX_CFG_NAV5_LENGTH 36
-#define UBX_CFG_NAV5_PAYLOAD_MASK 0x0001 /**< only update dynamic model and fix mode */
+#define UBX_CFG_NAV5_PAYLOAD_MASK 0x0005 /**< XXX only update dynamic model and fix mode */
#define UBX_CFG_NAV5_PAYLOAD_DYNMODEL 7 /**< 0: portable, 2: stationary, 3: pedestrian, 4: automotive, 5: sea, 6: airborne <1g, 7: airborne <2g, 8: airborne <4g */
-#define UBX_CFG_NAV5_PAYLOAD_FIXMODE 2 /**< 1: 2D only, 2: 3D only, 3: Auto 2D/3D */
+#define UBX_CFG_NAV5_PAYLOAD_FIXMODE 2 /**< 1: 2D only, 2: 3D only, 3: Auto 2D/3D */
#define UBX_CFG_MSG_LENGTH 8
#define UBX_CFG_MSG_PAYLOAD_RATE1_5HZ 0x01 /**< {0x00, 0x01, 0x00, 0x00, 0x00, 0x00} the second entry is for UART1 */
#define UBX_CFG_MSG_PAYLOAD_RATE1_1HZ 0x05 /**< {0x00, 0x05, 0x00, 0x00, 0x00, 0x00} the second entry is for UART1 */
+#define UBX_CFG_MSG_PAYLOAD_RATE1_05HZ 10
#define UBX_MAX_PAYLOAD_LENGTH 500
@@ -92,6 +93,14 @@
/** the structures of the binary packets */
#pragma pack(push, 1)
+struct ubx_header {
+ uint8_t sync1;
+ uint8_t sync2;
+ uint8_t msg_class;
+ uint8_t msg_id;
+ uint16_t length;
+};
+
typedef struct {
uint32_t time_milliseconds; /**< GPS Millisecond Time of Week */
int32_t lon; /**< Longitude * 1e-7, deg */
@@ -274,11 +283,17 @@ typedef struct {
uint16_t length;
uint8_t msgClass_payload;
uint8_t msgID_payload;
- uint8_t rate[6];
+ uint8_t rate;
uint8_t ck_a;
uint8_t ck_b;
} type_gps_bin_cfg_msg_packet_t;
+struct ubx_cfg_msg_rate {
+ uint8_t msg_class;
+ uint8_t msg_id;
+ uint8_t rate;
+};
+
// END the structures of the binary packets
// ************
@@ -341,55 +356,64 @@ class UBX : public GPS_Helper
public:
UBX(const int &fd, struct vehicle_gps_position_s *gps_position);
~UBX();
- int receive(unsigned timeout);
- int configure(unsigned &baudrate);
+ int receive(unsigned timeout);
+ int configure(unsigned &baudrate);
private:
/**
* Parse the binary MTK packet
*/
- int parse_char(uint8_t b);
+ int parse_char(uint8_t b);
/**
* Handle the package once it has arrived
*/
- int handle_message(void);
+ int handle_message(void);
/**
* Reset the parse state machine for a fresh start
*/
- void decode_init(void);
+ void decode_init(void);
/**
* While parsing add every byte (except the sync bytes) to the checksum
*/
- void add_byte_to_checksum(uint8_t);
+ void add_byte_to_checksum(uint8_t);
/**
* Add the two checksum bytes to an outgoing message
*/
- void add_checksum_to_message(uint8_t* message, const unsigned length);
+ void add_checksum_to_message(uint8_t* message, const unsigned length);
/**
* Helper to send a config packet
*/
- void send_config_packet(const int &fd, uint8_t *packet, const unsigned length);
+ void send_config_packet(const int &fd, uint8_t *packet, const unsigned length);
- int _fd;
+ void configure_message_rate(uint8_t msg_class, uint8_t msg_id, uint8_t rate);
+
+ void send_message(uint8_t msg_class, uint8_t msg_id, void *msg, uint8_t size);
+
+ void add_checksum(uint8_t* message, const unsigned length, uint8_t &ck_a, uint8_t &ck_b);
+
+ int wait_for_ack(unsigned timeout);
+
+ int _fd;
struct vehicle_gps_position_s *_gps_position;
ubx_config_state_t _config_state;
- bool _waiting_for_ack;
- uint8_t _clsID_needed;
- uint8_t _msgID_needed;
+ bool _waiting_for_ack;
+ uint8_t _clsID_needed;
+ uint8_t _msgID_needed;
ubx_decode_state_t _decode_state;
- uint8_t _rx_buffer[RECV_BUFFER_SIZE];
- unsigned _rx_count;
- uint8_t _rx_ck_a;
- uint8_t _rx_ck_b;
- ubx_message_class_t _message_class;
+ uint8_t _rx_buffer[RECV_BUFFER_SIZE];
+ unsigned _rx_count;
+ uint8_t _rx_ck_a;
+ uint8_t _rx_ck_b;
+ ubx_message_class_t _message_class;
ubx_message_id_t _message_id;
- unsigned _payload_size;
+ unsigned _payload_size;
+ uint8_t _disable_cmd_counter;
};
#endif /* UBX_H_ */
diff --git a/apps/drivers/hil/hil.cpp b/src/drivers/hil/hil.cpp
similarity index 100%
rename from apps/drivers/hil/hil.cpp
rename to src/drivers/hil/hil.cpp
diff --git a/src/drivers/hil/module.mk b/src/drivers/hil/module.mk
new file mode 100644
index 0000000000..f8895f5d5a
--- /dev/null
+++ b/src/drivers/hil/module.mk
@@ -0,0 +1,40 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Hardware in the Loop (HIL) simulation actuator output bank
+#
+
+MODULE_COMMAND = hil
+
+SRCS = hil.cpp
diff --git a/apps/drivers/hmc5883/hmc5883.cpp b/src/drivers/hmc5883/hmc5883.cpp
similarity index 95%
rename from apps/drivers/hmc5883/hmc5883.cpp
rename to src/drivers/hmc5883/hmc5883.cpp
index 8ab5682821..78eda327c3 100644
--- a/apps/drivers/hmc5883/hmc5883.cpp
+++ b/src/drivers/hmc5883/hmc5883.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -75,7 +75,6 @@
* HMC5883 internal constants and data structures.
*/
-#define HMC5883L_BUS PX4_I2C_BUS_ONBOARD
#define HMC5883L_ADDRESS PX4_I2C_OBDEV_HMC5883
/* Max measurement rate is 160Hz */
@@ -842,12 +841,25 @@ HMC5883::collect()
* 74 from all measurements centers them around zero.
*/
- /* to align the sensor axes with the board, x and y need to be flipped */
- _reports[_next_report].x = ((report.y * _range_scale) - _scale.x_offset) * _scale.x_scale;
- /* flip axes and negate value for y */
- _reports[_next_report].y = ((((report.x == -32768) ? 32767 : -report.x) * _range_scale) - _scale.y_offset) * _scale.y_scale;
- /* z remains z */
- _reports[_next_report].z = ((report.z * _range_scale) - _scale.z_offset) * _scale.z_scale;
+#ifdef PX4_I2C_BUS_ONBOARD
+ if (_bus == PX4_I2C_BUS_ONBOARD) {
+ /* to align the sensor axes with the board, x and y need to be flipped */
+ _reports[_next_report].x = ((report.y * _range_scale) - _scale.x_offset) * _scale.x_scale;
+ /* flip axes and negate value for y */
+ _reports[_next_report].y = ((((report.x == -32768) ? 32767 : -report.x) * _range_scale) - _scale.y_offset) * _scale.y_scale;
+ /* z remains z */
+ _reports[_next_report].z = ((report.z * _range_scale) - _scale.z_offset) * _scale.z_scale;
+ } else {
+#endif
+ /* XXX axis assignment of external sensor is yet unknown */
+ _reports[_next_report].x = ((report.y * _range_scale) - _scale.x_offset) * _scale.x_scale;
+ /* flip axes and negate value for y */
+ _reports[_next_report].y = ((((report.x == -32768) ? 32767 : -report.x) * _range_scale) - _scale.y_offset) * _scale.y_scale;
+ /* z remains z */
+ _reports[_next_report].z = ((report.z * _range_scale) - _scale.z_offset) * _scale.z_scale;
+#ifdef PX4_I2C_BUS_ONBOARD
+ }
+#endif
/* publish it */
orb_publish(ORB_ID(sensor_mag), _mag_topic, &_reports[_next_report]);
@@ -1211,15 +1223,27 @@ start()
if (g_dev != nullptr)
errx(1, "already started");
- /* create the driver */
- g_dev = new HMC5883(HMC5883L_BUS);
+ /* create the driver, attempt expansion bus first */
+ g_dev = new HMC5883(PX4_I2C_BUS_EXPANSION);
+ if (g_dev != nullptr && OK != g_dev->init()) {
+ delete g_dev;
+ g_dev = nullptr;
+ }
+
+
+#ifdef PX4_I2C_BUS_ONBOARD
+ /* if this failed, attempt onboard sensor */
+ if (g_dev == nullptr) {
+ g_dev = new HMC5883(PX4_I2C_BUS_ONBOARD);
+ if (g_dev != nullptr && OK != g_dev->init()) {
+ goto fail;
+ }
+ }
+#endif
if (g_dev == nullptr)
goto fail;
- if (OK != g_dev->init())
- goto fail;
-
/* set the poll rate to default, starts automatic data collection */
fd = open(MAG_DEVICE_PATH, O_RDONLY);
diff --git a/apps/drivers/hil/Makefile b/src/drivers/hmc5883/module.mk
similarity index 88%
rename from apps/drivers/hil/Makefile
rename to src/drivers/hmc5883/module.mk
index 1fb6e37bce..07377556d3 100644
--- a/apps/drivers/hil/Makefile
+++ b/src/drivers/hmc5883/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,11 +32,12 @@
############################################################################
#
-# Interface driver for the PX4FMU board
+# HMC5883 driver
#
-APPNAME = hil
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = hmc5883
-include $(APPDIR)/mk/app.mk
+# XXX seems excessive, check if 2048 is sufficient
+MODULE_STACKSIZE = 4096
+
+SRCS = hmc5883.cpp
diff --git a/apps/hott_telemetry/hott_telemetry_main.c b/src/drivers/hott_telemetry/hott_telemetry_main.c
similarity index 96%
rename from apps/hott_telemetry/hott_telemetry_main.c
rename to src/drivers/hott_telemetry/hott_telemetry_main.c
index 31c9247aa5..a13a6ef589 100644
--- a/apps/hott_telemetry/hott_telemetry_main.c
+++ b/src/drivers/hott_telemetry/hott_telemetry_main.c
@@ -1,7 +1,7 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
- * Author: @author Simon Wilks
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+ * Author: Simon Wilks
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
/**
* @file hott_telemetry_main.c
+ * @author Simon Wilks
*
* Graupner HoTT Telemetry implementation.
*
@@ -41,7 +42,6 @@
* a data packet can be returned if necessary.
*
* TODO: Add support for at least the vario and GPS sensor data.
- *
*/
#include
@@ -57,12 +57,6 @@
#include "messages.h"
-/* The following are equired for UART direct manipulation. */
-#include
-#include "up_arch.h"
-#include "chip.h"
-#include "stm32_internal.h"
-
static int thread_should_exit = false; /**< Deamon exit flag */
static int thread_running = false; /**< Deamon status flag */
static int deamon_task; /**< Handle of deamon task / thread */
diff --git a/apps/hott_telemetry/messages.c b/src/drivers/hott_telemetry/messages.c
similarity index 83%
rename from apps/hott_telemetry/messages.c
rename to src/drivers/hott_telemetry/messages.c
index 8bfb997737..f0f32d2443 100644
--- a/apps/hott_telemetry/messages.c
+++ b/src/drivers/hott_telemetry/messages.c
@@ -1,7 +1,7 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
- * Author: @author Simon Wilks
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+ * Author: Simon Wilks
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@
/**
* @file messages.c
- *
+ * @author Simon Wilks
*/
#include "messages.h"
@@ -42,9 +42,11 @@
#include
#include
#include
+#include
#include
#include
+static int airspeed_sub = -1;
static int battery_sub = -1;
static int sensor_sub = -1;
@@ -52,6 +54,7 @@ void messages_init(void)
{
battery_sub = orb_subscribe(ORB_ID(battery_status));
sensor_sub = orb_subscribe(ORB_ID(sensor_combined));
+ airspeed_sub = orb_subscribe(ORB_ID(airspeed));
}
void build_eam_response(uint8_t *buffer, int *size)
@@ -81,6 +84,15 @@ void build_eam_response(uint8_t *buffer, int *size)
msg.altitude_L = (uint8_t)alt & 0xff;
msg.altitude_H = (uint8_t)(alt >> 8) & 0xff;
+ /* get a local copy of the current sensor values */
+ struct airspeed_s airspeed;
+ memset(&airspeed, 0, sizeof(airspeed));
+ orb_copy(ORB_ID(airspeed), airspeed_sub, &airspeed);
+
+ uint16_t speed = (uint16_t)(airspeed.indicated_airspeed_m_s * 3.6);
+ msg.speed_L = (uint8_t)speed & 0xff;
+ msg.speed_H = (uint8_t)(speed >> 8) & 0xff;
+
msg.stop = STOP_BYTE;
memcpy(buffer, &msg, *size);
diff --git a/apps/hott_telemetry/messages.h b/src/drivers/hott_telemetry/messages.h
similarity index 96%
rename from apps/hott_telemetry/messages.h
rename to src/drivers/hott_telemetry/messages.h
index 44001e04f0..dd38075fa8 100644
--- a/apps/hott_telemetry/messages.h
+++ b/src/drivers/hott_telemetry/messages.h
@@ -1,7 +1,7 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
- * Author: @author Simon Wilks
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+ * Author: Simon Wilks
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
/**
* @file messages.h
+ * @author Simon Wilks
*
* Graupner HoTT Telemetry message generation.
*
diff --git a/apps/drivers/blinkm/Makefile b/src/drivers/hott_telemetry/module.mk
similarity index 89%
rename from apps/drivers/blinkm/Makefile
rename to src/drivers/hott_telemetry/module.mk
index 5a623693df..def1d59e9b 100644
--- a/apps/drivers/blinkm/Makefile
+++ b/src/drivers/hott_telemetry/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,11 +32,10 @@
############################################################################
#
-# BlinkM I2C LED driver
+# Graupner HoTT Telemetry application.
#
-APPNAME = blinkm
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = hott_telemetry
-include $(APPDIR)/mk/app.mk
+SRCS = hott_telemetry_main.c \
+ messages.c
diff --git a/apps/drivers/l3gd20/l3gd20.cpp b/src/drivers/l3gd20/l3gd20.cpp
similarity index 98%
rename from apps/drivers/l3gd20/l3gd20.cpp
rename to src/drivers/l3gd20/l3gd20.cpp
index 6227df72aa..98098c83bf 100644
--- a/apps/drivers/l3gd20/l3gd20.cpp
+++ b/src/drivers/l3gd20/l3gd20.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,8 @@
****************************************************************************/
/**
- * @file Driver for the ST L3GD20 MEMS gyro connected via SPI.
+ * @file l3gd20.cpp
+ * Driver for the ST L3GD20 MEMS gyro connected via SPI.
*/
#include
@@ -684,9 +685,10 @@ L3GD20::measure()
* 74 from all measurements centers them around zero.
*/
report->timestamp = hrt_absolute_time();
- /* XXX adjust for sensor alignment to board here */
- report->x_raw = raw_report.x;
- report->y_raw = raw_report.y;
+
+ /* swap x and y and negate y */
+ report->x_raw = raw_report.y;
+ report->y_raw = ((raw_report.x == -32768) ? 32767 : -raw_report.x);
report->z_raw = raw_report.z;
report->x = ((report->x_raw * _gyro_range_scale) - _gyro_scale.x_offset) * _gyro_scale.x_scale;
diff --git a/src/drivers/l3gd20/module.mk b/src/drivers/l3gd20/module.mk
new file mode 100644
index 0000000000..23e77e8712
--- /dev/null
+++ b/src/drivers/l3gd20/module.mk
@@ -0,0 +1,6 @@
+#
+# LSM303D accel/mag driver
+#
+
+MODULE_COMMAND = l3gd20
+SRCS = l3gd20.cpp
diff --git a/apps/drivers/led/led.cpp b/src/drivers/led/led.cpp
similarity index 86%
rename from apps/drivers/led/led.cpp
rename to src/drivers/led/led.cpp
index c7c45525e1..04b565358c 100644
--- a/apps/drivers/led/led.cpp
+++ b/src/drivers/led/led.cpp
@@ -41,12 +41,17 @@
#include
#include
-/* Ideally we'd be able to get these from up_internal.h */
-//#include
+/*
+ * Ideally we'd be able to get these from up_internal.h,
+ * but since we want to be able to disable the NuttX use
+ * of leds for system indication at will and there is no
+ * separate switch, we need to build independent of the
+ * CONFIG_ARCH_LEDS configuration switch.
+ */
__BEGIN_DECLS
-extern void up_ledinit();
-extern void up_ledon(int led);
-extern void up_ledoff(int led);
+extern void led_init();
+extern void led_on(int led);
+extern void led_off(int led);
__END_DECLS
class LED : device::CDev
@@ -74,7 +79,7 @@ int
LED::init()
{
CDev::init();
- up_ledinit();
+ led_init();
return 0;
}
@@ -86,11 +91,11 @@ LED::ioctl(struct file *filp, int cmd, unsigned long arg)
switch (cmd) {
case LED_ON:
- up_ledon(arg);
+ led_on(arg);
break;
case LED_OFF:
- up_ledoff(arg);
+ led_off(arg);
break;
default:
diff --git a/apps/systemlib/mixer/Makefile b/src/drivers/led/module.mk
similarity index 92%
rename from apps/systemlib/mixer/Makefile
rename to src/drivers/led/module.mk
index f8b02f1941..777f3e4425 100644
--- a/apps/systemlib/mixer/Makefile
+++ b/src/drivers/led/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,8 +32,7 @@
############################################################################
#
-# mixer library
+# Build the LED driver.
#
-LIBNAME = mixerlib
-include $(APPDIR)/mk/app.mk
+SRCS = led.cpp
diff --git a/apps/drivers/mb12xx/mb12xx.cpp b/src/drivers/mb12xx/mb12xx.cpp
similarity index 99%
rename from apps/drivers/mb12xx/mb12xx.cpp
rename to src/drivers/mb12xx/mb12xx.cpp
index 9d0f6bddcf..397686e8bf 100644
--- a/apps/drivers/mb12xx/mb12xx.cpp
+++ b/src/drivers/mb12xx/mb12xx.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2013 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/apps/drivers/mb12xx/Makefile b/src/drivers/mb12xx/module.mk
similarity index 91%
rename from apps/drivers/mb12xx/Makefile
rename to src/drivers/mb12xx/module.mk
index 0d24057877..4e00ada025 100644
--- a/apps/drivers/mb12xx/Makefile
+++ b/src/drivers/mb12xx/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2013 PX4 Development Team. All rights reserved.
+# Copyright (c) 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -35,8 +35,6 @@
# Makefile to build the Maxbotix Sonar driver.
#
-APPNAME = mb12xx
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = mb12xx
-include $(APPDIR)/mk/app.mk
+SRCS = mb12xx.cpp
diff --git a/src/drivers/md25/md25.cpp b/src/drivers/md25/md25.cpp
new file mode 100644
index 0000000000..71932ad65d
--- /dev/null
+++ b/src/drivers/md25/md25.cpp
@@ -0,0 +1,553 @@
+/****************************************************************************
+ *
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file md25.cpp
+ *
+ * Driver for MD25 I2C Motor Driver
+ *
+ * references:
+ * http://www.robot-electronics.co.uk/htm/md25tech.htm
+ * http://www.robot-electronics.co.uk/files/rpi_md25.c
+ *
+ */
+
+#include "md25.hpp"
+#include
+#include
+
+#include
+#include
+
+// registers
+enum {
+ // RW: read/write
+ // R: read
+ REG_SPEED1_RW = 0,
+ REG_SPEED2_RW,
+ REG_ENC1A_R,
+ REG_ENC1B_R,
+ REG_ENC1C_R,
+ REG_ENC1D_R,
+ REG_ENC2A_R,
+ REG_ENC2B_R,
+ REG_ENC2C_R,
+ REG_ENC2D_R,
+ REG_BATTERY_VOLTS_R,
+ REG_MOTOR1_CURRENT_R,
+ REG_MOTOR2_CURRENT_R,
+ REG_SW_VERSION_R,
+ REG_ACCEL_RATE_RW,
+ REG_MODE_RW,
+ REG_COMMAND_RW,
+};
+
+MD25::MD25(const char *deviceName, int bus,
+ uint16_t address, uint32_t speed) :
+ I2C("MD25", deviceName, bus, address, speed),
+ _controlPoll(),
+ _actuators(NULL, ORB_ID(actuator_controls_0), 20),
+ _version(0),
+ _motor1Speed(0),
+ _motor2Speed(0),
+ _revolutions1(0),
+ _revolutions2(0),
+ _batteryVoltage(0),
+ _motor1Current(0),
+ _motor2Current(0),
+ _motorAccel(0),
+ _mode(MODE_UNSIGNED_SPEED),
+ _command(CMD_RESET_ENCODERS)
+{
+ // setup control polling
+ _controlPoll.fd = _actuators.getHandle();
+ _controlPoll.events = POLLIN;
+
+ // if initialization fails raise an error, unless
+ // probing
+ int ret = I2C::init();
+
+ if (ret != OK) {
+ warnc(ret, "I2C::init failed for bus: %d address: %d\n", bus, address);
+ }
+
+ // setup default settings, reset encoders
+ setMotor1Speed(0);
+ setMotor2Speed(0);
+ resetEncoders();
+ _setMode(MD25::MODE_UNSIGNED_SPEED);
+ setSpeedRegulation(true);
+ setTimeout(true);
+}
+
+MD25::~MD25()
+{
+}
+
+int MD25::readData()
+{
+ uint8_t sendBuf[1];
+ sendBuf[0] = REG_SPEED1_RW;
+ uint8_t recvBuf[17];
+ int ret = transfer(sendBuf, sizeof(sendBuf),
+ recvBuf, sizeof(recvBuf));
+
+ if (ret == OK) {
+ _version = recvBuf[REG_SW_VERSION_R];
+ _motor1Speed = _uint8ToNorm(recvBuf[REG_SPEED1_RW]);
+ _motor2Speed = _uint8ToNorm(recvBuf[REG_SPEED2_RW]);
+ _revolutions1 = -int32_t((recvBuf[REG_ENC1A_R] << 24) +
+ (recvBuf[REG_ENC1B_R] << 16) +
+ (recvBuf[REG_ENC1C_R] << 8) +
+ recvBuf[REG_ENC1D_R]) / 360.0;
+ _revolutions2 = -int32_t((recvBuf[REG_ENC2A_R] << 24) +
+ (recvBuf[REG_ENC2B_R] << 16) +
+ (recvBuf[REG_ENC2C_R] << 8) +
+ recvBuf[REG_ENC2D_R]) / 360.0;
+ _batteryVoltage = recvBuf[REG_BATTERY_VOLTS_R] / 10.0;
+ _motor1Current = recvBuf[REG_MOTOR1_CURRENT_R] / 10.0;
+ _motor2Current = recvBuf[REG_MOTOR2_CURRENT_R] / 10.0;
+ _motorAccel = recvBuf[REG_ACCEL_RATE_RW];
+ _mode = e_mode(recvBuf[REG_MODE_RW]);
+ _command = e_cmd(recvBuf[REG_COMMAND_RW]);
+ }
+
+ return ret;
+}
+
+void MD25::status(char *string, size_t n)
+{
+ snprintf(string, n,
+ "version:\t%10d\n" \
+ "motor 1 speed:\t%10.2f\n" \
+ "motor 2 speed:\t%10.2f\n" \
+ "revolutions 1:\t%10.2f\n" \
+ "revolutions 2:\t%10.2f\n" \
+ "battery volts :\t%10.2f\n" \
+ "motor 1 current :\t%10.2f\n" \
+ "motor 2 current :\t%10.2f\n" \
+ "motor accel :\t%10d\n" \
+ "mode :\t%10d\n" \
+ "command :\t%10d\n",
+ getVersion(),
+ double(getMotor1Speed()),
+ double(getMotor2Speed()),
+ double(getRevolutions1()),
+ double(getRevolutions2()),
+ double(getBatteryVolts()),
+ double(getMotor1Current()),
+ double(getMotor2Current()),
+ getMotorAccel(),
+ getMode(),
+ getCommand());
+}
+
+uint8_t MD25::getVersion()
+{
+ return _version;
+}
+
+float MD25::getMotor1Speed()
+{
+ return _motor1Speed;
+}
+
+float MD25::getMotor2Speed()
+{
+ return _motor2Speed;
+}
+
+float MD25::getRevolutions1()
+{
+ return _revolutions1;
+}
+
+float MD25::getRevolutions2()
+{
+ return _revolutions2;
+}
+
+float MD25::getBatteryVolts()
+{
+ return _batteryVoltage;
+}
+
+float MD25::getMotor1Current()
+{
+ return _motor1Current;
+}
+float MD25::getMotor2Current()
+{
+ return _motor2Current;
+}
+
+uint8_t MD25::getMotorAccel()
+{
+ return _motorAccel;
+}
+
+MD25::e_mode MD25::getMode()
+{
+ return _mode;
+}
+
+MD25::e_cmd MD25::getCommand()
+{
+ return _command;
+}
+
+int MD25::resetEncoders()
+{
+ return _writeUint8(REG_COMMAND_RW,
+ CMD_RESET_ENCODERS);
+}
+
+int MD25::_setMode(e_mode mode)
+{
+ return _writeUint8(REG_MODE_RW,
+ mode);
+}
+
+int MD25::setSpeedRegulation(bool enable)
+{
+ if (enable) {
+ return _writeUint8(REG_COMMAND_RW,
+ CMD_ENABLE_SPEED_REGULATION);
+
+ } else {
+ return _writeUint8(REG_COMMAND_RW,
+ CMD_DISABLE_SPEED_REGULATION);
+ }
+}
+
+int MD25::setTimeout(bool enable)
+{
+ if (enable) {
+ return _writeUint8(REG_COMMAND_RW,
+ CMD_ENABLE_TIMEOUT);
+
+ } else {
+ return _writeUint8(REG_COMMAND_RW,
+ CMD_DISABLE_TIMEOUT);
+ }
+}
+
+int MD25::setDeviceAddress(uint8_t address)
+{
+ uint8_t sendBuf[1];
+ sendBuf[0] = CMD_CHANGE_I2C_SEQ_0;
+ int ret = OK;
+ ret = transfer(sendBuf, sizeof(sendBuf),
+ nullptr, 0);
+
+ if (ret != OK) {
+ warnc(ret, "MD25::setDeviceAddress");
+ return ret;
+ }
+
+ usleep(5000);
+ sendBuf[0] = CMD_CHANGE_I2C_SEQ_1;
+ ret = transfer(sendBuf, sizeof(sendBuf),
+ nullptr, 0);
+
+ if (ret != OK) {
+ warnc(ret, "MD25::setDeviceAddress");
+ return ret;
+ }
+
+ usleep(5000);
+ sendBuf[0] = CMD_CHANGE_I2C_SEQ_2;
+ ret = transfer(sendBuf, sizeof(sendBuf),
+ nullptr, 0);
+
+ if (ret != OK) {
+ warnc(ret, "MD25::setDeviceAddress");
+ return ret;
+ }
+
+ return OK;
+}
+
+int MD25::setMotor1Speed(float value)
+{
+ return _writeUint8(REG_SPEED1_RW,
+ _normToUint8(value));
+}
+
+int MD25::setMotor2Speed(float value)
+{
+ return _writeUint8(REG_SPEED2_RW,
+ _normToUint8(value));
+}
+
+void MD25::update()
+{
+ // wait for an actuator publication,
+ // check for exit condition every second
+ // note "::poll" is required to distinguish global
+ // poll from member function for driver
+ if (::poll(&_controlPoll, 1, 1000) < 0) return; // poll error
+
+ // if new data, send to motors
+ if (_actuators.updated()) {
+ _actuators.update();
+ setMotor1Speed(_actuators.control[CH_SPEED_LEFT]);
+ setMotor2Speed(_actuators.control[CH_SPEED_RIGHT]);
+ }
+}
+
+int MD25::probe()
+{
+ uint8_t goodAddress = 0;
+ bool found = false;
+ int ret = OK;
+
+ // try initial address first, if good, then done
+ if (readData() == OK) return ret;
+
+ // try all other addresses
+ uint8_t testAddress = 0;
+
+ //printf("searching for MD25 address\n");
+ while (true) {
+ set_address(testAddress);
+ ret = readData();
+
+ if (ret == OK && !found) {
+ //printf("device found at address: 0x%X\n", testAddress);
+ if (!found) {
+ found = true;
+ goodAddress = testAddress;
+ }
+ }
+
+ if (testAddress > 254) {
+ break;
+ }
+
+ testAddress++;
+ }
+
+ if (found) {
+ set_address(goodAddress);
+ return OK;
+
+ } else {
+ set_address(0);
+ return ret;
+ }
+}
+
+int MD25::search()
+{
+ uint8_t goodAddress = 0;
+ bool found = false;
+ int ret = OK;
+ // try all other addresses
+ uint8_t testAddress = 0;
+
+ //printf("searching for MD25 address\n");
+ while (true) {
+ set_address(testAddress);
+ ret = readData();
+
+ if (ret == OK && !found) {
+ printf("device found at address: 0x%X\n", testAddress);
+
+ if (!found) {
+ found = true;
+ goodAddress = testAddress;
+ }
+ }
+
+ if (testAddress > 254) {
+ break;
+ }
+
+ testAddress++;
+ }
+
+ if (found) {
+ set_address(goodAddress);
+ return OK;
+
+ } else {
+ set_address(0);
+ return ret;
+ }
+}
+
+int MD25::_writeUint8(uint8_t reg, uint8_t value)
+{
+ uint8_t sendBuf[2];
+ sendBuf[0] = reg;
+ sendBuf[1] = value;
+ return transfer(sendBuf, sizeof(sendBuf),
+ nullptr, 0);
+}
+
+int MD25::_writeInt8(uint8_t reg, int8_t value)
+{
+ uint8_t sendBuf[2];
+ sendBuf[0] = reg;
+ sendBuf[1] = value;
+ return transfer(sendBuf, sizeof(sendBuf),
+ nullptr, 0);
+}
+
+float MD25::_uint8ToNorm(uint8_t value)
+{
+ // TODO, should go from 0 to 255
+ // possibly should handle this differently
+ return (value - 128) / 127.0;
+}
+
+uint8_t MD25::_normToUint8(float value)
+{
+ if (value > 1) value = 1;
+
+ if (value < -1) value = -1;
+
+ // TODO, should go from 0 to 255
+ // possibly should handle this differently
+ return 127 * value + 128;
+}
+
+int md25Test(const char *deviceName, uint8_t bus, uint8_t address)
+{
+ printf("md25 test: starting\n");
+
+ // setup
+ MD25 md25("/dev/md25", bus, address);
+
+ // print status
+ char buf[200];
+ md25.status(buf, sizeof(buf));
+ printf("%s\n", buf);
+
+ // setup for test
+ md25.setSpeedRegulation(true);
+ md25.setTimeout(true);
+ float dt = 0.1;
+ float speed = 0.2;
+ float t = 0;
+
+ // motor 1 test
+ printf("md25 test: spinning motor 1 forward for 1 rev at 0.1 speed\n");
+ t = 0;
+
+ while (true) {
+ t += dt;
+ md25.setMotor1Speed(speed);
+ md25.readData();
+ usleep(1000000 * dt);
+
+ if (md25.getRevolutions1() > 1) {
+ printf("finished 1 revolution fwd\n");
+ break;
+ }
+
+ if (t > 2.0f) break;
+ }
+
+ md25.setMotor1Speed(0);
+ printf("revolution of wheel 1: %8.4f\n", double(md25.getRevolutions1()));
+ md25.resetEncoders();
+
+ t = 0;
+
+ while (true) {
+ t += dt;
+ md25.setMotor1Speed(-speed);
+ md25.readData();
+ usleep(1000000 * dt);
+
+ if (md25.getRevolutions1() < -1) {
+ printf("finished 1 revolution rev\n");
+ break;
+ }
+
+ if (t > 2.0f) break;
+ }
+
+ md25.setMotor1Speed(0);
+ printf("revolution of wheel 1: %8.4f\n", double(md25.getRevolutions1()));
+ md25.resetEncoders();
+
+ // motor 2 test
+ printf("md25 test: spinning motor 2 forward for 1 rev at 0.1 speed\n");
+ t = 0;
+
+ while (true) {
+ t += dt;
+ md25.setMotor2Speed(speed);
+ md25.readData();
+ usleep(1000000 * dt);
+
+ if (md25.getRevolutions2() > 1) {
+ printf("finished 1 revolution fwd\n");
+ break;
+ }
+
+ if (t > 2.0f) break;
+ }
+
+ md25.setMotor2Speed(0);
+ printf("revolution of wheel 2: %8.4f\n", double(md25.getRevolutions2()));
+ md25.resetEncoders();
+
+ t = 0;
+
+ while (true) {
+ t += dt;
+ md25.setMotor2Speed(-speed);
+ md25.readData();
+ usleep(1000000 * dt);
+
+ if (md25.getRevolutions2() < -1) {
+ printf("finished 1 revolution rev\n");
+ break;
+ }
+
+ if (t > 2.0f) break;
+ }
+
+ md25.setMotor2Speed(0);
+ printf("revolution of wheel 2: %8.4f\n", double(md25.getRevolutions2()));
+ md25.resetEncoders();
+
+ printf("Test complete\n");
+ return 0;
+}
+
+// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
diff --git a/src/drivers/md25/md25.hpp b/src/drivers/md25/md25.hpp
new file mode 100644
index 0000000000..e77511b163
--- /dev/null
+++ b/src/drivers/md25/md25.hpp
@@ -0,0 +1,293 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file md25.cpp
+ *
+ * Driver for MD25 I2C Motor Driver
+ *
+ * references:
+ * http://www.robot-electronics.co.uk/htm/md25tech.htm
+ * http://www.robot-electronics.co.uk/files/rpi_md25.c
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * This is a driver for the MD25 motor controller utilizing the I2C interface.
+ */
+class MD25 : public device::I2C
+{
+public:
+
+ /**
+ * modes
+ *
+ * NOTE: this driver assumes we are always
+ * in mode 0!
+ *
+ * seprate speed mode:
+ * motor speed1 = speed1
+ * motor speed2 = speed2
+ * turn speed mode:
+ * motor speed1 = speed1 + speed2
+ * motor speed2 = speed2 - speed2
+ * unsigned:
+ * full rev (0), stop(128), full fwd (255)
+ * signed:
+ * full rev (-127), stop(0), full fwd (128)
+ *
+ * modes numbers:
+ * 0 : unsigned separate (default)
+ * 1 : signed separate
+ * 2 : unsigned turn
+ * 3 : signed turn
+ */
+ enum e_mode {
+ MODE_UNSIGNED_SPEED = 0,
+ MODE_SIGNED_SPEED,
+ MODE_UNSIGNED_SPEED_TURN,
+ MODE_SIGNED_SPEED_TURN,
+ };
+
+ /** commands */
+ enum e_cmd {
+ CMD_RESET_ENCODERS = 32,
+ CMD_DISABLE_SPEED_REGULATION = 48,
+ CMD_ENABLE_SPEED_REGULATION = 49,
+ CMD_DISABLE_TIMEOUT = 50,
+ CMD_ENABLE_TIMEOUT = 51,
+ CMD_CHANGE_I2C_SEQ_0 = 160,
+ CMD_CHANGE_I2C_SEQ_1 = 170,
+ CMD_CHANGE_I2C_SEQ_2 = 165,
+ };
+
+ /** control channels */
+ enum e_channels {
+ CH_SPEED_LEFT = 0,
+ CH_SPEED_RIGHT
+ };
+
+ /**
+ * constructor
+ * @param deviceName the name of the device e.g. "/dev/md25"
+ * @param bus the I2C bus
+ * @param address the adddress on the I2C bus
+ * @param speed the speed of the I2C communication
+ */
+ MD25(const char *deviceName,
+ int bus,
+ uint16_t address,
+ uint32_t speed = 100000);
+
+ /**
+ * deconstructor
+ */
+ virtual ~MD25();
+
+ /**
+ * @return software version
+ */
+ uint8_t getVersion();
+
+ /**
+ * @return speed of motor, normalized (-1, 1)
+ */
+ float getMotor1Speed();
+
+ /**
+ * @return speed of motor 2, normalized (-1, 1)
+ */
+ float getMotor2Speed();
+
+ /**
+ * @return number of rotations since reset
+ */
+ float getRevolutions1();
+
+ /**
+ * @return number of rotations since reset
+ */
+ float getRevolutions2();
+
+ /**
+ * @return battery voltage, volts
+ */
+ float getBatteryVolts();
+
+ /**
+ * @return motor 1 current, amps
+ */
+ float getMotor1Current();
+
+ /**
+ * @return motor 2 current, amps
+ */
+ float getMotor2Current();
+
+ /**
+ * @return the motor acceleration
+ * controls motor speed change (1-10)
+ * accel rate | time for full fwd. to full rev.
+ * 1 | 6.375 s
+ * 2 | 1.6 s
+ * 3 | 0.675 s
+ * 5(default) | 1.275 s
+ * 10 | 0.65 s
+ */
+ uint8_t getMotorAccel();
+
+ /**
+ * @return motor output mode
+ * */
+ e_mode getMode();
+
+ /**
+ * @return current command register value
+ */
+ e_cmd getCommand();
+
+ /**
+ * resets the encoders
+ * @return non-zero -> error
+ * */
+ int resetEncoders();
+
+ /**
+ * enable/disable speed regulation
+ * @return non-zero -> error
+ */
+ int setSpeedRegulation(bool enable);
+
+ /**
+ * set the timeout for the motors
+ * enable/disable timeout (motor stop)
+ * after 2 sec of no i2c messages
+ * @return non-zero -> error
+ */
+ int setTimeout(bool enable);
+
+ /**
+ * sets the device address
+ * can only be done with one MD25
+ * on the bus
+ * @return non-zero -> error
+ */
+ int setDeviceAddress(uint8_t address);
+
+ /**
+ * set motor 1 speed
+ * @param normSpeed normalize speed between -1 and 1
+ * @return non-zero -> error
+ */
+ int setMotor1Speed(float normSpeed);
+
+ /**
+ * set motor 2 speed
+ * @param normSpeed normalize speed between -1 and 1
+ * @return non-zero -> error
+ */
+ int setMotor2Speed(float normSpeed);
+
+ /**
+ * main update loop that updates MD25 motor
+ * speeds based on actuator publication
+ */
+ void update();
+
+ /**
+ * probe for device
+ */
+ virtual int probe();
+
+ /**
+ * search for device
+ */
+ int search();
+
+ /**
+ * read data from i2c
+ */
+ int readData();
+
+ /**
+ * print status
+ */
+ void status(char *string, size_t n);
+
+private:
+ /** poll structure for control packets */
+ struct pollfd _controlPoll;
+
+ /** actuator controls subscription */
+ control::UOrbSubscription _actuators;
+
+ // local copy of data from i2c device
+ uint8_t _version;
+ float _motor1Speed;
+ float _motor2Speed;
+ float _revolutions1;
+ float _revolutions2;
+ float _batteryVoltage;
+ float _motor1Current;
+ float _motor2Current;
+ uint8_t _motorAccel;
+ e_mode _mode;
+ e_cmd _command;
+
+ // private methods
+ int _writeUint8(uint8_t reg, uint8_t value);
+ int _writeInt8(uint8_t reg, int8_t value);
+ float _uint8ToNorm(uint8_t value);
+ uint8_t _normToUint8(float value);
+
+ /**
+ * set motor control mode,
+ * this driver assumed we are always in mode 0
+ * so we don't let the user change the mode
+ * @return non-zero -> error
+ */
+ int _setMode(e_mode);
+};
+
+// unit testing
+int md25Test(const char *deviceName, uint8_t bus, uint8_t address);
+
+// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
diff --git a/src/drivers/md25/md25_main.cpp b/src/drivers/md25/md25_main.cpp
new file mode 100644
index 0000000000..80850e7088
--- /dev/null
+++ b/src/drivers/md25/md25_main.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+ *
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+
+
+/**
+ * @ file md25.cpp
+ *
+ * Driver for MD25 I2C Motor Driver
+ *
+ * references:
+ * http://www.robot-electronics.co.uk/htm/md25tech.htm
+ * http://www.robot-electronics.co.uk/files/rpi_md25.c
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include "md25.hpp"
+
+static bool thread_should_exit = false; /**< Deamon exit flag */
+static bool thread_running = false; /**< Deamon status flag */
+static int deamon_task; /**< Handle of deamon task / thread */
+
+/**
+ * Deamon management function.
+ */
+extern "C" __EXPORT int md25_main(int argc, char *argv[]);
+
+/**
+ * Mainloop of deamon.
+ */
+int md25_thread_main(int argc, char *argv[]);
+
+/**
+ * Print the correct usage.
+ */
+static void usage(const char *reason);
+
+static void
+usage(const char *reason)
+{
+ if (reason)
+ fprintf(stderr, "%s\n", reason);
+
+ fprintf(stderr, "usage: md25 {start|stop|status|search|test|change_address}\n\n");
+ exit(1);
+}
+
+/**
+ * The deamon app only briefly exists to start
+ * the background job. The stack size assigned in the
+ * Makefile does only apply to this management task.
+ *
+ * The actual stack size should be set in the call
+ * to task_create().
+ */
+int md25_main(int argc, char *argv[])
+{
+
+ if (argc < 1)
+ usage("missing command");
+
+ if (!strcmp(argv[1], "start")) {
+
+ if (thread_running) {
+ printf("md25 already running\n");
+ /* this is not an error */
+ exit(0);
+ }
+
+ thread_should_exit = false;
+ deamon_task = task_spawn("md25",
+ SCHED_DEFAULT,
+ SCHED_PRIORITY_MAX - 10,
+ 2048,
+ md25_thread_main,
+ (const char **)argv);
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "test")) {
+
+ if (argc < 4) {
+ printf("usage: md25 test bus address\n");
+ exit(0);
+ }
+
+ const char *deviceName = "/dev/md25";
+
+ uint8_t bus = strtoul(argv[2], nullptr, 0);
+
+ uint8_t address = strtoul(argv[3], nullptr, 0);
+
+ md25Test(deviceName, bus, address);
+
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "probe")) {
+ if (argc < 4) {
+ printf("usage: md25 probe bus address\n");
+ exit(0);
+ }
+
+ const char *deviceName = "/dev/md25";
+
+ uint8_t bus = strtoul(argv[2], nullptr, 0);
+
+ uint8_t address = strtoul(argv[3], nullptr, 0);
+
+ MD25 md25(deviceName, bus, address);
+
+ int ret = md25.probe();
+
+ if (ret == OK) {
+ printf("MD25 found on bus %d at address 0x%X\n", bus, md25.get_address());
+
+ } else {
+ printf("MD25 not found on bus %d\n", bus);
+ }
+
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "search")) {
+ if (argc < 3) {
+ printf("usage: md25 search bus\n");
+ exit(0);
+ }
+
+ const char *deviceName = "/dev/md25";
+
+ uint8_t bus = strtoul(argv[2], nullptr, 0);
+
+ uint8_t address = strtoul(argv[3], nullptr, 0);
+
+ MD25 md25(deviceName, bus, address);
+
+ md25.search();
+
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "change_address")) {
+ if (argc < 5) {
+ printf("usage: md25 change_address bus old_address new_address\n");
+ exit(0);
+ }
+
+ const char *deviceName = "/dev/md25";
+
+ uint8_t bus = strtoul(argv[2], nullptr, 0);
+
+ uint8_t old_address = strtoul(argv[3], nullptr, 0);
+
+ uint8_t new_address = strtoul(argv[4], nullptr, 0);
+
+ MD25 md25(deviceName, bus, old_address);
+
+ int ret = md25.setDeviceAddress(new_address);
+
+ if (ret == OK) {
+ printf("MD25 new address set to 0x%X\n", new_address);
+
+ } else {
+ printf("MD25 failed to set address to 0x%X\n", new_address);
+ }
+
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "stop")) {
+ thread_should_exit = true;
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "status")) {
+ if (thread_running) {
+ printf("\tmd25 app is running\n");
+
+ } else {
+ printf("\tmd25 app not started\n");
+ }
+
+ exit(0);
+ }
+
+ usage("unrecognized command");
+ exit(1);
+}
+
+int md25_thread_main(int argc, char *argv[])
+{
+ printf("[MD25] starting\n");
+
+ if (argc < 5) {
+ // extra md25 in arg list since this is a thread
+ printf("usage: md25 start bus address\n");
+ exit(0);
+ }
+
+ const char *deviceName = "/dev/md25";
+
+ uint8_t bus = strtoul(argv[3], nullptr, 0);
+
+ uint8_t address = strtoul(argv[4], nullptr, 0);
+
+ // start
+ MD25 md25("/dev/md25", bus, address);
+
+ thread_running = true;
+
+ // loop
+ while (!thread_should_exit) {
+ md25.update();
+ }
+
+ // exit
+ printf("[MD25] exiting.\n");
+ thread_running = false;
+ return 0;
+}
+
+// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
diff --git a/apps/ardrone_interface/Makefile b/src/drivers/md25/module.mk
similarity index 88%
rename from apps/ardrone_interface/Makefile
rename to src/drivers/md25/module.mk
index fea96082f6..13821a6b58 100644
--- a/apps/ardrone_interface/Makefile
+++ b/src/drivers/md25/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,11 +32,11 @@
############################################################################
#
-# Makefile to build ardrone interface
+# MD25 I2C Based Motor Controller
+# http://www.robot-electronics.co.uk/htm/md25tech.htm
#
-APPNAME = ardrone_interface
-PRIORITY = SCHED_PRIORITY_MAX - 15
-STACKSIZE = 2048
+MODULE_COMMAND = md25
-include $(APPDIR)/mk/app.mk
+SRCS = md25.cpp \
+ md25_main.cpp
diff --git a/src/drivers/mkblctrl/mkblctrl.cpp b/src/drivers/mkblctrl/mkblctrl.cpp
new file mode 100644
index 0000000000..3a735e26fb
--- /dev/null
+++ b/src/drivers/mkblctrl/mkblctrl.cpp
@@ -0,0 +1,1442 @@
+/****************************************************************************
+ *
+ * Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file mkblctrl.cpp
+ *
+ * Driver/configurator for the Mikrokopter BL-Ctrl.
+ * Marco Bauer
+ *
+ */
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#define I2C_BUS_SPEED 400000
+#define UPDATE_RATE 400
+#define MAX_MOTORS 8
+#define BLCTRL_BASE_ADDR 0x29
+#define BLCTRL_OLD 0
+#define BLCTRL_NEW 1
+#define BLCTRL_MIN_VALUE -0.920F
+#define MOTOR_STATE_PRESENT_MASK 0x80
+#define MOTOR_STATE_ERROR_MASK 0x7F
+#define MOTOR_SPINUP_COUNTER 2500
+
+
+class MK : public device::I2C
+{
+public:
+ enum Mode {
+ MODE_2PWM,
+ MODE_4PWM,
+ MODE_NONE
+ };
+
+ enum MappingMode {
+ MAPPING_MK = 0,
+ MAPPING_PX4,
+ };
+
+ enum FrameType {
+ FRAME_PLUS = 0,
+ FRAME_X,
+ };
+
+ MK(int bus);
+ ~MK();
+
+ virtual int ioctl(file *filp, int cmd, unsigned long arg);
+ virtual int init(unsigned motors);
+
+ int set_mode(Mode mode);
+ int set_pwm_rate(unsigned rate);
+ int set_motor_count(unsigned count);
+ int set_motor_test(bool motortest);
+ int set_px4mode(int px4mode);
+ int set_frametype(int frametype);
+ unsigned int mk_check_for_blctrl(unsigned int count, bool showOutput);
+
+private:
+ static const unsigned _max_actuators = MAX_MOTORS;
+ static const bool showDebug = false;
+
+ Mode _mode;
+ int _update_rate;
+ int _current_update_rate;
+ int _task;
+ int _t_actuators;
+ int _t_armed;
+ unsigned int _motor;
+ int _px4mode;
+ int _frametype;
+ orb_advert_t _t_outputs;
+ orb_advert_t _t_actuators_effective;
+ unsigned int _num_outputs;
+ bool _primary_pwm_device;
+ bool _motortest;
+
+ volatile bool _task_should_exit;
+ bool _armed;
+
+ unsigned long debugCounter;
+
+ MixerGroup *_mixers;
+
+ actuator_controls_s _controls;
+
+ static void task_main_trampoline(int argc, char *argv[]);
+ void task_main() __attribute__((noreturn));
+
+ static int control_callback(uintptr_t handle,
+ uint8_t control_group,
+ uint8_t control_index,
+ float &input);
+
+ int pwm_ioctl(file *filp, int cmd, unsigned long arg);
+
+ struct GPIOConfig {
+ uint32_t input;
+ uint32_t output;
+ uint32_t alt;
+ };
+
+ static const GPIOConfig _gpio_tab[];
+ static const unsigned _ngpio;
+
+ void gpio_reset(void);
+ void gpio_set_function(uint32_t gpios, int function);
+ void gpio_write(uint32_t gpios, int function);
+ uint32_t gpio_read(void);
+ int gpio_ioctl(file *filp, int cmd, unsigned long arg);
+ int mk_servo_arm(bool status);
+
+ int mk_servo_set(unsigned int chan, float val);
+ int mk_servo_set_test(unsigned int chan, float val);
+ int mk_servo_test(unsigned int chan);
+
+
+};
+
+const MK::GPIOConfig MK::_gpio_tab[] = {
+ {GPIO_GPIO0_INPUT, GPIO_GPIO0_OUTPUT, 0},
+ {GPIO_GPIO1_INPUT, GPIO_GPIO1_OUTPUT, 0},
+ {GPIO_GPIO2_INPUT, GPIO_GPIO2_OUTPUT, GPIO_USART2_CTS_1},
+ {GPIO_GPIO3_INPUT, GPIO_GPIO3_OUTPUT, GPIO_USART2_RTS_1},
+ {GPIO_GPIO4_INPUT, GPIO_GPIO4_OUTPUT, GPIO_USART2_TX_1},
+ {GPIO_GPIO5_INPUT, GPIO_GPIO5_OUTPUT, GPIO_USART2_RX_1},
+ {GPIO_GPIO6_INPUT, GPIO_GPIO6_OUTPUT, GPIO_CAN2_TX_2},
+ {GPIO_GPIO7_INPUT, GPIO_GPIO7_OUTPUT, GPIO_CAN2_RX_2},
+};
+
+const unsigned MK::_ngpio = sizeof(MK::_gpio_tab) / sizeof(MK::_gpio_tab[0]);
+
+const int blctrlAddr_quad_plus[] = { 2, 2, -2, -2, 0, 0, 0, 0 }; // Addresstranslator for Quad + configuration
+const int blctrlAddr_hexa_plus[] = { 0, 2, 2, -2, 1, -3, 0, 0 }; // Addresstranslator for Hexa + configuration
+const int blctrlAddr_octo_plus[] = { 0, 3, -1, 0, 3, 0, 0, -5 }; // Addresstranslator for Octo + configuration
+
+const int blctrlAddr_quad_x[] = { 2, 2, -2, -2, 0, 0, 0, 0 }; // Addresstranslator for Quad X configuration
+const int blctrlAddr_hexa_x[] = { 2, 4, -2, 0, -3, -1, 0, 0 }; // Addresstranslator for Hexa X configuration
+const int blctrlAddr_octo_x[] = { 1, 4, 0, 1, -4, 1, 1, -4 }; // Addresstranslator for Octo X configuration
+
+const int blctrlAddr_px4[] = { 0, 0, 0, 0, 0, 0, 0, 0};
+
+int addrTranslator[] = {0,0,0,0,0,0,0,0};
+
+struct MotorData_t
+{
+ unsigned int Version; // the version of the BL (0 = old)
+ unsigned int SetPoint; // written by attitude controller
+ unsigned int SetPointLowerBits; // for higher Resolution of new BLs
+ unsigned int State; // 7 bit for I2C error counter, highest bit indicates if motor is present
+ unsigned int ReadMode; // select data to read
+ // the following bytes must be exactly in that order!
+ unsigned int Current; // in 0.1 A steps, read back from BL
+ unsigned int MaxPWM; // read back from BL is less than 255 if BL is in current limit
+ unsigned int Temperature; // old BL-Ctrl will return a 255 here, the new version the temp. in
+ unsigned int RoundCount;
+};
+
+MotorData_t Motor[MAX_MOTORS];
+
+
+namespace
+{
+
+MK *g_mk;
+
+} // namespace
+
+MK::MK(int bus) :
+ I2C("mkblctrl", "/dev/mkblctrl", bus, 0, I2C_BUS_SPEED),
+ _mode(MODE_NONE),
+ _update_rate(50),
+ _task(-1),
+ _t_actuators(-1),
+ _t_armed(-1),
+ _t_outputs(0),
+ _t_actuators_effective(0),
+ _num_outputs(0),
+ _motortest(false),
+ _motor(-1),
+ _px4mode(MAPPING_MK),
+ _frametype(FRAME_PLUS),
+ _primary_pwm_device(false),
+ _task_should_exit(false),
+ _armed(false),
+ _mixers(nullptr)
+{
+ _debug_enabled = true;
+}
+
+MK::~MK()
+{
+ if (_task != -1) {
+ /* tell the task we want it to go away */
+ _task_should_exit = true;
+
+ unsigned i = 10;
+
+ do {
+ /* wait 50ms - it should wake every 100ms or so worst-case */
+ usleep(50000);
+
+ /* if we have given up, kill it */
+ if (--i == 0) {
+ task_delete(_task);
+ break;
+ }
+
+ } while (_task != -1);
+ }
+
+ /* clean up the alternate device node */
+ if (_primary_pwm_device)
+ unregister_driver(PWM_OUTPUT_DEVICE_PATH);
+
+ g_mk = nullptr;
+}
+
+int
+MK::init(unsigned motors)
+{
+ _num_outputs = motors;
+ debugCounter = 0;
+ int ret;
+ ASSERT(_task == -1);
+
+ ret = I2C::init();
+
+ if (ret != OK) {
+ warnx("I2C init failed");
+ return ret;
+ }
+
+ usleep(500000);
+
+ /* try to claim the generic PWM output device node as well - it's OK if we fail at this */
+ ret = register_driver(PWM_OUTPUT_DEVICE_PATH, &fops, 0666, (void *)this);
+
+ if (ret == OK) {
+ log("default PWM output device");
+ _primary_pwm_device = true;
+ }
+
+ /* reset GPIOs */
+ gpio_reset();
+
+ /* start the IO interface task */
+ _task = task_spawn("mkblctrl",
+ SCHED_DEFAULT,
+ SCHED_PRIORITY_MAX -20,
+ 2048,
+ (main_t)&MK::task_main_trampoline,
+ nullptr);
+
+
+ if (_task < 0) {
+ debug("task start failed: %d", errno);
+ return -errno;
+ }
+
+ return OK;
+}
+
+void
+MK::task_main_trampoline(int argc, char *argv[])
+{
+ g_mk->task_main();
+}
+
+int
+MK::set_mode(Mode mode)
+{
+ /*
+ * Configure for PWM output.
+ *
+ * Note that regardless of the configured mode, the task is always
+ * listening and mixing; the mode just selects which of the channels
+ * are presented on the output pins.
+ */
+ switch (mode) {
+ case MODE_2PWM:
+ if(_num_outputs == 4) {
+ //debug("MODE_QUAD");
+ } else if(_num_outputs == 6) {
+ //debug("MODE_HEXA");
+ } else if(_num_outputs == 8) {
+ //debug("MODE_OCTO");
+ }
+ //up_pwm_servo_init(0x3);
+ up_pwm_servo_deinit();
+ _update_rate = UPDATE_RATE; /* default output rate */
+ break;
+
+ case MODE_4PWM:
+ if(_num_outputs == 4) {
+ //debug("MODE_QUADRO");
+ } else if(_num_outputs == 6) {
+ //debug("MODE_HEXA");
+ } else if(_num_outputs == 8) {
+ //debug("MODE_OCTO");
+ }
+ //up_pwm_servo_init(0xf);
+ up_pwm_servo_deinit();
+ _update_rate = UPDATE_RATE; /* default output rate */
+ break;
+
+ case MODE_NONE:
+ debug("MODE_NONE");
+ /* disable servo outputs and set a very low update rate */
+ up_pwm_servo_deinit();
+ _update_rate = UPDATE_RATE;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ _mode = mode;
+ return OK;
+}
+
+int
+MK::set_pwm_rate(unsigned rate)
+{
+ if ((rate > 500) || (rate < 10))
+ return -EINVAL;
+
+ _update_rate = rate;
+ return OK;
+}
+
+int
+MK::set_px4mode(int px4mode)
+{
+ _px4mode = px4mode;
+}
+
+int
+MK::set_frametype(int frametype)
+{
+ _frametype = frametype;
+}
+
+
+int
+MK::set_motor_count(unsigned count)
+{
+ if(count > 0) {
+
+ _num_outputs = count;
+
+ if(_px4mode == MAPPING_MK) {
+ if(_frametype == FRAME_PLUS) {
+ fprintf(stderr, "[mkblctrl] addresstanslator for Mikrokopter addressing used. Frametype: +\n");
+ } else if(_frametype == FRAME_X) {
+ fprintf(stderr, "[mkblctrl] addresstanslator for Mikrokopter addressing used. Frametype: X\n");
+ }
+ if(_num_outputs == 4) {
+ if(_frametype == FRAME_PLUS) {
+ memcpy(&addrTranslator, &blctrlAddr_quad_plus, sizeof(blctrlAddr_quad_plus));
+ } else if(_frametype == FRAME_X) {
+ memcpy(&addrTranslator, &blctrlAddr_quad_x, sizeof(blctrlAddr_quad_x));
+ }
+ } else if(_num_outputs == 6) {
+ if(_frametype == FRAME_PLUS) {
+ memcpy(&addrTranslator, &blctrlAddr_hexa_plus, sizeof(blctrlAddr_hexa_plus));
+ } else if(_frametype == FRAME_X) {
+ memcpy(&addrTranslator, &blctrlAddr_hexa_x, sizeof(blctrlAddr_hexa_x));
+ }
+ } else if(_num_outputs == 8) {
+ if(_frametype == FRAME_PLUS) {
+ memcpy(&addrTranslator, &blctrlAddr_octo_plus, sizeof(blctrlAddr_octo_plus));
+ } else if(_frametype == FRAME_X) {
+ memcpy(&addrTranslator, &blctrlAddr_octo_x, sizeof(blctrlAddr_octo_x));
+ }
+ }
+ } else {
+ fprintf(stderr, "[mkblctrl] PX4 native addressing used.\n");
+ memcpy(&addrTranslator, &blctrlAddr_px4, sizeof(blctrlAddr_px4));
+ }
+
+ if(_num_outputs == 4) {
+ fprintf(stderr, "[mkblctrl] Quadrocopter Mode (4)\n");
+ } else if(_num_outputs == 6) {
+ fprintf(stderr, "[mkblctrl] Hexacopter Mode (6)\n");
+ } else if(_num_outputs == 8) {
+ fprintf(stderr, "[mkblctrl] Octocopter Mode (8)\n");
+ }
+
+ return OK;
+
+ } else {
+ return -1;
+ }
+
+}
+
+int
+MK::set_motor_test(bool motortest)
+{
+ _motortest = motortest;
+ return OK;
+}
+
+
+void
+MK::task_main()
+{
+ /*
+ * Subscribe to the appropriate PWM output topic based on whether we are the
+ * primary PWM output or not.
+ */
+ _t_actuators = orb_subscribe(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS :
+ ORB_ID(actuator_controls_1));
+ /* force a reset of the update rate */
+ _current_update_rate = 0;
+
+ _t_armed = orb_subscribe(ORB_ID(actuator_armed));
+ orb_set_interval(_t_armed, 200); /* 5Hz update rate */
+
+ /* advertise the mixed control outputs */
+ actuator_outputs_s outputs;
+ memset(&outputs, 0, sizeof(outputs));
+ /* advertise the mixed control outputs */
+ _t_outputs = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1),
+ &outputs);
+
+ /* advertise the effective control inputs */
+ actuator_controls_effective_s controls_effective;
+ memset(&controls_effective, 0, sizeof(controls_effective));
+ /* advertise the effective control inputs */
+ _t_actuators_effective = orb_advertise(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS_EFFECTIVE : ORB_ID(actuator_controls_effective_1),
+ &controls_effective);
+
+ pollfd fds[2];
+ fds[0].fd = _t_actuators;
+ fds[0].events = POLLIN;
+ fds[1].fd = _t_armed;
+ fds[1].events = POLLIN;
+
+ // rc input, published to ORB
+ struct rc_input_values rc_in;
+ orb_advert_t to_input_rc = 0;
+
+ memset(&rc_in, 0, sizeof(rc_in));
+ rc_in.input_source = RC_INPUT_SOURCE_PX4FMU_PPM;
+
+ log("starting");
+ long update_rate_in_us = 0;
+
+ /* loop until killed */
+ while (!_task_should_exit) {
+
+ /* handle update rate changes */
+ if (_current_update_rate != _update_rate) {
+ int update_rate_in_ms = int(1000 / _update_rate);
+ update_rate_in_us = long(1000000 / _update_rate);
+
+ /* reject faster than 500 Hz updates */
+ if (update_rate_in_ms < 2) {
+ update_rate_in_ms = 2;
+ _update_rate = 500;
+ }
+ /* reject slower than 50 Hz updates */
+ if (update_rate_in_ms > 20) {
+ update_rate_in_ms = 20;
+ _update_rate = 50;
+ }
+
+ orb_set_interval(_t_actuators, update_rate_in_ms);
+ up_pwm_servo_set_rate(_update_rate);
+ _current_update_rate = _update_rate;
+ }
+
+ /* sleep waiting for data, but no more than a second */
+ int ret = ::poll(&fds[0], 2, 1000);
+
+ /* this would be bad... */
+ if (ret < 0) {
+ log("poll error %d", errno);
+ usleep(1000000);
+ continue;
+ }
+
+ /* do we have a control update? */
+ if (fds[0].revents & POLLIN) {
+
+ /* get controls - must always do this to avoid spinning */
+ orb_copy(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS : ORB_ID(actuator_controls_1), _t_actuators, &_controls);
+
+ /* can we mix? */
+ if (_mixers != nullptr) {
+
+ /* do mixing */
+ outputs.noutputs = _mixers->mix(&outputs.output[0], _num_outputs);
+ outputs.timestamp = hrt_absolute_time();
+
+ // XXX output actual limited values
+ memcpy(&controls_effective, &_controls, sizeof(controls_effective));
+
+ orb_publish(_primary_pwm_device ? ORB_ID_VEHICLE_ATTITUDE_CONTROLS_EFFECTIVE : ORB_ID(actuator_controls_effective_1), _t_actuators_effective, &controls_effective);
+
+ /* iterate actuators */
+ for (unsigned int i = 0; i < _num_outputs; i++) {
+
+ /* last resort: catch NaN, INF and out-of-band errors */
+ if (i < outputs.noutputs &&
+ isfinite(outputs.output[i]) &&
+ outputs.output[i] >= -1.0f &&
+ outputs.output[i] <= 1.0f) {
+ /* scale for PWM output 900 - 2100us */
+ //outputs.output[i] = 1500 + (600 * outputs.output[i]);
+ //outputs.output[i] = 127 + (127 * outputs.output[i]);
+ } else {
+ /*
+ * Value is NaN, INF or out of band - set to the minimum value.
+ * This will be clearly visible on the servo status and will limit the risk of accidentally
+ * spinning motors. It would be deadly in flight.
+ */
+ if(outputs.output[i] < -1.0f) {
+ outputs.output[i] = -1.0f;
+ } else if(outputs.output[i] > 1.0f) {
+ outputs.output[i] = 1.0f;
+ } else {
+ outputs.output[i] = -1.0f;
+ }
+ }
+
+ /* don't go under BLCTRL_MIN_VALUE */
+ if(outputs.output[i] < BLCTRL_MIN_VALUE) {
+ outputs.output[i] = BLCTRL_MIN_VALUE;
+ }
+ //_motortest = true;
+ /* output to BLCtrl's */
+ if(_motortest == true) {
+ mk_servo_test(i);
+ } else {
+ //mk_servo_set(i, outputs.output[i]);
+ mk_servo_set_test(i, outputs.output[i]); // 8Bit
+ }
+
+
+ }
+
+ /* and publish for anyone that cares to see */
+ orb_publish(_primary_pwm_device ? ORB_ID_VEHICLE_CONTROLS : ORB_ID(actuator_outputs_1), _t_outputs, &outputs);
+ }
+ }
+
+ /* how about an arming update? */
+ if (fds[1].revents & POLLIN) {
+ actuator_armed_s aa;
+
+ /* get new value */
+ orb_copy(ORB_ID(actuator_armed), _t_armed, &aa);
+
+ /* update PWM servo armed status if armed and not locked down */
+ ////up_pwm_servo_arm(aa.armed && !aa.lockdown);
+ mk_servo_arm(aa.armed && !aa.lockdown);
+ }
+
+ // see if we have new PPM input data
+ if (ppm_last_valid_decode != rc_in.timestamp) {
+ // we have a new PPM frame. Publish it.
+ rc_in.channel_count = ppm_decoded_channels;
+ if (rc_in.channel_count > RC_INPUT_MAX_CHANNELS) {
+ rc_in.channel_count = RC_INPUT_MAX_CHANNELS;
+ }
+ for (uint8_t i=0; i 2047) {
+ tmpVal = 2047;
+ }
+
+
+ Motor[chan].SetPoint = (uint8_t) tmpVal / 3; // divide 8
+ Motor[chan].SetPointLowerBits = (uint8_t) tmpVal % 8; // rest of divide 8
+ //rod = (uint8_t) tmpVal % 8;
+ //Motor[chan].SetPointLowerBits = rod<<1; // rest of divide 8
+ Motor[chan].SetPointLowerBits = 0;
+
+ if(_armed == false) {
+ Motor[chan].SetPoint = 0;
+ Motor[chan].SetPointLowerBits = 0;
+ }
+
+ //if(Motor[chan].State & MOTOR_STATE_PRESENT_MASK) {
+ set_address(BLCTRL_BASE_ADDR + (chan + addrTranslator[chan]));
+
+ if(Motor[chan].Version == BLCTRL_OLD) {
+ /*
+ * Old BL-Ctrl 8Bit served. Version < 2.0
+ */
+ msg[0] = Motor[chan].SetPoint;
+ if(Motor[chan].RoundCount >= 16) {
+ // on each 16th cyle we read out the status messages from the blctrl
+ if (OK == transfer(&msg[0], 1, &result[0], 2)) {
+ Motor[chan].Current = result[0];
+ Motor[chan].MaxPWM = result[1];
+ Motor[chan].Temperature = 255;;
+ } else {
+ if((Motor[chan].State & MOTOR_STATE_ERROR_MASK) < MOTOR_STATE_ERROR_MASK) Motor[chan].State++; // error
+ }
+ Motor[chan].RoundCount = 0;
+ } else {
+ if (OK != transfer(&msg[0], 1, nullptr, 0)) {
+ if((Motor[chan].State & MOTOR_STATE_ERROR_MASK) < MOTOR_STATE_ERROR_MASK) Motor[chan].State++; // error
+ }
+ }
+
+ } else {
+ /*
+ * New BL-Ctrl 11Bit served. Version >= 2.0
+ */
+ msg[0] = Motor[chan].SetPoint;
+ msg[1] = Motor[chan].SetPointLowerBits;
+
+ if(Motor[chan].SetPointLowerBits == 0) {
+ bytesToSendBL2 = 1; // if setpoint lower bits are zero, we send only the higher bits - this saves time
+ }
+
+ if(Motor[chan].RoundCount >= 16) {
+ // on each 16th cyle we read out the status messages from the blctrl
+ if (OK == transfer(&msg[0], bytesToSendBL2, &result[0], 3)) {
+ Motor[chan].Current = result[0];
+ Motor[chan].MaxPWM = result[1];
+ Motor[chan].Temperature = result[2];
+ } else {
+ if((Motor[chan].State & MOTOR_STATE_ERROR_MASK) < MOTOR_STATE_ERROR_MASK) Motor[chan].State++; // error
+ }
+ Motor[chan].RoundCount = 0;
+ } else {
+ if (OK != transfer(&msg[0], bytesToSendBL2, nullptr, 0)) {
+ if((Motor[chan].State & MOTOR_STATE_ERROR_MASK) < MOTOR_STATE_ERROR_MASK) Motor[chan].State++; // error
+ }
+ }
+
+ }
+
+ Motor[chan].RoundCount++;
+ //}
+
+ if(showDebug == true) {
+ debugCounter++;
+ if(debugCounter == 2000) {
+ debugCounter = 0;
+ for(int i=0; i<_num_outputs; i++){
+ if(Motor[i].State & MOTOR_STATE_PRESENT_MASK) {
+ fprintf(stderr, "[mkblctrl] #%i:\tVer: %i\tVal: %i\tCurr: %i\tMaxPWM: %i\tTemp: %i\tState: %i\n", i, Motor[i].Version, Motor[i].SetPoint, Motor[i].Current, Motor[i].MaxPWM, Motor[i].Temperature, Motor[i].State);
+ }
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ return 0;
+}
+
+int
+MK::mk_servo_set_test(unsigned int chan, float val)
+{
+ _retries = 0;
+ int ret;
+
+ float tmpVal = 0;
+
+ uint8_t msg[2] = { 0,0 };
+
+ tmpVal = (1023 + (1023 * val));
+ if(tmpVal > 2048) {
+ tmpVal = 2048;
+ }
+
+ Motor[chan].SetPoint = (uint8_t) (tmpVal / 8);
+
+ if(_armed == false) {
+ Motor[chan].SetPoint = 0;
+ Motor[chan].SetPointLowerBits = 0;
+ }
+
+ msg[0] = Motor[chan].SetPoint;
+
+ set_address(BLCTRL_BASE_ADDR + (chan + addrTranslator[chan]));
+ ret = transfer(&msg[0], 1, nullptr, 0);
+
+ ret = OK;
+
+ return ret;
+}
+
+
+int
+MK::mk_servo_test(unsigned int chan)
+{
+ int ret=0;
+ float tmpVal = 0;
+ float val = -1;
+ _retries = 0;
+ uint8_t msg[2] = { 0,0 };
+
+ if(debugCounter >= MOTOR_SPINUP_COUNTER) {
+ debugCounter = 0;
+ _motor++;
+
+ if(_motor < _num_outputs) {
+ fprintf(stderr, "[mkblctrl] Motortest - #%i:\tspinup\n", _motor);
+ }
+
+ if(_motor >= _num_outputs) {
+ _motor = -1;
+ _motortest = false;
+ }
+
+ }
+ debugCounter++;
+
+ if(_motor == chan) {
+ val = BLCTRL_MIN_VALUE;
+ } else {
+ val = -1;
+ }
+
+ tmpVal = (1023 + (1023 * val));
+ if(tmpVal > 2048) {
+ tmpVal = 2048;
+ }
+
+ //Motor[chan].SetPoint = (uint8_t) (tmpVal / 8);
+ //Motor[chan].SetPointLowerBits = (uint8_t) (tmpVal % 8) & 0x07;
+ Motor[chan].SetPoint = (uint8_t) tmpVal>>3;
+ Motor[chan].SetPointLowerBits = (uint8_t) tmpVal & 0x07;
+
+ if(_motor != chan) {
+ Motor[chan].SetPoint = 0;
+ Motor[chan].SetPointLowerBits = 0;
+ }
+
+ if(Motor[chan].Version == BLCTRL_OLD) {
+ msg[0] = Motor[chan].SetPoint;
+ } else {
+ msg[0] = Motor[chan].SetPoint;
+ msg[1] = Motor[chan].SetPointLowerBits;
+ }
+
+ set_address(BLCTRL_BASE_ADDR + (chan + addrTranslator[chan]));
+ if(Motor[chan].Version == BLCTRL_OLD) {
+ ret = transfer(&msg[0], 1, nullptr, 0);
+ } else {
+ ret = transfer(&msg[0], 2, nullptr, 0);
+ }
+
+ return ret;
+}
+
+
+int
+MK::control_callback(uintptr_t handle,
+ uint8_t control_group,
+ uint8_t control_index,
+ float &input)
+{
+ const actuator_controls_s *controls = (actuator_controls_s *)handle;
+
+ input = controls->control[control_index];
+ return 0;
+}
+
+int
+MK::ioctl(file *filp, int cmd, unsigned long arg)
+{
+ int ret;
+
+ // XXX disabled, confusing users
+ //debug("ioctl 0x%04x 0x%08x", cmd, arg);
+
+ /* try it as a GPIO ioctl first */
+ ret = gpio_ioctl(filp, cmd, arg);
+
+ if (ret != -ENOTTY)
+ return ret;
+
+ /* if we are in valid PWM mode, try it as a PWM ioctl as well */
+ switch (_mode) {
+ case MODE_2PWM:
+ case MODE_4PWM:
+ ret = pwm_ioctl(filp, cmd, arg);
+ break;
+
+ default:
+ debug("not in a PWM mode");
+ break;
+ }
+
+ /* if nobody wants it, let CDev have it */
+ if (ret == -ENOTTY)
+ ret = CDev::ioctl(filp, cmd, arg);
+
+ return ret;
+}
+
+int
+MK::pwm_ioctl(file *filp, int cmd, unsigned long arg)
+{
+ int ret = OK;
+ int channel;
+
+ lock();
+
+ switch (cmd) {
+ case PWM_SERVO_ARM:
+ ////up_pwm_servo_arm(true);
+ mk_servo_arm(true);
+ break;
+
+ case PWM_SERVO_DISARM:
+ ////up_pwm_servo_arm(false);
+ mk_servo_arm(false);
+ break;
+
+ case PWM_SERVO_SET_UPDATE_RATE:
+ set_pwm_rate(arg);
+ break;
+
+
+ case PWM_SERVO_SET(0) ... PWM_SERVO_SET(_max_actuators - 1):
+
+ /* fake an update to the selected 'servo' channel */
+ if ((arg >= 0) && (arg <= 255)) {
+ channel = cmd - PWM_SERVO_SET(0);
+ //mk_servo_set(channel, arg);
+ } else {
+ ret = -EINVAL;
+ }
+
+ break;
+
+ case PWM_SERVO_GET(0) ... PWM_SERVO_GET(_max_actuators - 1):
+ /* copy the current output value from the channel */
+ *(servo_position_t *)arg = cmd - PWM_SERVO_GET(0);
+ break;
+
+ case MIXERIOCGETOUTPUTCOUNT:
+ /*
+ if (_mode == MODE_4PWM) {
+ *(unsigned *)arg = 4;
+ } else {
+ *(unsigned *)arg = 2;
+ }
+ */
+
+ *(unsigned *)arg = _num_outputs;
+
+ break;
+
+ case MIXERIOCRESET:
+ if (_mixers != nullptr) {
+ delete _mixers;
+ _mixers = nullptr;
+ }
+
+ break;
+
+ case MIXERIOCADDSIMPLE: {
+ mixer_simple_s *mixinfo = (mixer_simple_s *)arg;
+
+ SimpleMixer *mixer = new SimpleMixer(control_callback,
+ (uintptr_t)&_controls, mixinfo);
+
+ if (mixer->check()) {
+ delete mixer;
+ ret = -EINVAL;
+
+ } else {
+ if (_mixers == nullptr)
+ _mixers = new MixerGroup(control_callback,
+ (uintptr_t)&_controls);
+
+ _mixers->add_mixer(mixer);
+ }
+
+ break;
+ }
+
+ case MIXERIOCLOADBUF: {
+ const char *buf = (const char *)arg;
+ unsigned buflen = strnlen(buf, 1024);
+
+ if (_mixers == nullptr)
+ _mixers = new MixerGroup(control_callback, (uintptr_t)&_controls);
+
+ if (_mixers == nullptr) {
+ ret = -ENOMEM;
+
+ } else {
+
+ ret = _mixers->load_from_buf(buf, buflen);
+
+ if (ret != 0) {
+ debug("mixer load failed with %d", ret);
+ delete _mixers;
+ _mixers = nullptr;
+ ret = -EINVAL;
+ }
+ }
+ break;
+ }
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ unlock();
+
+ return ret;
+}
+
+void
+MK::gpio_reset(void)
+{
+ /*
+ * Setup default GPIO config - all pins as GPIOs, GPIO driver chip
+ * to input mode.
+ */
+ for (unsigned i = 0; i < _ngpio; i++)
+ stm32_configgpio(_gpio_tab[i].input);
+
+ stm32_gpiowrite(GPIO_GPIO_DIR, 0);
+ stm32_configgpio(GPIO_GPIO_DIR);
+}
+
+void
+MK::gpio_set_function(uint32_t gpios, int function)
+{
+ /*
+ * GPIOs 0 and 1 must have the same direction as they are buffered
+ * by a shared 2-port driver. Any attempt to set either sets both.
+ */
+ if (gpios & 3) {
+ gpios |= 3;
+
+ /* flip the buffer to output mode if required */
+ if (GPIO_SET_OUTPUT == function)
+ stm32_gpiowrite(GPIO_GPIO_DIR, 1);
+ }
+
+ /* configure selected GPIOs as required */
+ for (unsigned i = 0; i < _ngpio; i++) {
+ if (gpios & (1 << i)) {
+ switch (function) {
+ case GPIO_SET_INPUT:
+ stm32_configgpio(_gpio_tab[i].input);
+ break;
+
+ case GPIO_SET_OUTPUT:
+ stm32_configgpio(_gpio_tab[i].output);
+ break;
+
+ case GPIO_SET_ALT_1:
+ if (_gpio_tab[i].alt != 0)
+ stm32_configgpio(_gpio_tab[i].alt);
+
+ break;
+ }
+ }
+ }
+
+ /* flip buffer to input mode if required */
+ if ((GPIO_SET_INPUT == function) && (gpios & 3))
+ stm32_gpiowrite(GPIO_GPIO_DIR, 0);
+}
+
+void
+MK::gpio_write(uint32_t gpios, int function)
+{
+ int value = (function == GPIO_SET) ? 1 : 0;
+
+ for (unsigned i = 0; i < _ngpio; i++)
+ if (gpios & (1 << i))
+ stm32_gpiowrite(_gpio_tab[i].output, value);
+}
+
+uint32_t
+MK::gpio_read(void)
+{
+ uint32_t bits = 0;
+
+ for (unsigned i = 0; i < _ngpio; i++)
+ if (stm32_gpioread(_gpio_tab[i].input))
+ bits |= (1 << i);
+
+ return bits;
+}
+
+int
+MK::gpio_ioctl(struct file *filp, int cmd, unsigned long arg)
+{
+ int ret = OK;
+
+ lock();
+
+ switch (cmd) {
+
+ case GPIO_RESET:
+ gpio_reset();
+ break;
+
+ case GPIO_SET_OUTPUT:
+ case GPIO_SET_INPUT:
+ case GPIO_SET_ALT_1:
+ gpio_set_function(arg, cmd);
+ break;
+
+ case GPIO_SET_ALT_2:
+ case GPIO_SET_ALT_3:
+ case GPIO_SET_ALT_4:
+ ret = -EINVAL;
+ break;
+
+ case GPIO_SET:
+ case GPIO_CLEAR:
+ gpio_write(arg, cmd);
+ break;
+
+ case GPIO_GET:
+ *(uint32_t *)arg = gpio_read();
+ break;
+
+ default:
+ ret = -ENOTTY;
+ }
+
+ unlock();
+
+ return ret;
+}
+
+namespace
+{
+
+enum PortMode {
+ PORT_MODE_UNSET = 0,
+ PORT_FULL_GPIO,
+ PORT_FULL_SERIAL,
+ PORT_FULL_PWM,
+ PORT_GPIO_AND_SERIAL,
+ PORT_PWM_AND_SERIAL,
+ PORT_PWM_AND_GPIO,
+};
+
+enum MappingMode {
+ MAPPING_MK = 0,
+ MAPPING_PX4,
+};
+
+ enum FrameType {
+ FRAME_PLUS = 0,
+ FRAME_X,
+ };
+
+PortMode g_port_mode;
+
+int
+mk_new_mode(PortMode new_mode, int update_rate, int motorcount, bool motortest, int px4mode, int frametype)
+{
+ uint32_t gpio_bits;
+ int shouldStop = 0;
+ MK::Mode servo_mode;
+
+ /* reset to all-inputs */
+ g_mk->ioctl(0, GPIO_RESET, 0);
+
+ gpio_bits = 0;
+ servo_mode = MK::MODE_NONE;
+
+ switch (new_mode) {
+ case PORT_FULL_GPIO:
+ case PORT_MODE_UNSET:
+ /* nothing more to do here */
+ break;
+
+ case PORT_FULL_SERIAL:
+ /* set all multi-GPIOs to serial mode */
+ gpio_bits = GPIO_MULTI_1 | GPIO_MULTI_2 | GPIO_MULTI_3 | GPIO_MULTI_4;
+ break;
+
+ case PORT_FULL_PWM:
+ /* select 4-pin PWM mode */
+ servo_mode = MK::MODE_4PWM;
+ break;
+
+ case PORT_GPIO_AND_SERIAL:
+ /* set RX/TX multi-GPIOs to serial mode */
+ gpio_bits = GPIO_MULTI_3 | GPIO_MULTI_4;
+ break;
+
+ case PORT_PWM_AND_SERIAL:
+ /* select 2-pin PWM mode */
+ servo_mode = MK::MODE_2PWM;
+ /* set RX/TX multi-GPIOs to serial mode */
+ gpio_bits = GPIO_MULTI_3 | GPIO_MULTI_4;
+ break;
+
+ case PORT_PWM_AND_GPIO:
+ /* select 2-pin PWM mode */
+ servo_mode = MK::MODE_2PWM;
+ break;
+ }
+
+ /* adjust GPIO config for serial mode(s) */
+ if (gpio_bits != 0)
+ g_mk->ioctl(0, GPIO_SET_ALT_1, gpio_bits);
+
+ /* native PX4 addressing) */
+ g_mk->set_px4mode(px4mode);
+
+ /* set frametype (geometry) */
+ g_mk->set_frametype(frametype);
+
+ /* motortest if enabled */
+ g_mk->set_motor_test(motortest);
+
+
+ /* (re)set count of used motors */
+ ////g_mk->set_motor_count(motorcount);
+ /* count used motors */
+
+ do {
+ if(g_mk->mk_check_for_blctrl(8, false) != 0) {
+ shouldStop = 4;
+ } else {
+ shouldStop++;
+ }
+ sleep(1);
+ } while ( shouldStop < 3);
+
+ g_mk->set_motor_count(g_mk->mk_check_for_blctrl(8, true));
+
+ /* (re)set the PWM output mode */
+ g_mk->set_mode(servo_mode);
+
+
+ if ((servo_mode != MK::MODE_NONE) && (update_rate != 0))
+ g_mk->set_pwm_rate(update_rate);
+
+ return OK;
+}
+
+int
+mk_start(unsigned bus, unsigned motors)
+{
+ int ret = OK;
+
+ if (g_mk == nullptr) {
+
+ g_mk = new MK(bus);
+
+ if (g_mk == nullptr) {
+ ret = -ENOMEM;
+
+ } else {
+ ret = g_mk->init(motors);
+
+ if (ret != OK) {
+ delete g_mk;
+ g_mk = nullptr;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+} // namespace
+
+extern "C" __EXPORT int mkblctrl_main(int argc, char *argv[]);
+
+int
+mkblctrl_main(int argc, char *argv[])
+{
+ PortMode port_mode = PORT_FULL_PWM;
+ int pwm_update_rate_in_hz = UPDATE_RATE;
+ int motorcount = 8;
+ int bus = 1;
+ int px4mode = MAPPING_PX4;
+ int frametype = FRAME_PLUS; // + plus is default
+ bool motortest = false;
+ bool showHelp = false;
+ bool newMode = false;
+
+ /*
+ * optional parameters
+ */
+ for (int i = 1; i < argc; i++) {
+
+ /* look for the optional i2c bus parameter */
+ if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--bus") == 0) {
+ if (argc > i + 1) {
+ bus = atoi(argv[i + 1]);
+ newMode = true;
+ } else {
+ errx(1, "missing argument for i2c bus (-b)");
+ return 1;
+ }
+ }
+
+ /* look for the optional frame parameter */
+ if (strcmp(argv[i], "-mkmode") == 0 || strcmp(argv[i], "--mkmode") == 0) {
+ if (argc > i + 1) {
+ if(strcmp(argv[i + 1], "+") == 0 || strcmp(argv[i + 1], "x") == 0 || strcmp(argv[i + 1], "X") == 0) {
+ px4mode = MAPPING_MK;
+ newMode = true;
+ if(strcmp(argv[i + 1], "+") == 0) {
+ frametype = FRAME_PLUS;
+ } else {
+ frametype = FRAME_X;
+ }
+ } else {
+ errx(1, "only + or x for frametype supported !");
+ }
+ } else {
+ errx(1, "missing argument for mkmode (-mkmode)");
+ return 1;
+ }
+ }
+
+ /* look for the optional test parameter */
+ if (strcmp(argv[i], "-t") == 0) {
+ motortest = true;
+ newMode = true;
+ }
+
+ /* look for the optional -h --help parameter */
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ showHelp == true;
+ }
+
+ }
+
+ if(showHelp) {
+ fprintf(stderr, "mkblctrl: help:\n");
+ fprintf(stderr, " [-mkmode frame{+/x}] [-b i2c_bus_number] [-t motortest] [-h / --help]\n");
+ exit(1);
+ }
+
+
+ if (g_mk == nullptr) {
+ if (mk_start(bus, motorcount) != OK) {
+ errx(1, "failed to start the MK-BLCtrl driver");
+ } else {
+ newMode = true;
+ }
+ }
+
+
+ /* parameter set ? */
+ if (newMode) {
+ /* switch parameter */
+ return mk_new_mode(port_mode, pwm_update_rate_in_hz, motorcount, motortest, px4mode, frametype);
+ }
+
+ /* test, etc. here g*/
+
+ exit(1);
+}
diff --git a/apps/commander/Makefile b/src/drivers/mkblctrl/module.mk
similarity index 87%
rename from apps/commander/Makefile
rename to src/drivers/mkblctrl/module.mk
index d12697274b..3ac263b002 100644
--- a/apps/commander/Makefile
+++ b/src/drivers/mkblctrl/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012,2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,14 +32,11 @@
############################################################################
#
-# Commander application
+# Interface driver for the Mikrokopter BLCtrl
#
-APPNAME = commander
-PRIORITY = SCHED_PRIORITY_MAX - 30
-STACKSIZE = 2048
+MODULE_COMMAND = mkblctrl
-INCLUDES = $(TOPDIR)/../mavlink/include/mavlink
-
-include $(APPDIR)/mk/app.mk
+SRCS = mkblctrl.cpp
+INCLUDE_DIRS += $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
diff --git a/apps/mavlink/Makefile b/src/drivers/mpu6000/module.mk
similarity index 87%
rename from apps/mavlink/Makefile
rename to src/drivers/mpu6000/module.mk
index 8ddb69b71d..c7d9cd3ef1 100644
--- a/apps/mavlink/Makefile
+++ b/src/drivers/mpu6000/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,13 +32,12 @@
############################################################################
#
-# Mavlink Application
+# Makefile to build the MPU6000 driver.
#
-APPNAME = mavlink
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = mpu6000
-INCLUDES = $(TOPDIR)/../mavlink/include/mavlink
+# XXX seems excessive, check if 2048 is not sufficient
+MODULE_STACKSIZE = 4096
-include $(APPDIR)/mk/app.mk
+SRCS = mpu6000.cpp
diff --git a/apps/drivers/mpu6000/mpu6000.cpp b/src/drivers/mpu6000/mpu6000.cpp
similarity index 99%
rename from apps/drivers/mpu6000/mpu6000.cpp
rename to src/drivers/mpu6000/mpu6000.cpp
index ce7062046f..df1958186f 100644
--- a/apps/drivers/mpu6000/mpu6000.cpp
+++ b/src/drivers/mpu6000/mpu6000.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/apps/drivers/led/Makefile b/src/drivers/ms5611/module.mk
similarity index 92%
rename from apps/drivers/led/Makefile
rename to src/drivers/ms5611/module.mk
index 7de1882597..3c4b0f0938 100644
--- a/apps/drivers/led/Makefile
+++ b/src/drivers/ms5611/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,7 +32,9 @@
############################################################################
#
-# Makefile to build the LED driver.
+# MS5611 driver
#
-include $(APPDIR)/mk/app.mk
+MODULE_COMMAND = ms5611
+
+SRCS = ms5611.cpp
diff --git a/apps/drivers/ms5611/ms5611.cpp b/src/drivers/ms5611/ms5611.cpp
similarity index 100%
rename from apps/drivers/ms5611/ms5611.cpp
rename to src/drivers/ms5611/ms5611.cpp
diff --git a/apps/drivers/px4fmu/fmu.cpp b/src/drivers/px4fmu/fmu.cpp
similarity index 98%
rename from apps/drivers/px4fmu/fmu.cpp
rename to src/drivers/px4fmu/fmu.cpp
index e547245367..bf72892ebe 100644
--- a/apps/drivers/px4fmu/fmu.cpp
+++ b/src/drivers/px4fmu/fmu.cpp
@@ -505,7 +505,11 @@ PX4FMU::task_main()
orb_copy(ORB_ID(actuator_armed), _t_armed, &aa);
/* update PWM servo armed status if armed and not locked down */
- up_pwm_servo_arm(aa.armed && !aa.lockdown);
+ bool set_armed = aa.armed && !aa.lockdown;
+ if (set_armed != _armed) {
+ _armed = set_armed;
+ up_pwm_servo_arm(set_armed);
+ }
}
// see if we have new PPM input data
@@ -602,6 +606,11 @@ PX4FMU::pwm_ioctl(file *filp, int cmd, unsigned long arg)
up_pwm_servo_arm(true);
break;
+ case PWM_SERVO_SET_ARM_OK:
+ case PWM_SERVO_CLEAR_ARM_OK:
+ // these are no-ops, as no safety switch
+ break;
+
case PWM_SERVO_DISARM:
up_pwm_servo_arm(false);
break;
diff --git a/src/drivers/px4fmu/module.mk b/src/drivers/px4fmu/module.mk
new file mode 100644
index 0000000000..05bc7a5b33
--- /dev/null
+++ b/src/drivers/px4fmu/module.mk
@@ -0,0 +1,6 @@
+#
+# Interface driver for the PX4FMU board
+#
+
+MODULE_COMMAND = fmu
+SRCS = fmu.cpp
diff --git a/apps/drivers/px4io/Makefile b/src/drivers/px4io/module.mk
similarity index 91%
rename from apps/drivers/px4io/Makefile
rename to src/drivers/px4io/module.mk
index cbd9425463..328e5a6843 100644
--- a/apps/drivers/px4io/Makefile
+++ b/src/drivers/px4io/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -35,8 +35,7 @@
# Interface driver for the PX4IO board.
#
-APPNAME = px4io
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = px4io
-include $(APPDIR)/mk/app.mk
+SRCS = px4io.cpp \
+ uploader.cpp
diff --git a/apps/drivers/px4io/px4io.cpp b/src/drivers/px4io/px4io.cpp
similarity index 93%
rename from apps/drivers/px4io/px4io.cpp
rename to src/drivers/px4io/px4io.cpp
index f72a2c6b59..399c003b76 100644
--- a/apps/drivers/px4io/px4io.cpp
+++ b/src/drivers/px4io/px4io.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012,2013 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -80,11 +80,11 @@
#include
#include
#include
+#include
-#include
#include
#include "uploader.h"
-#include
+#include
#define PX4IO_SET_DEBUG _IOC(0xff00, 0)
#define PX4IO_INAIR_RESTART_ENABLE _IOC(0xff00, 1)
@@ -108,6 +108,14 @@ public:
*/
int set_update_rate(int rate);
+ /**
+ * Set the battery current scaling and bias
+ *
+ * @param amp_per_volt
+ * @param amp_bias
+ */
+ void set_battery_current_scaling(float amp_per_volt, float amp_bias);
+
/**
* Print the current status of IO
*/
@@ -151,6 +159,10 @@ private:
bool _primary_pwm_device; ///< true if we are the default PWM output
+ float _battery_amp_per_volt;
+ float _battery_amp_bias;
+ float _battery_mamphour_total;
+ uint64_t _battery_last_timestamp;
/**
* Trampoline to the worker task
@@ -314,6 +326,10 @@ PX4IO::PX4IO() :
_to_actuators_effective(0),
_to_outputs(0),
_to_battery(0),
+ _battery_amp_per_volt(90.0f/5.0f), // this matches the 3DR current sensor
+ _battery_amp_bias(0),
+ _battery_mamphour_total(0),
+ _battery_last_timestamp(0),
_primary_pwm_device(false)
{
/* we need this potentially before it could be set in task_main */
@@ -400,7 +416,7 @@ PX4IO::init()
* already armed, and has been configured for in-air restart
*/
if ((reg & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) &&
- (reg & PX4IO_P_SETUP_ARMING_ARM_OK)) {
+ (reg & PX4IO_P_SETUP_ARMING_FMU_ARMED)) {
mavlink_log_emergency(_mavlink_fd, "[IO] RECOVERING FROM FMU IN-AIR RESTART");
@@ -484,10 +500,9 @@ PX4IO::init()
/* dis-arm IO before touching anything */
io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING,
- PX4IO_P_SETUP_ARMING_ARM_OK |
+ PX4IO_P_SETUP_ARMING_FMU_ARMED |
PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK |
- PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK |
- PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK, 0);
+ PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK, 0);
/* publish RC config to IO */
ret = io_set_rc_config();
@@ -686,17 +701,18 @@ PX4IO::io_set_arming_state()
uint16_t set = 0;
uint16_t clear = 0;
- if (armed.armed) {
- set |= PX4IO_P_SETUP_ARMING_ARM_OK;
+ if (armed.armed && !armed.lockdown) {
+ set |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
} else {
- clear |= PX4IO_P_SETUP_ARMING_ARM_OK;
+ clear |= PX4IO_P_SETUP_ARMING_FMU_ARMED;
}
// TODO fix this
- // if (vstatus.flag_vector_flight_mode_ok) {
- // set |= PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK;
- // } else {
- // clear |= PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK;
- // }
+// if (armed.ready_to_arm) {
+// set |= PX4IO_P_SETUP_ARMING_IO_ARM_OK;
+// } else {
+// clear |= PX4IO_P_SETUP_ARMING_IO_ARM_OK;
+// }
+
if (vstatus.flag_external_manual_override_ok) {
set |= PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK;
} else {
@@ -885,11 +901,22 @@ PX4IO::io_get_status()
/* voltage is scaled to mV */
battery_status.voltage_v = regs[2] / 1000.0f;
- /* current scaling should be to cA in order to avoid limiting at 65A */
- battery_status.current_a = regs[3] / 100.f;
+ /*
+ regs[3] contains the raw ADC count, as 12 bit ADC
+ value, with full range being 3.3v
+ */
+ battery_status.current_a = regs[3] * (3.3f/4096.0f) * _battery_amp_per_volt;
+ battery_status.current_a += _battery_amp_bias;
- /* this requires integration over time - not currently implemented */
- battery_status.discharged_mah = -1.0f;
+ /*
+ integrate battery over time to get total mAh used
+ */
+ if (_battery_last_timestamp != 0) {
+ _battery_mamphour_total += battery_status.current_a *
+ (battery_status.timestamp - _battery_last_timestamp) * 1.0e-3f / 3600;
+ }
+ battery_status.discharged_mah = _battery_mamphour_total;
+ _battery_last_timestamp = battery_status.timestamp;
/* lazily publish the battery voltage */
if (_to_battery > 0) {
@@ -1246,9 +1273,14 @@ PX4IO::print_status()
((alarms & PX4IO_P_STATUS_ALARMS_FMU_LOST) ? " FMU_LOST" : ""),
((alarms & PX4IO_P_STATUS_ALARMS_RC_LOST) ? " RC_LOST" : ""),
((alarms & PX4IO_P_STATUS_ALARMS_PWM_ERROR) ? " PWM_ERROR" : ""));
- printf("vbatt %u ibatt %u\n",
- io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_VBATT),
- io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_IBATT));
+ printf("vbatt %u ibatt %u vbatt scale %u\n",
+ io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_VBATT),
+ io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_IBATT),
+ io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_VBATT_SCALE));
+ printf("amp_per_volt %.3f amp_offset %.3f mAhDischarged %.3f\n",
+ (double)_battery_amp_per_volt,
+ (double)_battery_amp_bias,
+ (double)_battery_mamphour_total);
printf("actuators");
for (unsigned i = 0; i < _max_actuators; i++)
printf(" %u", io_reg_get(PX4IO_PAGE_ACTUATORS, i));
@@ -1280,19 +1312,15 @@ PX4IO::print_status()
uint16_t arming = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING);
printf("arming 0x%04x%s%s%s%s\n",
arming,
- ((arming & PX4IO_P_SETUP_ARMING_ARM_OK) ? " ARM_OK" : ""),
+ ((arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) ? " FMU_ARMED" : ""),
+ ((arming & PX4IO_P_SETUP_ARMING_IO_ARM_OK) ? " IO_ARM_OK" : ""),
((arming & PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK) ? " MANUAL_OVERRIDE_OK" : ""),
- ((arming & PX4IO_P_SETUP_ARMING_VECTOR_FLIGHT_OK) ? " VECTOR_FLIGHT_OK" : ""),
((arming & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) ? " INAIR_RESTART_OK" : ""));
printf("rates 0x%04x default %u alt %u relays 0x%04x\n",
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES),
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_DEFAULTRATE),
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE),
io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_RELAYS));
- printf("vbatt scale %u ibatt scale %u ibatt bias %u\n",
- io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_VBATT_SCALE),
- io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_IBATT_SCALE),
- io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_IBATT_BIAS));
printf("debuglevel %u\n", io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_SET_DEBUG));
printf("controls");
for (unsigned i = 0; i < _max_controls; i++)
@@ -1327,21 +1355,27 @@ PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
switch (cmd) {
case PWM_SERVO_ARM:
/* set the 'armed' bit */
- ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_ARM_OK);
+ ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_FMU_ARMED);
+ break;
+
+ case PWM_SERVO_SET_ARM_OK:
+ /* set the 'OK to arm' bit */
+ ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, 0, PX4IO_P_SETUP_ARMING_IO_ARM_OK);
+ break;
+
+ case PWM_SERVO_CLEAR_ARM_OK:
+ /* clear the 'OK to arm' bit */
+ ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_IO_ARM_OK, 0);
break;
case PWM_SERVO_DISARM:
/* clear the 'armed' bit */
- ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_ARM_OK, 0);
+ ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, PX4IO_P_SETUP_ARMING_FMU_ARMED, 0);
break;
case PWM_SERVO_SET_UPDATE_RATE:
/* set the requested alternate rate */
- if ((arg >= 50) && (arg <= 400)) { /* TODO: we could go higher for e.g. TurboPWM */
- ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE, arg);
- } else {
- ret = -EINVAL;
- }
+ ret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE, arg);
break;
case PWM_SERVO_SELECT_UPDATE_RATE: {
@@ -1526,6 +1560,12 @@ PX4IO::set_update_rate(int rate)
return 0;
}
+void
+PX4IO::set_battery_current_scaling(float amp_per_volt, float amp_bias)
+{
+ _battery_amp_per_volt = amp_per_volt;
+ _battery_amp_bias = amp_bias;
+}
extern "C" __EXPORT int px4io_main(int argc, char *argv[]);
@@ -1663,6 +1703,18 @@ px4io_main(int argc, char *argv[])
exit(0);
}
+ if (!strcmp(argv[1], "current")) {
+ if (g_dev != nullptr) {
+ if ((argc > 3)) {
+ g_dev->set_battery_current_scaling(atof(argv[2]), atof(argv[3]));
+ } else {
+ errx(1, "missing argument (apm_per_volt, amp_offset)");
+ return 1;
+ }
+ }
+ exit(0);
+ }
+
if (!strcmp(argv[1], "recovery")) {
if (g_dev != nullptr) {
@@ -1790,5 +1842,5 @@ px4io_main(int argc, char *argv[])
monitor();
out:
- errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug', 'recovery', 'limit' or 'update'");
+ errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug', 'recovery', 'limit', 'current' or 'update'");
}
diff --git a/apps/drivers/px4io/uploader.cpp b/src/drivers/px4io/uploader.cpp
similarity index 97%
rename from apps/drivers/px4io/uploader.cpp
rename to src/drivers/px4io/uploader.cpp
index abf59216a6..15524c3aeb 100644
--- a/apps/drivers/px4io/uploader.cpp
+++ b/src/drivers/px4io/uploader.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,8 @@
****************************************************************************/
/**
- * @file Firmware uploader for PX4IO
+ * @file uploader.cpp
+ * Firmware uploader for PX4IO
*/
#include
@@ -126,6 +127,8 @@ PX4IO_Uploader::upload(const char *filenames[])
if (ret != OK) {
/* this is immediately fatal */
log("bootloader not responding");
+ close(_io_fd);
+ _io_fd = -1;
return -EIO;
}
@@ -144,18 +147,25 @@ PX4IO_Uploader::upload(const char *filenames[])
if (filename == NULL) {
log("no firmware found");
+ close(_io_fd);
+ _io_fd = -1;
return -ENOENT;
}
struct stat st;
if (stat(filename, &st) != 0) {
log("Failed to stat %s - %d\n", filename, (int)errno);
+ close(_io_fd);
+ _io_fd = -1;
return -errno;
}
fw_size = st.st_size;
- if (_fw_fd == -1)
+ if (_fw_fd == -1) {
+ close(_io_fd);
+ _io_fd = -1;
return -ENOENT;
+ }
/* do the usual program thing - allow for failure */
for (unsigned retries = 0; retries < 1; retries++) {
@@ -166,6 +176,8 @@ PX4IO_Uploader::upload(const char *filenames[])
if (ret != OK) {
/* this is immediately fatal */
log("bootloader not responding");
+ close(_io_fd);
+ _io_fd = -1;
return -EIO;
}
}
@@ -177,6 +189,8 @@ PX4IO_Uploader::upload(const char *filenames[])
log("found bootloader revision: %d", bl_rev);
} else {
log("found unsupported bootloader revision %d, exiting", bl_rev);
+ close(_io_fd);
+ _io_fd = -1;
return OK;
}
}
@@ -220,6 +234,8 @@ PX4IO_Uploader::upload(const char *filenames[])
}
close(_fw_fd);
+ close(_io_fd);
+ _io_fd = -1;
return ret;
}
diff --git a/apps/drivers/px4io/uploader.h b/src/drivers/px4io/uploader.h
similarity index 95%
rename from apps/drivers/px4io/uploader.h
rename to src/drivers/px4io/uploader.h
index f983d19811..135202dd1b 100644
--- a/apps/drivers/px4io/uploader.h
+++ b/src/drivers/px4io/uploader.h
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,8 @@
****************************************************************************/
/**
- * @file Firmware uploader for PX4IO
+ * @file uploader.h
+ * Firmware uploader definitions for PX4IO.
*/
#ifndef _PX4IO_UPLOADER_H
diff --git a/apps/drivers/stm32/adc/adc.cpp b/src/drivers/stm32/adc/adc.cpp
similarity index 100%
rename from apps/drivers/stm32/adc/adc.cpp
rename to src/drivers/stm32/adc/adc.cpp
diff --git a/src/drivers/stm32/adc/module.mk b/src/drivers/stm32/adc/module.mk
new file mode 100644
index 0000000000..48620feea8
--- /dev/null
+++ b/src/drivers/stm32/adc/module.mk
@@ -0,0 +1,42 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# STM32 ADC driver
+#
+
+MODULE_COMMAND = adc
+
+SRCS = adc.cpp
+
+INCLUDE_DIRS += $(NUTTX_SRC)/arch/arm/src/stm32 $(NUTTX_SRC)/arch/arm/src/common
diff --git a/apps/drivers/stm32/drv_hrt.c b/src/drivers/stm32/drv_hrt.c
similarity index 99%
rename from apps/drivers/stm32/drv_hrt.c
rename to src/drivers/stm32/drv_hrt.c
index bb67d5e6d2..cec0c49ffd 100644
--- a/apps/drivers/stm32/drv_hrt.c
+++ b/src/drivers/stm32/drv_hrt.c
@@ -125,7 +125,7 @@
# define HRT_TIMER_VECTOR STM32_IRQ_TIM8CC
# define HRT_TIMER_CLOCK STM32_APB2_TIM8_CLKIN
# if CONFIG_STM32_TIM8
-# error must not set CONFIG_STM32_TIM8=y and HRT_TIMER=6
+# error must not set CONFIG_STM32_TIM8=y and HRT_TIMER=8
# endif
#elif HRT_TIMER == 9
# define HRT_TIMER_BASE STM32_TIM9_BASE
diff --git a/apps/drivers/stm32/drv_pwm_servo.c b/src/drivers/stm32/drv_pwm_servo.c
similarity index 99%
rename from apps/drivers/stm32/drv_pwm_servo.c
rename to src/drivers/stm32/drv_pwm_servo.c
index d7316e1f76..c1efb8515f 100644
--- a/apps/drivers/stm32/drv_pwm_servo.c
+++ b/src/drivers/stm32/drv_pwm_servo.c
@@ -290,6 +290,8 @@ up_pwm_servo_set_rate(unsigned rate)
{
for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++)
up_pwm_servo_set_rate_group_update(i, rate);
+
+ return 0;
}
uint32_t
diff --git a/apps/drivers/stm32/drv_pwm_servo.h b/src/drivers/stm32/drv_pwm_servo.h
similarity index 100%
rename from apps/drivers/stm32/drv_pwm_servo.h
rename to src/drivers/stm32/drv_pwm_servo.h
diff --git a/apps/drivers/stm32/Makefile b/src/drivers/stm32/module.mk
similarity index 89%
rename from apps/drivers/stm32/Makefile
rename to src/drivers/stm32/module.mk
index 4ad57f4135..bb751c7f68 100644
--- a/apps/drivers/stm32/Makefile
+++ b/src/drivers/stm32/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -37,6 +37,7 @@
# Modules in this directory are compiled for all STM32 targets.
#
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
+SRCS = drv_hrt.c \
+ drv_pwm_servo.c
-include $(APPDIR)/mk/app.mk
+INCLUDE_DIRS += $(NUTTX_SRC)/arch/arm/src/stm32 $(NUTTX_SRC)/arch/arm/src/common
diff --git a/src/drivers/stm32/tone_alarm/module.mk b/src/drivers/stm32/tone_alarm/module.mk
new file mode 100644
index 0000000000..827cf30b27
--- /dev/null
+++ b/src/drivers/stm32/tone_alarm/module.mk
@@ -0,0 +1,42 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Tone alarm driver
+#
+
+MODULE_COMMAND = tone_alarm
+
+SRCS = tone_alarm.cpp
+
+INCLUDE_DIRS += $(NUTTX_SRC)/arch/arm/src/stm32 $(NUTTX_SRC)/arch/arm/src/common
diff --git a/apps/drivers/stm32/tone_alarm/tone_alarm.cpp b/src/drivers/stm32/tone_alarm/tone_alarm.cpp
similarity index 99%
rename from apps/drivers/stm32/tone_alarm/tone_alarm.cpp
rename to src/drivers/stm32/tone_alarm/tone_alarm.cpp
index baa652d8ad..ac5511e60a 100644
--- a/apps/drivers/stm32/tone_alarm/tone_alarm.cpp
+++ b/src/drivers/stm32/tone_alarm/tone_alarm.cpp
@@ -494,7 +494,7 @@ ToneAlarm::init()
return ret;
/* configure the GPIO to the idle state */
- stm32_configgpio(GPIO_TONE_ALARM);
+ stm32_configgpio(GPIO_TONE_ALARM_IDLE);
/* clock/power on our timer */
modifyreg32(STM32_RCC_APB1ENR, 0, TONE_ALARM_CLOCK_ENABLE);
@@ -606,6 +606,8 @@ ToneAlarm::start_note(unsigned note)
rEGR = GTIM_EGR_UG; // force a reload of the period
rCCER |= TONE_CCER; // enable the output
+ // configure the GPIO to enable timer output
+ stm32_configgpio(GPIO_TONE_ALARM);
}
void
@@ -616,10 +618,8 @@ ToneAlarm::stop_note()
/*
* Make sure the GPIO is not driving the speaker.
- *
- * XXX this presumes PX4FMU and the onboard speaker driver FET.
*/
- stm32_gpiowrite(GPIO_TONE_ALARM, 0);
+ stm32_configgpio(GPIO_TONE_ALARM_IDLE);
}
void
diff --git a/src/examples/fixedwing_control/main.c b/src/examples/fixedwing_control/main.c
new file mode 100644
index 0000000000..7bf99785cc
--- /dev/null
+++ b/src/examples/fixedwing_control/main.c
@@ -0,0 +1,477 @@
+/****************************************************************************
+ *
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ * Author: Lorenz Meier
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+/**
+ * @file main.c
+ * Implementation of a fixed wing attitude controller. This file is a complete
+ * fixed wing controller flying manual attitude control or auto waypoint control.
+ * There is no need to touch any other system components to extend / modify the
+ * complete control architecture.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* process-specific header files */
+#include "params.h"
+
+/* Prototypes */
+/**
+ * Daemon management function.
+ */
+__EXPORT int ex_fixedwing_control_main(int argc, char *argv[]);
+
+/**
+ * Mainloop of daemon.
+ */
+int fixedwing_control_thread_main(int argc, char *argv[]);
+
+/**
+ * Print the correct usage.
+ */
+static void usage(const char *reason);
+
+void control_attitude(const struct vehicle_attitude_setpoint_s *att_sp, const struct vehicle_attitude_s *att,
+ float speed_body[], float gyro[], struct vehicle_rates_setpoint_s *rates_sp,
+ struct actuator_controls_s *actuators);
+
+void control_heading(const struct vehicle_global_position_s *pos, const struct vehicle_global_position_setpoint_s *sp,
+ const struct vehicle_attitude_s *att, struct vehicle_attitude_setpoint_s *att_sp);
+
+/* Variables */
+static bool thread_should_exit = false; /**< Daemon exit flag */
+static bool thread_running = false; /**< Daemon status flag */
+static int deamon_task; /**< Handle of deamon task / thread */
+static struct params p;
+static struct param_handles ph;
+
+void control_attitude(const struct vehicle_attitude_setpoint_s *att_sp, const struct vehicle_attitude_s *att,
+ float speed_body[], float gyro[], struct vehicle_rates_setpoint_s *rates_sp,
+ struct actuator_controls_s *actuators)
+{
+
+ /*
+ * The PX4 architecture provides a mixer outside of the controller.
+ * The mixer is fed with a default vector of actuator controls, representing
+ * moments applied to the vehicle frame. This vector
+ * is structured as:
+ *
+ * Control Group 0 (attitude):
+ *
+ * 0 - roll (-1..+1)
+ * 1 - pitch (-1..+1)
+ * 2 - yaw (-1..+1)
+ * 3 - thrust ( 0..+1)
+ * 4 - flaps (-1..+1)
+ * ...
+ *
+ * Control Group 1 (payloads / special):
+ *
+ * ...
+ */
+
+ /*
+ * Calculate roll error and apply P gain
+ */
+ float roll_err = att->roll - att_sp->roll_body;
+ actuators->control[0] = roll_err * p.roll_p;
+
+ /*
+ * Calculate pitch error and apply P gain
+ */
+ float pitch_err = att->pitch - att_sp->pitch_body;
+ actuators->control[1] = pitch_err * p.pitch_p;
+}
+
+void control_heading(const struct vehicle_global_position_s *pos, const struct vehicle_global_position_setpoint_s *sp,
+ const struct vehicle_attitude_s *att, struct vehicle_attitude_setpoint_s *att_sp)
+{
+
+ /*
+ * Calculate heading error of current position to desired position
+ */
+
+ /* PX4 uses 1e7 scaled integers to represent global coordinates for max resolution */
+ float bearing = get_bearing_to_next_waypoint(pos->lat/1e7d, pos->lon/1e7d, sp->lat/1e7d, sp->lon/1e7d);
+
+ /* calculate heading error */
+ float yaw_err = att->yaw - bearing;
+ /* apply control gain */
+ att_sp->roll_body = yaw_err * p.hdng_p;
+}
+
+/* Main Thread */
+int fixedwing_control_thread_main(int argc, char *argv[])
+{
+ /* read arguments */
+ bool verbose = false;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose = true;
+ }
+ }
+
+ /* welcome user (warnx prints a line, including an appended\n, with variable arguments */
+ warnx("[example fixedwing control] started");
+
+ /* initialize parameters, first the handles, then the values */
+ parameters_init(&ph);
+ parameters_update(&ph, &p);
+
+ /* declare and safely initialize all structs to zero */
+ struct vehicle_attitude_s att;
+ memset(&att, 0, sizeof(att));
+ struct vehicle_attitude_setpoint_s att_sp;
+ memset(&att_sp, 0, sizeof(att_sp));
+ struct vehicle_rates_setpoint_s rates_sp;
+ memset(&rates_sp, 0, sizeof(rates_sp));
+ struct vehicle_global_position_s global_pos;
+ memset(&global_pos, 0, sizeof(global_pos));
+ struct manual_control_setpoint_s manual_sp;
+ memset(&manual_sp, 0, sizeof(manual_sp));
+ struct vehicle_status_s vstatus;
+ memset(&vstatus, 0, sizeof(vstatus));
+ struct vehicle_global_position_setpoint_s global_sp;
+ memset(&global_sp, 0, sizeof(global_sp));
+
+ /* output structs */
+ struct actuator_controls_s actuators;
+ memset(&actuators, 0, sizeof(actuators));
+
+
+ /* publish actuator controls */
+ for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++) {
+ actuators.control[i] = 0.0f;
+ }
+
+ orb_advert_t actuator_pub = orb_advertise(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, &actuators);
+ orb_advert_t rates_pub = orb_advertise(ORB_ID(vehicle_rates_setpoint), &rates_sp);
+
+ /* subscribe */
+ int att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
+ int att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
+ int global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
+ int manual_sp_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
+ int vstatus_sub = orb_subscribe(ORB_ID(vehicle_status));
+ int global_sp_sub = orb_subscribe(ORB_ID(vehicle_global_position_setpoint));
+ int param_sub = orb_subscribe(ORB_ID(parameter_update));
+
+ /* Setup of loop */
+ float gyro[3] = {0.0f, 0.0f, 0.0f};
+ float speed_body[3] = {0.0f, 0.0f, 0.0f};
+ struct pollfd fds[2] = {{ .fd = param_sub, .events = POLLIN },
+ { .fd = att_sub, .events = POLLIN }};
+
+ while (!thread_should_exit) {
+
+ /*
+ * Wait for a sensor or param update, check for exit condition every 500 ms.
+ * This means that the execution will block here without consuming any resources,
+ * but will continue to execute the very moment a new attitude measurement or
+ * a param update is published. So no latency in contrast to the polling
+ * design pattern (do not confuse the poll() system call with polling).
+ *
+ * This design pattern makes the controller also agnostic of the attitude
+ * update speed - it runs as fast as the attitude updates with minimal latency.
+ */
+ int ret = poll(fds, 2, 500);
+
+ if (ret < 0) {
+ /* poll error, this will not really happen in practice */
+ warnx("poll error");
+
+ } else if (ret == 0) {
+ /* no return value = nothing changed for 500 ms, ignore */
+ } else {
+
+ /* only update parameters if they changed */
+ if (fds[0].revents & POLLIN) {
+ /* read from param to clear updated flag (uORB API requirement) */
+ struct parameter_update_s update;
+ orb_copy(ORB_ID(parameter_update), param_sub, &update);
+
+ /* if a param update occured, re-read our parameters */
+ parameters_update(&ph, &p);
+ }
+
+ /* only run controller if attitude changed */
+ if (fds[1].revents & POLLIN) {
+
+
+ /* Check if there is a new position measurement or position setpoint */
+ bool pos_updated;
+ orb_check(global_pos_sub, &pos_updated);
+ bool global_sp_updated;
+ orb_check(global_sp_sub, &global_sp_updated);
+
+ /* get a local copy of attitude */
+ orb_copy(ORB_ID(vehicle_attitude), att_sub, &att);
+
+ if (global_sp_updated)
+ orb_copy(ORB_ID(vehicle_global_position_setpoint), global_sp_sub, &global_sp);
+
+ if (pos_updated) {
+ orb_copy(ORB_ID(vehicle_global_position), global_pos_sub, &global_pos);
+
+ if (att.R_valid) {
+ speed_body[0] = att.R[0][0] * global_pos.vx + att.R[0][1] * global_pos.vy + att.R[0][2] * global_pos.vz;
+ speed_body[1] = att.R[1][0] * global_pos.vx + att.R[1][1] * global_pos.vy + att.R[1][2] * global_pos.vz;
+ speed_body[2] = att.R[2][0] * global_pos.vx + att.R[2][1] * global_pos.vy + att.R[2][2] * global_pos.vz;
+
+ } else {
+ speed_body[0] = 0;
+ speed_body[1] = 0;
+ speed_body[2] = 0;
+
+ warnx("Did not get a valid R\n");
+ }
+ }
+
+ orb_copy(ORB_ID(manual_control_setpoint), manual_sp_sub, &manual_sp);
+ orb_copy(ORB_ID(vehicle_status), vstatus_sub, &vstatus);
+
+ gyro[0] = att.rollspeed;
+ gyro[1] = att.pitchspeed;
+ gyro[2] = att.yawspeed;
+
+ /* control */
+
+#warning fix this
+#if 0
+ if (vstatus.navigation_state == NAVIGATION_STATE_AUTO_ ||
+ vstatus.navigation_state == NAVIGATION_STATE_STABILIZED) {
+
+ /* simple heading control */
+ control_heading(&global_pos, &global_sp, &att, &att_sp);
+
+ /* nail pitch and yaw (rudder) to zero. This example only controls roll (index 0) */
+ actuators.control[1] = 0.0f;
+ actuators.control[2] = 0.0f;
+
+ /* simple attitude control */
+ control_attitude(&att_sp, &att, speed_body, gyro, &rates_sp, &actuators);
+
+ /* pass through throttle */
+ actuators.control[3] = att_sp.thrust;
+
+ /* set flaps to zero */
+ actuators.control[4] = 0.0f;
+
+ } else if (vstatus.navigation_state == NAVIGATION_STATE_MANUAL) {
+ if (vstatus.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_SAS) {
+
+ /* if the RC signal is lost, try to stay level and go slowly back down to ground */
+ if (vstatus.rc_signal_lost) {
+
+ /* put plane into loiter */
+ att_sp.roll_body = 0.3f;
+ att_sp.pitch_body = 0.0f;
+
+ /* limit throttle to 60 % of last value if sane */
+ if (isfinite(manual_sp.throttle) &&
+ (manual_sp.throttle >= 0.0f) &&
+ (manual_sp.throttle <= 1.0f)) {
+ att_sp.thrust = 0.6f * manual_sp.throttle;
+
+ } else {
+ att_sp.thrust = 0.0f;
+ }
+
+ att_sp.yaw_body = 0;
+
+ // XXX disable yaw control, loiter
+
+ } else {
+
+ att_sp.roll_body = manual_sp.roll;
+ att_sp.pitch_body = manual_sp.pitch;
+ att_sp.yaw_body = 0;
+ att_sp.thrust = manual_sp.throttle;
+ }
+
+ att_sp.timestamp = hrt_absolute_time();
+
+ /* attitude control */
+ control_attitude(&att_sp, &att, speed_body, gyro, &rates_sp, &actuators);
+
+ /* pass through throttle */
+ actuators.control[3] = att_sp.thrust;
+
+ /* pass through flaps */
+ if (isfinite(manual_sp.flaps)) {
+ actuators.control[4] = manual_sp.flaps;
+
+ } else {
+ actuators.control[4] = 0.0f;
+ }
+
+ } else if (vstatus.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_DIRECT) {
+ /* directly pass through values */
+ actuators.control[0] = manual_sp.roll;
+ /* positive pitch means negative actuator -> pull up */
+ actuators.control[1] = manual_sp.pitch;
+ actuators.control[2] = manual_sp.yaw;
+ actuators.control[3] = manual_sp.throttle;
+
+ if (isfinite(manual_sp.flaps)) {
+ actuators.control[4] = manual_sp.flaps;
+
+ } else {
+ actuators.control[4] = 0.0f;
+ }
+ }
+ }
+#endif
+
+ /* publish rates */
+ orb_publish(ORB_ID(vehicle_rates_setpoint), rates_pub, &rates_sp);
+
+ /* sanity check and publish actuator outputs */
+ if (isfinite(actuators.control[0]) &&
+ isfinite(actuators.control[1]) &&
+ isfinite(actuators.control[2]) &&
+ isfinite(actuators.control[3])) {
+ orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
+ }
+ }
+ }
+ }
+
+ printf("[ex_fixedwing_control] exiting, stopping all motors.\n");
+ thread_running = false;
+
+ /* kill all outputs */
+ for (unsigned i = 0; i < NUM_ACTUATOR_CONTROLS; i++)
+ actuators.control[i] = 0.0f;
+
+ orb_publish(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, actuator_pub, &actuators);
+
+ fflush(stdout);
+
+ return 0;
+}
+
+/* Startup Functions */
+
+static void
+usage(const char *reason)
+{
+ if (reason)
+ fprintf(stderr, "%s\n", reason);
+
+ fprintf(stderr, "usage: ex_fixedwing_control {start|stop|status}\n\n");
+ exit(1);
+}
+
+/**
+ * The daemon app only briefly exists to start
+ * the background job. The stack size assigned in the
+ * Makefile does only apply to this management task.
+ *
+ * The actual stack size should be set in the call
+ * to task_create().
+ */
+int ex_fixedwing_control_main(int argc, char *argv[])
+{
+ if (argc < 1)
+ usage("missing command");
+
+ if (!strcmp(argv[1], "start")) {
+
+ if (thread_running) {
+ printf("ex_fixedwing_control already running\n");
+ /* this is not an error */
+ exit(0);
+ }
+
+ thread_should_exit = false;
+ deamon_task = task_spawn("ex_fixedwing_control",
+ SCHED_DEFAULT,
+ SCHED_PRIORITY_MAX - 20,
+ 2048,
+ fixedwing_control_thread_main,
+ (argv) ? (const char **)&argv[2] : (const char **)NULL);
+ thread_running = true;
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "stop")) {
+ thread_should_exit = true;
+ exit(0);
+ }
+
+ if (!strcmp(argv[1], "status")) {
+ if (thread_running) {
+ printf("\tex_fixedwing_control is running\n");
+
+ } else {
+ printf("\tex_fixedwing_control not started\n");
+ }
+
+ exit(0);
+ }
+
+ usage("unrecognized command");
+ exit(1);
+}
+
+
+
diff --git a/src/examples/fixedwing_control/module.mk b/src/examples/fixedwing_control/module.mk
new file mode 100644
index 0000000000..d2c48934fc
--- /dev/null
+++ b/src/examples/fixedwing_control/module.mk
@@ -0,0 +1,41 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Fixedwing Attitude Control Demo / Example Application
+#
+
+MODULE_COMMAND = ex_fixedwing_control
+
+SRCS = main.c \
+ params.c
diff --git a/src/examples/fixedwing_control/params.c b/src/examples/fixedwing_control/params.c
new file mode 100644
index 0000000000..8042c74f5e
--- /dev/null
+++ b/src/examples/fixedwing_control/params.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+ *
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ * Author: Lorenz Meier
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/*
+ * @file params.c
+ *
+ * Parameters for fixedwing demo
+ */
+
+#include "params.h"
+
+/* controller parameters, use max. 15 characters for param name! */
+
+/**
+ *
+ */
+PARAM_DEFINE_FLOAT(EXFW_HDNG_P, 0.2f);
+
+/**
+ *
+ */
+PARAM_DEFINE_FLOAT(EXFW_ROLL_P, 0.2f);
+
+/**
+ *
+ */
+PARAM_DEFINE_FLOAT(EXFW_PITCH_P, 0.2f);
+
+int parameters_init(struct param_handles *h)
+{
+ /* PID parameters */
+ h->hdng_p = param_find("EXFW_HDNG_P");
+ h->roll_p = param_find("EXFW_ROLL_P");
+ h->pitch_p = param_find("EXFW_PITCH_P");
+
+ return OK;
+}
+
+int parameters_update(const struct param_handles *h, struct params *p)
+{
+ param_get(h->hdng_p, &(p->hdng_p));
+ param_get(h->roll_p, &(p->roll_p));
+ param_get(h->pitch_p, &(p->pitch_p));
+
+ return OK;
+}
diff --git a/src/examples/fixedwing_control/params.h b/src/examples/fixedwing_control/params.h
new file mode 100644
index 0000000000..4ae8e90ec4
--- /dev/null
+++ b/src/examples/fixedwing_control/params.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ *
+ * Copyright (c) 2013 PX4 Development Team. All rights reserved.
+ * Author: Lorenz Meier
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/*
+ * @file params.h
+ *
+ * Definition of parameters for fixedwing example
+ */
+
+#include
+
+struct params {
+ float hdng_p;
+ float roll_p;
+ float pitch_p;
+};
+
+struct param_handles {
+ param_t hdng_p;
+ param_t roll_p;
+ param_t pitch_p;
+};
+
+/**
+ * Initialize all parameter handles and values
+ *
+ */
+int parameters_init(struct param_handles *h);
+
+/**
+ * Update all parameters
+ *
+ */
+int parameters_update(const struct param_handles *h, struct params *p);
diff --git a/apps/examples/math_demo/math_demo.cpp b/src/examples/math_demo/math_demo.cpp
similarity index 95%
rename from apps/examples/math_demo/math_demo.cpp
rename to src/examples/math_demo/math_demo.cpp
index a9c5567480..36d3c2e849 100644
--- a/apps/examples/math_demo/math_demo.cpp
+++ b/src/examples/math_demo/math_demo.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
*
- * Copyright (C) 2012 PX4 Development Team. All rights reserved.
- * Author: @author Example User
+ * Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+ * Author: James Goppert
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
/**
* @file math_demo.cpp
+ * @author James Goppert
* Demonstration of math library
*/
diff --git a/apps/drivers/ms5611/Makefile b/src/examples/math_demo/module.mk
similarity index 89%
rename from apps/drivers/ms5611/Makefile
rename to src/examples/math_demo/module.mk
index d8e67cba25..deba13fd08 100644
--- a/apps/drivers/ms5611/Makefile
+++ b/src/examples/math_demo/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,11 +32,10 @@
############################################################################
#
-# MS5611 driver
+# Mathlib / operations demo application
#
-APPNAME = ms5611
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = math_demo
+MODULE_STACKSIZE = 12000
-include $(APPDIR)/mk/app.mk
+SRCS = math_demo.cpp
diff --git a/src/examples/px4_daemon_app/module.mk b/src/examples/px4_daemon_app/module.mk
new file mode 100644
index 0000000000..5f8aa73d57
--- /dev/null
+++ b/src/examples/px4_daemon_app/module.mk
@@ -0,0 +1,40 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Daemon application
+#
+
+MODULE_COMMAND = px4_daemon_app
+
+SRCS = px4_daemon_app.c
diff --git a/apps/examples/px4_deamon_app/px4_deamon_app.c b/src/examples/px4_daemon_app/px4_daemon_app.c
similarity index 100%
rename from apps/examples/px4_deamon_app/px4_deamon_app.c
rename to src/examples/px4_daemon_app/px4_daemon_app.c
diff --git a/apps/examples/math_demo/Makefile b/src/examples/px4_mavlink_debug/module.mk
similarity index 90%
rename from apps/examples/math_demo/Makefile
rename to src/examples/px4_mavlink_debug/module.mk
index a1105899a7..fefd614961 100644
--- a/apps/examples/math_demo/Makefile
+++ b/src/examples/px4_mavlink_debug/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -35,8 +35,6 @@
# Basic example application
#
-APPNAME = math_demo
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 8192
+MODULE_COMMAND = px4_mavlink_debug
-include $(APPDIR)/mk/app.mk
+SRCS = px4_mavlink_debug.c
\ No newline at end of file
diff --git a/apps/examples/px4_mavlink_debug/px4_mavlink_debug.c b/src/examples/px4_mavlink_debug/px4_mavlink_debug.c
similarity index 100%
rename from apps/examples/px4_mavlink_debug/px4_mavlink_debug.c
rename to src/examples/px4_mavlink_debug/px4_mavlink_debug.c
diff --git a/src/examples/px4_simple_app/module.mk b/src/examples/px4_simple_app/module.mk
new file mode 100644
index 0000000000..32b06c3a58
--- /dev/null
+++ b/src/examples/px4_simple_app/module.mk
@@ -0,0 +1,40 @@
+############################################################################
+#
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+#
+# Basic example application
+#
+
+MODULE_COMMAND = px4_simple_app
+
+SRCS = px4_simple_app.c
diff --git a/apps/examples/px4_simple_app/px4_simple_app.c b/src/examples/px4_simple_app/px4_simple_app.c
similarity index 100%
rename from apps/examples/px4_simple_app/px4_simple_app.c
rename to src/examples/px4_simple_app/px4_simple_app.c
diff --git a/apps/mavlink/mavlink_log.h b/src/include/mavlink/mavlink_log.h
similarity index 100%
rename from apps/mavlink/mavlink_log.h
rename to src/include/mavlink/mavlink_log.h
diff --git a/apps/systemlib/visibility.h b/src/include/visibility.h
similarity index 100%
rename from apps/systemlib/visibility.h
rename to src/include/visibility.h
diff --git a/apps/examples/kalman_demo/KalmanNav.cpp b/src/modules/att_pos_estimator_ekf/KalmanNav.cpp
similarity index 99%
rename from apps/examples/kalman_demo/KalmanNav.cpp
rename to src/modules/att_pos_estimator_ekf/KalmanNav.cpp
index 6df454a555..4ef150da1e 100644
--- a/apps/examples/kalman_demo/KalmanNav.cpp
+++ b/src/modules/att_pos_estimator_ekf/KalmanNav.cpp
@@ -355,6 +355,8 @@ int KalmanNav::predictState(float dt)
float LDot = vN / R;
float lDot = vE / (cosLSing * R);
float rotRate = 2 * omega + lDot;
+
+ // XXX position prediction using speed
float vNDot = fN - vE * rotRate * sinL +
vD * LDot;
float vDDot = fD - vE * rotRate * cosL -
diff --git a/apps/examples/kalman_demo/KalmanNav.hpp b/src/modules/att_pos_estimator_ekf/KalmanNav.hpp
similarity index 100%
rename from apps/examples/kalman_demo/KalmanNav.hpp
rename to src/modules/att_pos_estimator_ekf/KalmanNav.hpp
diff --git a/apps/examples/kalman_demo/kalman_demo.cpp b/src/modules/att_pos_estimator_ekf/kalman_main.cpp
similarity index 96%
rename from apps/examples/kalman_demo/kalman_demo.cpp
rename to src/modules/att_pos_estimator_ekf/kalman_main.cpp
index 581b68b016..aebe3d1feb 100644
--- a/apps/examples/kalman_demo/kalman_demo.cpp
+++ b/src/modules/att_pos_estimator_ekf/kalman_main.cpp
@@ -55,7 +55,7 @@ static int deamon_task; /**< Handle of deamon task / thread */
/**
* Deamon management function.
*/
-extern "C" __EXPORT int kalman_demo_main(int argc, char *argv[]);
+extern "C" __EXPORT int att_pos_estimator_ekf_main(int argc, char *argv[]);
/**
* Mainloop of deamon.
@@ -85,7 +85,7 @@ usage(const char *reason)
* The actual stack size should be set in the call
* to task_create().
*/
-int kalman_demo_main(int argc, char *argv[])
+int att_pos_estimator_ekf_main(int argc, char *argv[])
{
if (argc < 1)
diff --git a/apps/drivers/px4fmu/Makefile b/src/modules/att_pos_estimator_ekf/module.mk
similarity index 83%
rename from apps/drivers/px4fmu/Makefile
rename to src/modules/att_pos_estimator_ekf/module.mk
index 7f7c2a7328..21b7c91665 100644
--- a/apps/drivers/px4fmu/Makefile
+++ b/src/modules/att_pos_estimator_ekf/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,13 +32,14 @@
############################################################################
#
-# Interface driver for the PX4FMU board
+# Full attitude / position Extended Kalman Filter
#
-APPNAME = fmu
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+MODULE_COMMAND = att_pos_estimator_ekf
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
+# XXX this might be intended for the spawned deamon, validate
+MODULE_PRIORITY = "SCHED_PRIORITY_MAX-30"
-include $(APPDIR)/mk/app.mk
+SRCS = kalman_main.cpp \
+ KalmanNav.cpp \
+ params.c
diff --git a/apps/examples/kalman_demo/params.c b/src/modules/att_pos_estimator_ekf/params.c
similarity index 100%
rename from apps/examples/kalman_demo/params.c
rename to src/modules/att_pos_estimator_ekf/params.c
diff --git a/apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
similarity index 98%
rename from apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c
rename to src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
index bd972f03f3..8e18c3c9a7 100755
--- a/apps/attitude_estimator_ekf/attitude_estimator_ekf_main.c
+++ b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_main.cpp
@@ -46,7 +46,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -66,11 +65,17 @@
#include
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
#include "codegen/attitudeKalmanfilter_initialize.h"
#include "codegen/attitudeKalmanfilter.h"
#include "attitude_estimator_ekf_params.h"
+#ifdef __cplusplus
+}
+#endif
-__EXPORT int attitude_estimator_ekf_main(int argc, char *argv[]);
+extern "C" __EXPORT int attitude_estimator_ekf_main(int argc, char *argv[]);
static bool thread_should_exit = false; /**< Deamon exit flag */
static bool thread_running = false; /**< Deamon status flag */
@@ -265,10 +270,11 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
/* Main loop*/
while (!thread_should_exit) {
- struct pollfd fds[2] = {
- { .fd = sub_raw, .events = POLLIN },
- { .fd = sub_params, .events = POLLIN }
- };
+ struct pollfd fds[2];
+ fds[0].fd = sub_raw;
+ fds[0].events = POLLIN;
+ fds[1].fd = sub_params;
+ fds[1].events = POLLIN;
int ret = poll(fds, 2, 1000);
if (ret < 0) {
diff --git a/apps/attitude_estimator_ekf/attitude_estimator_ekf_params.c b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_params.c
similarity index 100%
rename from apps/attitude_estimator_ekf/attitude_estimator_ekf_params.c
rename to src/modules/attitude_estimator_ekf/attitude_estimator_ekf_params.c
diff --git a/apps/attitude_estimator_ekf/attitude_estimator_ekf_params.h b/src/modules/attitude_estimator_ekf/attitude_estimator_ekf_params.h
similarity index 100%
rename from apps/attitude_estimator_ekf/attitude_estimator_ekf_params.h
rename to src/modules/attitude_estimator_ekf/attitude_estimator_ekf_params.h
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter.c
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter.h
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.c
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_initialize.h
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.c
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_terminate.h
diff --git a/apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h b/src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h
rename to src/modules/attitude_estimator_ekf/codegen/attitudeKalmanfilter_types.h
diff --git a/apps/attitude_estimator_ekf/codegen/cross.c b/src/modules/attitude_estimator_ekf/codegen/cross.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/cross.c
rename to src/modules/attitude_estimator_ekf/codegen/cross.c
diff --git a/apps/attitude_estimator_ekf/codegen/cross.h b/src/modules/attitude_estimator_ekf/codegen/cross.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/cross.h
rename to src/modules/attitude_estimator_ekf/codegen/cross.h
diff --git a/apps/attitude_estimator_ekf/codegen/eye.c b/src/modules/attitude_estimator_ekf/codegen/eye.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/eye.c
rename to src/modules/attitude_estimator_ekf/codegen/eye.c
diff --git a/apps/attitude_estimator_ekf/codegen/eye.h b/src/modules/attitude_estimator_ekf/codegen/eye.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/eye.h
rename to src/modules/attitude_estimator_ekf/codegen/eye.h
diff --git a/apps/attitude_estimator_ekf/codegen/mrdivide.c b/src/modules/attitude_estimator_ekf/codegen/mrdivide.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/mrdivide.c
rename to src/modules/attitude_estimator_ekf/codegen/mrdivide.c
diff --git a/apps/attitude_estimator_ekf/codegen/mrdivide.h b/src/modules/attitude_estimator_ekf/codegen/mrdivide.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/mrdivide.h
rename to src/modules/attitude_estimator_ekf/codegen/mrdivide.h
diff --git a/apps/attitude_estimator_ekf/codegen/norm.c b/src/modules/attitude_estimator_ekf/codegen/norm.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/norm.c
rename to src/modules/attitude_estimator_ekf/codegen/norm.c
diff --git a/apps/attitude_estimator_ekf/codegen/norm.h b/src/modules/attitude_estimator_ekf/codegen/norm.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/norm.h
rename to src/modules/attitude_estimator_ekf/codegen/norm.h
diff --git a/apps/attitude_estimator_ekf/codegen/rdivide.c b/src/modules/attitude_estimator_ekf/codegen/rdivide.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rdivide.c
rename to src/modules/attitude_estimator_ekf/codegen/rdivide.c
diff --git a/apps/attitude_estimator_ekf/codegen/rdivide.h b/src/modules/attitude_estimator_ekf/codegen/rdivide.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rdivide.h
rename to src/modules/attitude_estimator_ekf/codegen/rdivide.h
diff --git a/apps/attitude_estimator_ekf/codegen/rtGetInf.c b/src/modules/attitude_estimator_ekf/codegen/rtGetInf.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rtGetInf.c
rename to src/modules/attitude_estimator_ekf/codegen/rtGetInf.c
diff --git a/apps/attitude_estimator_ekf/codegen/rtGetInf.h b/src/modules/attitude_estimator_ekf/codegen/rtGetInf.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rtGetInf.h
rename to src/modules/attitude_estimator_ekf/codegen/rtGetInf.h
diff --git a/apps/attitude_estimator_ekf/codegen/rtGetNaN.c b/src/modules/attitude_estimator_ekf/codegen/rtGetNaN.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rtGetNaN.c
rename to src/modules/attitude_estimator_ekf/codegen/rtGetNaN.c
diff --git a/apps/attitude_estimator_ekf/codegen/rtGetNaN.h b/src/modules/attitude_estimator_ekf/codegen/rtGetNaN.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rtGetNaN.h
rename to src/modules/attitude_estimator_ekf/codegen/rtGetNaN.h
diff --git a/apps/attitude_estimator_ekf/codegen/rt_defines.h b/src/modules/attitude_estimator_ekf/codegen/rt_defines.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rt_defines.h
rename to src/modules/attitude_estimator_ekf/codegen/rt_defines.h
diff --git a/apps/attitude_estimator_ekf/codegen/rt_nonfinite.c b/src/modules/attitude_estimator_ekf/codegen/rt_nonfinite.c
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rt_nonfinite.c
rename to src/modules/attitude_estimator_ekf/codegen/rt_nonfinite.c
diff --git a/apps/attitude_estimator_ekf/codegen/rt_nonfinite.h b/src/modules/attitude_estimator_ekf/codegen/rt_nonfinite.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rt_nonfinite.h
rename to src/modules/attitude_estimator_ekf/codegen/rt_nonfinite.h
diff --git a/apps/attitude_estimator_ekf/codegen/rtwtypes.h b/src/modules/attitude_estimator_ekf/codegen/rtwtypes.h
similarity index 100%
rename from apps/attitude_estimator_ekf/codegen/rtwtypes.h
rename to src/modules/attitude_estimator_ekf/codegen/rtwtypes.h
diff --git a/apps/attitude_estimator_ekf/Makefile b/src/modules/attitude_estimator_ekf/module.mk
old mode 100755
new mode 100644
similarity index 85%
rename from apps/attitude_estimator_ekf/Makefile
rename to src/modules/attitude_estimator_ekf/module.mk
index 734af7cc1c..d98647f999
--- a/apps/attitude_estimator_ekf/Makefile
+++ b/src/modules/attitude_estimator_ekf/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -31,11 +31,13 @@
#
############################################################################
-APPNAME = attitude_estimator_ekf
-PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = 2048
+#
+# Attitude estimator (Extended Kalman Filter)
+#
-CSRCS = attitude_estimator_ekf_main.c \
+MODULE_COMMAND = attitude_estimator_ekf
+
+SRCS = attitude_estimator_ekf_main.cpp \
attitude_estimator_ekf_params.c \
codegen/eye.c \
codegen/attitudeKalmanfilter.c \
@@ -47,10 +49,4 @@ CSRCS = attitude_estimator_ekf_main.c \
codegen/rtGetInf.c \
codegen/rtGetNaN.c \
codegen/norm.c \
- codegen/cross.c
-
-
-# XXX this is *horribly* broken
-INCLUDES += $(TOPDIR)/../mavlink/include/mavlink
-
-include $(APPDIR)/mk/app.mk
+ codegen/cross.c
diff --git a/src/modules/commander/accelerometer_calibration.c b/src/modules/commander/accelerometer_calibration.c
new file mode 100644
index 0000000000..231739962c
--- /dev/null
+++ b/src/modules/commander/accelerometer_calibration.c
@@ -0,0 +1,404 @@
+/*
+ * accelerometer_calibration.c
+ *
+ * Copyright (C) 2013 Anton Babushkin. All rights reserved.
+ * Author: Anton Babushkin
+ *
+ * Transform acceleration vector to true orientation and scale
+ *
+ * * * * Model * * *
+ * accel_corr = accel_T * (accel_raw - accel_offs)
+ *
+ * accel_corr[3] - fully corrected acceleration vector in body frame
+ * accel_T[3][3] - accelerometers transform matrix, rotation and scaling transform
+ * accel_raw[3] - raw acceleration vector
+ * accel_offs[3] - acceleration offset vector
+ *
+ * * * * Calibration * * *
+ *
+ * Reference vectors
+ * accel_corr_ref[6][3] = [ g 0 0 ] // nose up
+ * | -g 0 0 | // nose down
+ * | 0 g 0 | // left side down
+ * | 0 -g 0 | // right side down
+ * | 0 0 g | // on back
+ * [ 0 0 -g ] // level
+ * accel_raw_ref[6][3]
+ *
+ * accel_corr_ref[i] = accel_T * (accel_raw_ref[i] - accel_offs), i = 0...5
+ *
+ * 6 reference vectors * 3 axes = 18 equations
+ * 9 (accel_T) + 3 (accel_offs) = 12 unknown constants
+ *
+ * Find accel_offs
+ *
+ * accel_offs[i] = (accel_raw_ref[i*2][i] + accel_raw_ref[i*2+1][i]) / 2
+ *
+ *
+ * Find accel_T
+ *
+ * 9 unknown constants
+ * need 9 equations -> use 3 of 6 measurements -> 3 * 3 = 9 equations
+ *
+ * accel_corr_ref[i*2] = accel_T * (accel_raw_ref[i*2] - accel_offs), i = 0...2
+ *
+ * Solve separate system for each row of accel_T:
+ *
+ * accel_corr_ref[j*2][i] = accel_T[i] * (accel_raw_ref[j*2] - accel_offs), j = 0...2
+ *
+ * A * x = b
+ *
+ * x = [ accel_T[0][i] ]
+ * | accel_T[1][i] |
+ * [ accel_T[2][i] ]
+ *
+ * b = [ accel_corr_ref[0][i] ] // One measurement per axis is enough
+ * | accel_corr_ref[2][i] |
+ * [ accel_corr_ref[4][i] ]
+ *
+ * a[i][j] = accel_raw_ref[i][j] - accel_offs[j], i = 0;2;4, j = 0...2
+ *
+ * Matrix A is common for all three systems:
+ * A = [ a[0][0] a[0][1] a[0][2] ]
+ * | a[2][0] a[2][1] a[2][2] |
+ * [ a[4][0] a[4][1] a[4][2] ]
+ *
+ * x = A^-1 * b
+ *
+ * accel_T = A^-1 * g
+ * g = 9.80665
+ */
+
+#include "accelerometer_calibration.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+void do_accel_calibration(int mavlink_fd);
+int do_accel_calibration_measurements(int mavlink_fd, float accel_offs[3], float accel_scale[3]);
+int detect_orientation(int mavlink_fd, int sub_sensor_combined);
+int read_accelerometer_avg(int sensor_combined_sub, float accel_avg[3], int samples_num);
+int mat_invert3(float src[3][3], float dst[3][3]);
+int calculate_calibration_values(float accel_ref[6][3], float accel_T[3][3], float accel_offs[3], float g);
+
+void do_accel_calibration(int mavlink_fd) {
+ /* announce change */
+ mavlink_log_info(mavlink_fd, "accel calibration started");
+
+ /* measure and calculate offsets & scales */
+ float accel_offs[3];
+ float accel_scale[3];
+ int res = do_accel_calibration_measurements(mavlink_fd, accel_offs, accel_scale);
+
+ if (res == OK) {
+ /* measurements complete successfully, set parameters */
+ if (param_set(param_find("SENS_ACC_XOFF"), &(accel_offs[0]))
+ || param_set(param_find("SENS_ACC_YOFF"), &(accel_offs[1]))
+ || param_set(param_find("SENS_ACC_ZOFF"), &(accel_offs[2]))
+ || param_set(param_find("SENS_ACC_XSCALE"), &(accel_scale[0]))
+ || param_set(param_find("SENS_ACC_YSCALE"), &(accel_scale[1]))
+ || param_set(param_find("SENS_ACC_ZSCALE"), &(accel_scale[2]))) {
+ mavlink_log_critical(mavlink_fd, "ERROR: setting offs or scale failed");
+ }
+
+ int fd = open(ACCEL_DEVICE_PATH, 0);
+ struct accel_scale ascale = {
+ accel_offs[0],
+ accel_scale[0],
+ accel_offs[1],
+ accel_scale[1],
+ accel_offs[2],
+ accel_scale[2],
+ };
+
+ if (OK != ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&ascale))
+ warn("WARNING: failed to set scale / offsets for accel");
+
+ close(fd);
+
+ /* auto-save to EEPROM */
+ int save_ret = param_save_default();
+
+ if (save_ret != 0) {
+ warn("WARNING: auto-save of params to storage failed");
+ }
+
+ mavlink_log_info(mavlink_fd, "accel calibration done");
+ tune_positive();
+ } else {
+ /* measurements error */
+ mavlink_log_info(mavlink_fd, "accel calibration aborted");
+ tune_negative();
+ }
+
+ /* exit accel calibration mode */
+}
+
+int do_accel_calibration_measurements(int mavlink_fd, float accel_offs[3], float accel_scale[3]) {
+ const int samples_num = 2500;
+ float accel_ref[6][3];
+ bool data_collected[6] = { false, false, false, false, false, false };
+ const char *orientation_strs[6] = { "x+", "x-", "y+", "y-", "z+", "z-" };
+
+ /* reset existing calibration */
+ int fd = open(ACCEL_DEVICE_PATH, 0);
+ struct accel_scale ascale_null = {
+ 0.0f,
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ };
+ int ioctl_res = ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&ascale_null);
+ close(fd);
+
+ if (OK != ioctl_res) {
+ warn("ERROR: failed to set scale / offsets for accel");
+ return ERROR;
+ }
+
+ int sensor_combined_sub = orb_subscribe(ORB_ID(sensor_combined));
+ while (true) {
+ bool done = true;
+ char str[80];
+ int str_ptr;
+ str_ptr = sprintf(str, "keep vehicle still:");
+ for (int i = 0; i < 6; i++) {
+ if (!data_collected[i]) {
+ str_ptr += sprintf(&(str[str_ptr]), " %s", orientation_strs[i]);
+ done = false;
+ }
+ }
+ if (done)
+ break;
+ mavlink_log_info(mavlink_fd, str);
+
+ int orient = detect_orientation(mavlink_fd, sensor_combined_sub);
+ if (orient < 0)
+ return ERROR;
+
+ sprintf(str, "meas started: %s", orientation_strs[orient]);
+ mavlink_log_info(mavlink_fd, str);
+ read_accelerometer_avg(sensor_combined_sub, &(accel_ref[orient][0]), samples_num);
+ str_ptr = sprintf(str, "meas result for %s: [ %.2f %.2f %.2f ]", orientation_strs[orient], accel_ref[orient][0], accel_ref[orient][1], accel_ref[orient][2]);
+ mavlink_log_info(mavlink_fd, str);
+ data_collected[orient] = true;
+ tune_neutral();
+ }
+ close(sensor_combined_sub);
+
+ /* calculate offsets and rotation+scale matrix */
+ float accel_T[3][3];
+ int res = calculate_calibration_values(accel_ref, accel_T, accel_offs, CONSTANTS_ONE_G);
+ if (res != 0) {
+ mavlink_log_info(mavlink_fd, "ERROR: calibration values calc error");
+ return ERROR;
+ }
+
+ /* convert accel transform matrix to scales,
+ * rotation part of transform matrix is not used by now
+ */
+ for (int i = 0; i < 3; i++) {
+ accel_scale[i] = accel_T[i][i];
+ }
+
+ return OK;
+}
+
+/*
+ * Wait for vehicle become still and detect it's orientation.
+ *
+ * @return 0..5 according to orientation when vehicle is still and ready for measurements,
+ * ERROR if vehicle is not still after 30s or orientation error is more than 5m/s^2
+ */
+int detect_orientation(int mavlink_fd, int sub_sensor_combined) {
+ struct sensor_combined_s sensor;
+ /* exponential moving average of accel */
+ float accel_ema[3] = { 0.0f, 0.0f, 0.0f };
+ /* max-hold dispersion of accel */
+ float accel_disp[3] = { 0.0f, 0.0f, 0.0f };
+ /* EMA time constant in seconds*/
+ float ema_len = 0.2f;
+ /* set "still" threshold to 0.1 m/s^2 */
+ float still_thr2 = pow(0.1f, 2);
+ /* set accel error threshold to 5m/s^2 */
+ float accel_err_thr = 5.0f;
+ /* still time required in us */
+ int64_t still_time = 2000000;
+ struct pollfd fds[1] = { { .fd = sub_sensor_combined, .events = POLLIN } };
+
+ hrt_abstime t_start = hrt_absolute_time();
+ /* set timeout to 30s */
+ hrt_abstime timeout = 30000000;
+ hrt_abstime t_timeout = t_start + timeout;
+ hrt_abstime t = t_start;
+ hrt_abstime t_prev = t_start;
+ hrt_abstime t_still = 0;
+ while (true) {
+ /* wait blocking for new data */
+ int poll_ret = poll(fds, 1, 1000);
+ if (poll_ret) {
+ orb_copy(ORB_ID(sensor_combined), sub_sensor_combined, &sensor);
+ t = hrt_absolute_time();
+ float dt = (t - t_prev) / 1000000.0f;
+ t_prev = t;
+ float w = dt / ema_len;
+ for (int i = 0; i < 3; i++) {
+ accel_ema[i] = accel_ema[i] * (1.0f - w) + sensor.accelerometer_m_s2[i] * w;
+ float d = (float) sensor.accelerometer_m_s2[i] - accel_ema[i];
+ d = d * d;
+ accel_disp[i] = accel_disp[i] * (1.0f - w);
+ if (d > accel_disp[i])
+ accel_disp[i] = d;
+ }
+ /* still detector with hysteresis */
+ if ( accel_disp[0] < still_thr2 &&
+ accel_disp[1] < still_thr2 &&
+ accel_disp[2] < still_thr2 ) {
+ /* is still now */
+ if (t_still == 0) {
+ /* first time */
+ mavlink_log_info(mavlink_fd, "still...");
+ t_still = t;
+ t_timeout = t + timeout;
+ } else {
+ /* still since t_still */
+ if ((int64_t) t - (int64_t) t_still > still_time) {
+ /* vehicle is still, exit from the loop to detection of its orientation */
+ break;
+ }
+ }
+ } else if ( accel_disp[0] > still_thr2 * 2.0f ||
+ accel_disp[1] > still_thr2 * 2.0f ||
+ accel_disp[2] > still_thr2 * 2.0f) {
+ /* not still, reset still start time */
+ if (t_still != 0) {
+ mavlink_log_info(mavlink_fd, "moving...");
+ t_still = 0;
+ }
+ }
+ } else if (poll_ret == 0) {
+ /* any poll failure for 1s is a reason to abort */
+ mavlink_log_info(mavlink_fd, "ERROR: poll failure");
+ return -3;
+ }
+ if (t > t_timeout) {
+ mavlink_log_info(mavlink_fd, "ERROR: timeout");
+ return -1;
+ }
+ }
+
+ if ( fabs(accel_ema[0] - CONSTANTS_ONE_G) < accel_err_thr &&
+ fabs(accel_ema[1]) < accel_err_thr &&
+ fabs(accel_ema[2]) < accel_err_thr )
+ return 0; // [ g, 0, 0 ]
+ if ( fabs(accel_ema[0] + CONSTANTS_ONE_G) < accel_err_thr &&
+ fabs(accel_ema[1]) < accel_err_thr &&
+ fabs(accel_ema[2]) < accel_err_thr )
+ return 1; // [ -g, 0, 0 ]
+ if ( fabs(accel_ema[0]) < accel_err_thr &&
+ fabs(accel_ema[1] - CONSTANTS_ONE_G) < accel_err_thr &&
+ fabs(accel_ema[2]) < accel_err_thr )
+ return 2; // [ 0, g, 0 ]
+ if ( fabs(accel_ema[0]) < accel_err_thr &&
+ fabs(accel_ema[1] + CONSTANTS_ONE_G) < accel_err_thr &&
+ fabs(accel_ema[2]) < accel_err_thr )
+ return 3; // [ 0, -g, 0 ]
+ if ( fabs(accel_ema[0]) < accel_err_thr &&
+ fabs(accel_ema[1]) < accel_err_thr &&
+ fabs(accel_ema[2] - CONSTANTS_ONE_G) < accel_err_thr )
+ return 4; // [ 0, 0, g ]
+ if ( fabs(accel_ema[0]) < accel_err_thr &&
+ fabs(accel_ema[1]) < accel_err_thr &&
+ fabs(accel_ema[2] + CONSTANTS_ONE_G) < accel_err_thr )
+ return 5; // [ 0, 0, -g ]
+
+ mavlink_log_info(mavlink_fd, "ERROR: invalid orientation");
+
+ return -2; // Can't detect orientation
+}
+
+/*
+ * Read specified number of accelerometer samples, calculate average and dispersion.
+ */
+int read_accelerometer_avg(int sensor_combined_sub, float accel_avg[3], int samples_num) {
+ struct pollfd fds[1] = { { .fd = sensor_combined_sub, .events = POLLIN } };
+ int count = 0;
+ float accel_sum[3] = { 0.0f, 0.0f, 0.0f };
+
+ while (count < samples_num) {
+ int poll_ret = poll(fds, 1, 1000);
+ if (poll_ret == 1) {
+ struct sensor_combined_s sensor;
+ orb_copy(ORB_ID(sensor_combined), sensor_combined_sub, &sensor);
+ for (int i = 0; i < 3; i++)
+ accel_sum[i] += sensor.accelerometer_m_s2[i];
+ count++;
+ } else {
+ return ERROR;
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ accel_avg[i] = accel_sum[i] / count;
+ }
+
+ return OK;
+}
+
+int mat_invert3(float src[3][3], float dst[3][3]) {
+ float det = src[0][0] * (src[1][1] * src[2][2] - src[1][2] * src[2][1]) -
+ src[0][1] * (src[1][0] * src[2][2] - src[1][2] * src[2][0]) +
+ src[0][2] * (src[1][0] * src[2][1] - src[1][1] * src[2][0]);
+ if (det == 0.0)
+ return ERROR; // Singular matrix
+
+ dst[0][0] = (src[1][1] * src[2][2] - src[1][2] * src[2][1]) / det;
+ dst[1][0] = (src[1][2] * src[2][0] - src[1][0] * src[2][2]) / det;
+ dst[2][0] = (src[1][0] * src[2][1] - src[1][1] * src[2][0]) / det;
+ dst[0][1] = (src[0][2] * src[2][1] - src[0][1] * src[2][2]) / det;
+ dst[1][1] = (src[0][0] * src[2][2] - src[0][2] * src[2][0]) / det;
+ dst[2][1] = (src[0][1] * src[2][0] - src[0][0] * src[2][1]) / det;
+ dst[0][2] = (src[0][1] * src[1][2] - src[0][2] * src[1][1]) / det;
+ dst[1][2] = (src[0][2] * src[1][0] - src[0][0] * src[1][2]) / det;
+ dst[2][2] = (src[0][0] * src[1][1] - src[0][1] * src[1][0]) / det;
+
+ return OK;
+}
+
+int calculate_calibration_values(float accel_ref[6][3], float accel_T[3][3], float accel_offs[3], float g) {
+ /* calculate offsets */
+ for (int i = 0; i < 3; i++) {
+ accel_offs[i] = (accel_ref[i * 2][i] + accel_ref[i * 2 + 1][i]) / 2;
+ }
+
+ /* fill matrix A for linear equations system*/
+ float mat_A[3][3];
+ memset(mat_A, 0, sizeof(mat_A));
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ float a = accel_ref[i * 2][j] - accel_offs[j];
+ mat_A[i][j] = a;
+ }
+ }
+
+ /* calculate inverse matrix for A */
+ float mat_A_inv[3][3];
+ if (mat_invert3(mat_A, mat_A_inv) != OK)
+ return ERROR;
+
+ /* copy results to accel_T */
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ /* simplify matrices mult because b has only one non-zero element == g at index i */
+ accel_T[j][i] = mat_A_inv[j][i] * g;
+ }
+ }
+
+ return OK;
+}
diff --git a/src/modules/commander/accelerometer_calibration.h b/src/modules/commander/accelerometer_calibration.h
new file mode 100644
index 0000000000..6a920c4ef1
--- /dev/null
+++ b/src/modules/commander/accelerometer_calibration.h
@@ -0,0 +1,16 @@
+/*
+ * accelerometer_calibration.h
+ *
+ * Copyright (C) 2013 Anton Babushkin. All rights reserved.
+ * Author: Anton Babushkin
+ */
+
+#ifndef ACCELEROMETER_CALIBRATION_H_
+#define ACCELEROMETER_CALIBRATION_H_
+
+#include
+#include
+
+void do_accel_calibration(int mavlink_fd);
+
+#endif /* ACCELEROMETER_CALIBRATION_H_ */
diff --git a/apps/commander/calibration_routines.c b/src/modules/commander/calibration_routines.c
similarity index 100%
rename from apps/commander/calibration_routines.c
rename to src/modules/commander/calibration_routines.c
diff --git a/apps/commander/calibration_routines.h b/src/modules/commander/calibration_routines.h
similarity index 100%
rename from apps/commander/calibration_routines.h
rename to src/modules/commander/calibration_routines.h
diff --git a/apps/commander/commander.c b/src/modules/commander/commander.c
similarity index 86%
rename from apps/commander/commander.c
rename to src/modules/commander/commander.c
index 77853aa7ae..a34e526a8b 100644
--- a/apps/commander/commander.c
+++ b/src/modules/commander/commander.c
@@ -97,7 +97,7 @@
#include
#include "calibration_routines.h"
-
+#include "accelerometer_calibration.h"
PARAM_DEFINE_INT32(SYS_FAILSAVE_LL, 0); /**< Go into low-level failsafe after 0 ms */
//PARAM_DEFINE_INT32(SYS_FAILSAVE_HL, 0); /**< Go into high-level failsafe after 0 ms */
@@ -184,7 +184,6 @@ void do_reboot(void);
void do_gyro_calibration(void);
void do_mag_calibration(void);
void do_rc_calibration(void);
-void do_accel_calibration(void);
void do_airspeed_calibration(void);
@@ -657,113 +656,6 @@ void do_gyro_calibration()
close(sub_sensor_combined);
}
-void do_accel_calibration()
-{
- /* give directions */
- mavlink_log_info(mavlink_fd, "accel calibration starting, keep it level");
-
- const int calibration_count = 2500;
-
- int sub_sensor_combined = orb_subscribe(ORB_ID(sensor_combined));
- struct sensor_combined_s raw;
-
- int calibration_counter = 0;
- float accel_offset[3] = {0.0f, 0.0f, 0.0f};
-
- int fd = open(ACCEL_DEVICE_PATH, 0);
- struct accel_scale ascale_null = {
- 0.0f,
- 1.0f,
- 0.0f,
- 1.0f,
- 0.0f,
- 1.0f,
- };
-
- if (OK != ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&ascale_null))
- warn("WARNING: failed to set scale / offsets for accel");
-
- close(fd);
-
- while (calibration_counter < calibration_count) {
-
- /* wait blocking for new data */
- struct pollfd fds[1] = { { .fd = sub_sensor_combined, .events = POLLIN } };
-
- int poll_ret = poll(fds, 1, 1000);
-
- if (poll_ret) {
- orb_copy(ORB_ID(sensor_combined), sub_sensor_combined, &raw);
- accel_offset[0] += raw.accelerometer_m_s2[0];
- accel_offset[1] += raw.accelerometer_m_s2[1];
- accel_offset[2] += raw.accelerometer_m_s2[2];
- calibration_counter++;
-
- } else if (poll_ret == 0) {
- /* any poll failure for 1s is a reason to abort */
- mavlink_log_info(mavlink_fd, "acceleration calibration aborted");
- return;
- }
- }
-
- accel_offset[0] = accel_offset[0] / calibration_count;
- accel_offset[1] = accel_offset[1] / calibration_count;
- accel_offset[2] = accel_offset[2] / calibration_count;
-
- if (isfinite(accel_offset[0]) && isfinite(accel_offset[1]) && isfinite(accel_offset[2])) {
-
- /* add the removed length from x / y to z, since we induce a scaling issue else */
- float total_len = sqrtf(accel_offset[0] * accel_offset[0] + accel_offset[1] * accel_offset[1] + accel_offset[2] * accel_offset[2]);
-
- /* if length is correct, zero results here */
- accel_offset[2] = accel_offset[2] + total_len;
-
- float scale = 9.80665f / total_len;
-
- if (param_set(param_find("SENS_ACC_XOFF"), &(accel_offset[0]))
- || param_set(param_find("SENS_ACC_YOFF"), &(accel_offset[1]))
- || param_set(param_find("SENS_ACC_ZOFF"), &(accel_offset[2]))
- || param_set(param_find("SENS_ACC_XSCALE"), &(scale))
- || param_set(param_find("SENS_ACC_YSCALE"), &(scale))
- || param_set(param_find("SENS_ACC_ZSCALE"), &(scale))) {
- mavlink_log_critical(mavlink_fd, "Setting offs or scale failed!");
- }
-
- fd = open(ACCEL_DEVICE_PATH, 0);
- struct accel_scale ascale = {
- accel_offset[0],
- scale,
- accel_offset[1],
- scale,
- accel_offset[2],
- scale,
- };
-
- if (OK != ioctl(fd, ACCELIOCSSCALE, (long unsigned int)&ascale))
- warn("WARNING: failed to set scale / offsets for accel");
-
- close(fd);
-
- /* auto-save to EEPROM */
- int save_ret = param_save_default();
-
- if (save_ret != 0) {
- warn("WARNING: auto-save of params to storage failed");
- }
-
- //char buf[50];
- //sprintf(buf, "[cmd] accel cal: x:%8.4f y:%8.4f z:%8.4f\n", (double)accel_offset[0], (double)accel_offset[1], (double)accel_offset[2]);
- //mavlink_log_info(mavlink_fd, buf);
- mavlink_log_info(mavlink_fd, "accel calibration done");
-
- tune_positive();
-
- } else {
- mavlink_log_info(mavlink_fd, "accel calibration FAILED (NaN)");
- }
-
- close(sub_sensor_combined);
-}
void do_airspeed_calibration()
{
@@ -772,22 +664,22 @@ void do_airspeed_calibration()
const int calibration_count = 2500;
- int sub_differential_pressure = orb_subscribe(ORB_ID(differential_pressure));
- struct differential_pressure_s differential_pressure;
+ int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
+ struct differential_pressure_s diff_pres;
int calibration_counter = 0;
- float airspeed_offset = 0.0f;
+ float diff_pres_offset = 0.0f;
while (calibration_counter < calibration_count) {
/* wait blocking for new data */
- struct pollfd fds[1] = { { .fd = sub_differential_pressure, .events = POLLIN } };
+ struct pollfd fds[1] = { { .fd = diff_pres_sub, .events = POLLIN } };
int poll_ret = poll(fds, 1, 1000);
if (poll_ret) {
- orb_copy(ORB_ID(differential_pressure), sub_differential_pressure, &differential_pressure);
- airspeed_offset += differential_pressure.voltage;
+ orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);
+ diff_pres_offset += diff_pres.differential_pressure_pa;
calibration_counter++;
} else if (poll_ret == 0) {
@@ -797,11 +689,11 @@ void do_airspeed_calibration()
}
}
- airspeed_offset = airspeed_offset / calibration_count;
+ diff_pres_offset = diff_pres_offset / calibration_count;
- if (isfinite(airspeed_offset)) {
+ if (isfinite(diff_pres_offset)) {
- if (param_set(param_find("SENS_VAIR_OFF"), &(airspeed_offset))) {
+ if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
mavlink_log_critical(mavlink_fd, "Setting offs failed!");
}
@@ -823,7 +715,7 @@ void do_airspeed_calibration()
mavlink_log_info(mavlink_fd, "airspeed calibration FAILED (NaN)");
}
- close(sub_differential_pressure);
+ close(diff_pres_sub);
}
void handle_command(int status_pub, struct vehicle_status_s *current_vehicle_status, struct vehicle_command_s *cmd)
@@ -925,129 +817,128 @@ void handle_command(int status_pub, struct vehicle_status_s *current_vehicle_sta
// break;
//
/* preflight calibration */
- case VEHICLE_CMD_PREFLIGHT_CALIBRATION: {
+ case VEHICLE_CMD_PREFLIGHT_CALIBRATION:
- /* gyro calibration */
- if ((int)(cmd->param1) == 1) {
+ /* gyro calibration */
+ if ((int)(cmd->param1) == 1) {
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
+ /* check if no other task is scheduled */
+ if(low_prio_task == LOW_PRIO_TASK_NONE) {
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_GYRO_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
+ /* try to go to INIT/PREFLIGHT arming state */
+ if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ result = VEHICLE_CMD_RESULT_ACCEPTED;
+ /* now set the task for the low prio thread */
+ low_prio_task = LOW_PRIO_TASK_GYRO_CALIBRATION;
} else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ result = VEHICLE_CMD_RESULT_DENIED;
}
+ } else {
+ result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
+ }
- /* magnetometer calibration */
- if ((int)(cmd->param2) == 1) {
+ /* magnetometer calibration */
+ if ((int)(cmd->param2) == 1) {
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
+ /* check if no other task is scheduled */
+ if(low_prio_task == LOW_PRIO_TASK_NONE) {
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_MAG_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
+ /* try to go to INIT/PREFLIGHT arming state */
+ if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ result = VEHICLE_CMD_RESULT_ACCEPTED;
+ /* now set the task for the low prio thread */
+ low_prio_task = LOW_PRIO_TASK_MAG_CALIBRATION;
} else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ result = VEHICLE_CMD_RESULT_DENIED;
}
+ } else {
+ result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
+ }
-#if 0
- /* zero-altitude pressure calibration */
- if ((int)(cmd->param3) == 1) {
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
+ // /* zero-altitude pressure calibration */
+ // if ((int)(cmd->param3) == 1) {
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_ALTITUDE_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
+ // /* check if no other task is scheduled */
+ // if(low_prio_task == LOW_PRIO_TASK_NONE) {
+
+ // /* try to go to INIT/PREFLIGHT arming state */
+ // if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ // result = VEHICLE_CMD_RESULT_ACCEPTED;
+ // /* now set the task for the low prio thread */
+ // low_prio_task = LOW_PRIO_TASK_ALTITUDE_CALIBRATION;
+ // } else {
+ // result = VEHICLE_CMD_RESULT_DENIED;
+ // }
+ // } else {
+ // result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ // }
+ // }
+
+
+
+ // /* trim calibration */
+ // if ((int)(cmd->param4) == 1) {
+
+ // /* check if no other task is scheduled */
+ // if(low_prio_task == LOW_PRIO_TASK_NONE) {
+
+ // /* try to go to INIT/PREFLIGHT arming state */
+ // if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ // result = VEHICLE_CMD_RESULT_ACCEPTED;
+ // /* now set the task for the low prio thread */
+ // low_prio_task = LOW_PRIO_TASK_RC_CALIBRATION;
+ // } else {
+ // result = VEHICLE_CMD_RESULT_DENIED;
+ // }
+ // } else {
+ // result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ // }
+ // }
+
+
+ /* accel calibration */
+ if ((int)(cmd->param5) == 1) {
+
+ /* check if no other task is scheduled */
+ if(low_prio_task == LOW_PRIO_TASK_NONE) {
+
+ /* try to go to INIT/PREFLIGHT arming state */
+ if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ result = VEHICLE_CMD_RESULT_ACCEPTED;
+ /* now set the task for the low prio thread */
+ low_prio_task = LOW_PRIO_TASK_ACCEL_CALIBRATION;
} else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ result = VEHICLE_CMD_RESULT_DENIED;
}
+ } else {
+ result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
-#endif
+ }
-#if 0
- /* trim calibration */
- if ((int)(cmd->param4) == 1) {
+ /* airspeed calibration */
+ if ((int)(cmd->param6) == 1) {
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
+ /* check if no other task is scheduled */
+ if(low_prio_task == LOW_PRIO_TASK_NONE) {
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_RC_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
+ /* try to go to INIT/PREFLIGHT arming state */
+ if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
+ result = VEHICLE_CMD_RESULT_ACCEPTED;
+ /* now set the task for the low prio thread */
+ low_prio_task = LOW_PRIO_TASK_AIRSPEED_CALIBRATION;
} else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
- }
- }
-#endif
-
- /* accel calibration */
- if ((int)(cmd->param5) == 1) {
-
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
-
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_ACCEL_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
- } else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
- }
- }
-
- /* airspeed calibration */
- if ((int)(cmd->param6) == 1) {
-
- /* check if no other task is scheduled */
- if(low_prio_task == LOW_PRIO_TASK_NONE) {
-
- /* try to go to INIT/PREFLIGHT arming state */
- if (OK == arming_state_transition(status_pub, current_vehicle_status, ARMING_STATE_INIT, mavlink_fd)) {
- result = VEHICLE_CMD_RESULT_ACCEPTED;
- /* now set the task for the low prio thread */
- low_prio_task = LOW_PRIO_TASK_AIRSPEED_CALIBRATION;
- } else {
- result = VEHICLE_CMD_RESULT_DENIED;
- }
- } else {
- result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
+ result = VEHICLE_CMD_RESULT_DENIED;
}
+ } else {
+ result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
}
break;
- case VEHICLE_CMD_PREFLIGHT_STORAGE: {
+ case VEHICLE_CMD_PREFLIGHT_STORAGE:
if (((int)(cmd->param1)) == 0) {
@@ -1070,12 +961,11 @@ void handle_command(int status_pub, struct vehicle_status_s *current_vehicle_sta
result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
}
- } break;
+ break;
- default: {
- mavlink_log_critical(mavlink_fd, "[cmd] refusing unsupported command");
- result = VEHICLE_CMD_RESULT_UNSUPPORTED;
- }
+ default:
+ mavlink_log_critical(mavlink_fd, "[cmd] refusing unsupported command");
+ result = VEHICLE_CMD_RESULT_UNSUPPORTED;
break;
}
@@ -1422,10 +1312,10 @@ int commander_thread_main(int argc, char *argv[])
struct sensor_combined_s sensors;
memset(&sensors, 0, sizeof(sensors));
- int differential_pressure_sub = orb_subscribe(ORB_ID(differential_pressure));
- struct differential_pressure_s differential_pressure;
- memset(&differential_pressure, 0, sizeof(differential_pressure));
- uint64_t last_differential_pressure_time = 0;
+ int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
+ struct differential_pressure_s diff_pres;
+ memset(&diff_pres, 0, sizeof(diff_pres));
+ uint64_t last_diff_pres_time = 0;
/* Subscribe to command topic */
int cmd_sub = orb_subscribe(ORB_ID(vehicle_command));
@@ -1482,11 +1372,11 @@ int commander_thread_main(int argc, char *argv[])
orb_copy(ORB_ID(sensor_combined), sensor_sub, &sensors);
}
- orb_check(differential_pressure_sub, &new_data);
+ orb_check(diff_pres_sub, &new_data);
if (new_data) {
- orb_copy(ORB_ID(differential_pressure), differential_pressure_sub, &differential_pressure);
- last_differential_pressure_time = differential_pressure.timestamp;
+ orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);
+ last_diff_pres_time = diff_pres.timestamp;
}
orb_check(cmd_sub, &new_data);
@@ -1574,26 +1464,46 @@ int commander_thread_main(int argc, char *argv[])
/* Slow but important 8 Hz checks */
if (counter % ((1000000 / COMMANDER_MONITORING_INTERVAL) / 8) == 0) {
- /* toggle activity (blue) led at 1 Hz in standby, 10 Hz in armed mode */
-// if ((current_status.state_machine == SYSTEM_STATE_GROUND_READY ||
-// current_status.state_machine == SYSTEM_STATE_AUTO ||
-// current_status.state_machine == SYSTEM_STATE_MANUAL)) {
-// /* armed */
- led_toggle(LED_BLUE);
- } else if (counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) {
- /* not armed */
- led_toggle(LED_BLUE);
- }
+ /* XXX if armed */
+ if ((false /*current_status.state_machine == SYSTEM_STATE_GROUND_READY ||
+ current_status.state_machine == SYSTEM_STATE_AUTO ||
+ current_status.state_machine == SYSTEM_STATE_MANUAL*/)) {
+ /* armed, solid */
+ led_on(LED_AMBER);
- /* toggle error led at 5 Hz in HIL mode */
- if (current_status.flag_hil_enabled) {
- /* hil enabled */
- led_toggle(LED_AMBER);
+ } else if (counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) {
+ /* not armed */
+ led_toggle(LED_AMBER);
+ }
- } else if (bat_remain < 0.3f && (low_voltage_counter > LOW_VOLTAGE_BATTERY_COUNTER_LIMIT)) {
- /* toggle error (red) at 5 Hz on low battery or error */
- led_toggle(LED_AMBER);
+ if (hrt_absolute_time() - gps_position.timestamp_position < 2000000) {
+
+ /* toggle GPS (blue) led at 1 Hz if GPS present but no lock, make is solid once locked */
+ if ((hrt_absolute_time() - gps_position.timestamp_position < 2000000)
+ && (gps_position.fix_type == GPS_FIX_TYPE_3D)) {
+ /* GPS lock */
+ led_on(LED_BLUE);
+
+ } else if ((counter + 4) % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0) {
+ /* no GPS lock, but GPS module is aquiring lock */
+ led_toggle(LED_BLUE);
+ }
+
+ } else {
+ /* no GPS info, don't light the blue led */
+ led_off(LED_BLUE);
+ }
+
+ /* toggle GPS led at 5 Hz in HIL mode */
+ if (current_status.flag_hil_enabled) {
+ /* hil enabled */
+ led_toggle(LED_BLUE);
+
+ } else if (bat_remain < 0.3f && (low_voltage_counter > LOW_VOLTAGE_BATTERY_COUNTER_LIMIT)) {
+ /* toggle arming (red) at 5 Hz on low battery or error */
+ led_toggle(LED_AMBER);
+ }
}
@@ -1654,7 +1564,7 @@ int commander_thread_main(int argc, char *argv[])
mavlink_log_critical(mavlink_fd, "[cmd] EMERGENCY! CRITICAL BATTERY!");
current_status.battery_warning = VEHICLE_BATTERY_WARNING_ALERT;
// XXX implement this
-// state_machine_emergency(stat_pub, ¤t_status, mavlink_fd);
+ // state_machine_emergency(stat_pub, ¤t_status, mavlink_fd);
}
critical_voltage_counter++;
@@ -1709,7 +1619,7 @@ int commander_thread_main(int argc, char *argv[])
}
/* Check for valid airspeed/differential pressure measurements */
- if (hrt_absolute_time() - last_differential_pressure_time < 2000000) {
+ if (hrt_absolute_time() - last_diff_pres_time < 2000000) {
current_status.condition_airspeed_valid = true;
} else {
@@ -2228,13 +2138,13 @@ int commander_thread_main(int argc, char *argv[])
// XXX this is missing
/* If full run came back clean, transition to standby */
-// if (current_status.state_machine == SYSTEM_STATE_PREFLIGHT &&
-// current_status.flag_preflight_gyro_calibration == false &&
-// current_status.flag_preflight_mag_calibration == false &&
-// current_status.flag_preflight_accel_calibration == false) {
-// /* All ok, no calibration going on, go to standby */
-// do_state_update(stat_pub, ¤t_status, mavlink_fd, SYSTEM_STATE_STANDBY);
-// }
+ // if (current_status.state_machine == SYSTEM_STATE_PREFLIGHT &&
+ // current_status.flag_preflight_gyro_calibration == false &&
+ // current_status.flag_preflight_mag_calibration == false &&
+ // current_status.flag_preflight_accel_calibration == false) {
+ // /* All ok, no calibration going on, go to standby */
+ // do_state_update(stat_pub, ¤t_status, mavlink_fd, SYSTEM_STATE_STANDBY);
+ // }
/* publish at least with 1 Hz */
if (counter % (1000000 / COMMANDER_MONITORING_INTERVAL) == 0 || state_changed) {
@@ -2323,18 +2233,18 @@ void *commander_low_prio_loop(void *arg)
case LOW_PRIO_TASK_ALTITUDE_CALIBRATION:
-// do_baro_calibration();
+ // do_baro_calibration();
case LOW_PRIO_TASK_RC_CALIBRATION:
-// do_rc_calibration();
+ // do_rc_calibration();
low_prio_task = LOW_PRIO_TASK_NONE;
break;
case LOW_PRIO_TASK_ACCEL_CALIBRATION:
- do_accel_calibration();
+ do_accel_calibration(mavlink_fd);
low_prio_task = LOW_PRIO_TASK_NONE;
break;
diff --git a/apps/commander/commander.h b/src/modules/commander/commander.h
similarity index 100%
rename from apps/commander/commander.h
rename to src/modules/commander/commander.h
diff --git a/apps/drivers/boards/px4fmu/Makefile b/src/modules/commander/module.mk
similarity index 87%
rename from apps/drivers/boards/px4fmu/Makefile
rename to src/modules/commander/module.mk
index 6b183d8d28..fe44e955ad 100644
--- a/apps/drivers/boards/px4fmu/Makefile
+++ b/src/modules/commander/module.mk
@@ -1,6 +1,6 @@
############################################################################
#
-# Copyright (C) 2012 PX4 Development Team. All rights reserved.
+# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -32,10 +32,12 @@
############################################################################
#
-# Board-specific startup code for the PX4FMU
+# Main system state machine
#
-INCLUDES = $(TOPDIR)/arch/arm/src/stm32 $(TOPDIR)/arch/arm/src/common
-LIBNAME = brd_px4fmu
+MODULE_COMMAND = commander
+SRCS = commander.c \
+ state_machine_helper.c \
+ calibration_routines.c \
+ accelerometer_calibration.c
-include $(APPDIR)/mk/app.mk
diff --git a/apps/commander/state_machine_helper.c b/src/modules/commander/state_machine_helper.c
similarity index 98%
rename from apps/commander/state_machine_helper.c
rename to src/modules/commander/state_machine_helper.c
index ba01f84105..daed81553d 100644
--- a/apps/commander/state_machine_helper.c
+++ b/src/modules/commander/state_machine_helper.c
@@ -557,17 +557,20 @@ void state_machine_publish(int status_pub, struct vehicle_status_s *current_stat
orb_publish(ORB_ID(vehicle_status), status_pub, current_status);
}
-//void publish_armed_status(const struct vehicle_status_s *current_status)
-//{
-// struct actuator_armed_s armed;
-// armed.armed = current_status->flag_fmu_armed;
+// void publish_armed_status(const struct vehicle_status_s *current_status)
+// {
+// struct actuator_armed_s armed;
+// armed.armed = current_status->flag_system_armed;
+//
+// /* XXX allow arming by external components on multicopters only if not yet armed by RC */
+// /* XXX allow arming only if core sensors are ok */
+// armed.ready_to_arm = true;
+//
// /* lock down actuators if required, only in HIL */
-// armed.lockdown = (current_status->flag_hil_enabled) ? true : false;
-// orb_advert_t armed_pub = orb_advertise(ORB_ID(actuator_armed), &armed);
-// orb_publish(ORB_ID(actuator_armed), armed_pub, &armed);
-//}
-
-
+// armed.lockdown = (current_status->flag_hil_enabled) ? true : false;
+// orb_advert_t armed_pub = orb_advertise(ORB_ID(actuator_armed), &armed);
+// orb_publish(ORB_ID(actuator_armed), armed_pub, &armed);
+// }
// /*
diff --git a/apps/commander/state_machine_helper.h b/src/modules/commander/state_machine_helper.h
similarity index 100%
rename from apps/commander/state_machine_helper.h
rename to src/modules/commander/state_machine_helper.h
diff --git a/apps/controllib/block/Block.cpp b/src/modules/controllib/block/Block.cpp
similarity index 100%
rename from apps/controllib/block/Block.cpp
rename to src/modules/controllib/block/Block.cpp
diff --git a/apps/controllib/block/Block.hpp b/src/modules/controllib/block/Block.hpp
similarity index 100%
rename from apps/controllib/block/Block.hpp
rename to src/modules/controllib/block/Block.hpp
diff --git a/apps/controllib/block/BlockParam.cpp b/src/modules/controllib/block/BlockParam.cpp
similarity index 100%
rename from apps/controllib/block/BlockParam.cpp
rename to src/modules/controllib/block/BlockParam.cpp
diff --git a/apps/controllib/block/BlockParam.hpp b/src/modules/controllib/block/BlockParam.hpp
similarity index 100%
rename from apps/controllib/block/BlockParam.hpp
rename to src/modules/controllib/block/BlockParam.hpp
diff --git a/apps/controllib/block/List.hpp b/src/modules/controllib/block/List.hpp
similarity index 100%
rename from apps/controllib/block/List.hpp
rename to src/modules/controllib/block/List.hpp
diff --git a/apps/controllib/block/UOrbPublication.cpp b/src/modules/controllib/block/UOrbPublication.cpp
similarity index 100%
rename from apps/controllib/block/UOrbPublication.cpp
rename to src/modules/controllib/block/UOrbPublication.cpp
diff --git a/apps/controllib/block/UOrbPublication.hpp b/src/modules/controllib/block/UOrbPublication.hpp
similarity index 100%
rename from apps/controllib/block/UOrbPublication.hpp
rename to src/modules/controllib/block/UOrbPublication.hpp
diff --git a/apps/controllib/block/UOrbSubscription.cpp b/src/modules/controllib/block/UOrbSubscription.cpp
similarity index 100%
rename from apps/controllib/block/UOrbSubscription.cpp
rename to src/modules/controllib/block/UOrbSubscription.cpp
diff --git a/apps/controllib/block/UOrbSubscription.hpp b/src/modules/controllib/block/UOrbSubscription.hpp
similarity index 100%
rename from apps/controllib/block/UOrbSubscription.hpp
rename to src/modules/controllib/block/UOrbSubscription.hpp
diff --git a/apps/controllib/blocks.cpp b/src/modules/controllib/blocks.cpp
similarity index 100%
rename from apps/controllib/blocks.cpp
rename to src/modules/controllib/blocks.cpp
diff --git a/apps/controllib/blocks.hpp b/src/modules/controllib/blocks.hpp
similarity index 100%
rename from apps/controllib/blocks.hpp
rename to src/modules/controllib/blocks.hpp
diff --git a/apps/controllib/fixedwing.cpp b/src/modules/controllib/fixedwing.cpp
similarity index 85%
rename from apps/controllib/fixedwing.cpp
rename to src/modules/controllib/fixedwing.cpp
index a93181f168..8b0ea2fac6 100644
--- a/apps/controllib/fixedwing.cpp
+++ b/src/modules/controllib/fixedwing.cpp
@@ -57,9 +57,9 @@ BlockYawDamper::BlockYawDamper(SuperBlock *parent, const char *name) :
BlockYawDamper::~BlockYawDamper() {};
-void BlockYawDamper::update(float rCmd, float r)
+void BlockYawDamper::update(float rCmd, float r, float outputScale)
{
- _rudder = _r2Rdr.update(rCmd -
+ _rudder = outputScale*_r2Rdr.update(rCmd -
_rWashout.update(_rLowPass.update(r)));
}
@@ -78,13 +78,13 @@ BlockStabilization::BlockStabilization(SuperBlock *parent, const char *name) :
BlockStabilization::~BlockStabilization() {};
void BlockStabilization::update(float pCmd, float qCmd, float rCmd,
- float p, float q, float r)
+ float p, float q, float r, float outputScale)
{
- _aileron = _p2Ail.update(
+ _aileron = outputScale*_p2Ail.update(
pCmd - _pLowPass.update(p));
- _elevator = _q2Elv.update(
+ _elevator = outputScale*_q2Elv.update(
qCmd - _qLowPass.update(q));
- _yawDamper.update(rCmd, r);
+ _yawDamper.update(rCmd, r, outputScale);
}
BlockWaypointGuidance::BlockWaypointGuidance(SuperBlock *parent, const char *name) :
@@ -157,21 +157,21 @@ BlockMultiModeBacksideAutopilot::BlockMultiModeBacksideAutopilot(SuperBlock *par
_theLimit(this, "THE"),
_vLimit(this, "V"),
- // altitude/roc hold
+ // altitude/climb rate hold
_h2Thr(this, "H2THR"),
- _roc2Thr(this, "ROC2THR"),
+ _cr2Thr(this, "CR2THR"),
// guidance block
_guide(this, ""),
- // block params
- _trimAil(this, "TRIM_ROLL", false), /* general roll trim (full name: TRIM_ROLL) */
- _trimElv(this, "TRIM_PITCH", false), /* general pitch trim */
- _trimRdr(this, "TRIM_YAW", false), /* general yaw trim */
- _trimThr(this, "TRIM_THR", true), /* FWB_ specific throttle trim (full name: FWB_TRIM_THR) */
+ _trimAil(this, "TRIM_ROLL", false), /* general roll trim (full name: TRIM_ROLL) */
+ _trimElv(this, "TRIM_PITCH", false), /* general pitch trim */
+ _trimRdr(this, "TRIM_YAW", false), /* general yaw trim */
+ _trimThr(this, "TRIM_THR"), /* FWB_ specific throttle trim (full name: FWB_TRIM_THR) */
+ _trimV(this, "TRIM_V"), /* FWB_ specific trim velocity (full name : FWB_TRIM_V) */
_vCmd(this, "V_CMD"),
- _rocMax(this, "ROC_MAX"),
+ _crMax(this, "CR_MAX"),
_attPoll(),
_lastPosCmd(),
_timeStamp(0)
@@ -231,7 +231,15 @@ void BlockMultiModeBacksideAutopilot::update()
_guide.update(_pos, _att, _posCmd, _lastPosCmd);
// calculate velocity, XXX should be airspeed, but using ground speed for now
- float v = sqrtf(_pos.vx * _pos.vx + _pos.vy * _pos.vy + _pos.vz * _pos.vz);
+ // for the purpose of control we will limit the velocity feedback between
+ // the min/max velocity
+ float v = _vLimit.update(sqrtf(
+ _pos.vx * _pos.vx +
+ _pos.vy * _pos.vy +
+ _pos.vz * _pos.vz));
+
+ // limit velocity command between min/max velocity
+ float vCmd = _vLimit.update(_vCmd.get());
// altitude hold
float dThrottle = _h2Thr.update(_posCmd.altitude - _pos.alt);
@@ -243,16 +251,19 @@ void BlockMultiModeBacksideAutopilot::update()
// velocity hold
// negative sign because nose over to increase speed
- float thetaCmd = _theLimit.update(-_v2Theta.update(
- _vLimit.update(_vCmd.get()) - v));
+ float thetaCmd = _theLimit.update(-_v2Theta.update(vCmd - v));
float qCmd = _theta2Q.update(thetaCmd - _att.pitch);
// yaw rate cmd
float rCmd = 0;
// stabilization
+ float velocityRatio = _trimV.get()/v;
+ float outputScale = velocityRatio*velocityRatio;
+ // this term scales the output based on the dynamic pressure change from trim
_stabilization.update(pCmd, qCmd, rCmd,
- _att.rollspeed, _att.pitchspeed, _att.yawspeed);
+ _att.rollspeed, _att.pitchspeed, _att.yawspeed,
+ outputScale);
// output
_actuators.control[CH_AIL] = _stabilization.getAileron() + _trimAil.get();
@@ -284,13 +295,18 @@ void BlockMultiModeBacksideAutopilot::update()
// } else if (_status.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_SAS) {
// calculate velocity, XXX should be airspeed, but using ground speed for now
- float v = sqrtf(_pos.vx * _pos.vx + _pos.vy * _pos.vy + _pos.vz * _pos.vz);
+ // for the purpose of control we will limit the velocity feedback between
+ // the min/max velocity
+ float v = _vLimit.update(sqrtf(
+ _pos.vx * _pos.vx +
+ _pos.vy * _pos.vy +
+ _pos.vz * _pos.vz));
// pitch channel -> rate of climb
// TODO, might want to put a gain on this, otherwise commanding
// from +1 -> -1 m/s for rate of climb
- //float dThrottle = _roc2Thr.update(
- //_rocMax.get()*_manual.pitch - _pos.vz);
+ //float dThrottle = _cr2Thr.update(
+ //_crMax.get()*_manual.pitch - _pos.vz);
// roll channel -> bank angle
float phiCmd = _phiLimit.update(_manual.roll * _phiLimit.getMax());
@@ -298,8 +314,10 @@ void BlockMultiModeBacksideAutopilot::update()
// throttle channel -> velocity
// negative sign because nose over to increase speed
- float vCmd = _manual.throttle * (_vLimit.getMax() - _vLimit.getMin()) + _vLimit.getMin();
- float thetaCmd = _theLimit.update(-_v2Theta.update(_vLimit.update(vCmd) - v));
+ float vCmd = _vLimit.update(_manual.throttle *
+ (_vLimit.getMax() - _vLimit.getMin()) +
+ _vLimit.getMin());
+ float thetaCmd = _theLimit.update(-_v2Theta.update(vCmd - v));
float qCmd = _theta2Q.update(thetaCmd - _att.pitch);
// yaw rate cmd
diff --git a/apps/controllib/fixedwing.hpp b/src/modules/controllib/fixedwing.hpp
similarity index 97%
rename from apps/controllib/fixedwing.hpp
rename to src/modules/controllib/fixedwing.hpp
index 281cbb4cb6..53d0cf8935 100644
--- a/apps/controllib/fixedwing.hpp
+++ b/src/modules/controllib/fixedwing.hpp
@@ -193,7 +193,7 @@ public:
* good idea to declare a member to store the temporary
* variable.
*/
- void update(float rCmd, float r);
+ void update(float rCmd, float r, float outputScale = 1.0);
/**
* Rudder output value accessor
@@ -226,7 +226,8 @@ public:
BlockStabilization(SuperBlock *parent, const char *name);
virtual ~BlockStabilization();
void update(float pCmd, float qCmd, float rCmd,
- float p, float q, float r);
+ float p, float q, float r,
+ float outputScale = 1.0);
float getAileron() { return _aileron; }
float getElevator() { return _elevator; }
float getRudder() { return _yawDamper.getRudder(); }
@@ -310,9 +311,9 @@ private:
BlockLimit _theLimit;
BlockLimit _vLimit;
- // altitude/ roc hold
+ // altitude/ climb rate hold
BlockPID _h2Thr;
- BlockPID _roc2Thr;
+ BlockPID _cr2Thr;
// guidance
BlockWaypointGuidance _guide;
@@ -322,8 +323,9 @@ private:
BlockParam _trimElv;
BlockParam