From ea97baa542ddbca6b6db33a5a442c15766a14f3c Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Mon, 19 Jun 2017 13:20:23 +0200
Subject: [PATCH] add axle type to vehicle dialog, write axle type into json
 job, read axle type from json job (optional), changing labels, correction
 enable/disable PTO in declaration mode

---
 VECTO/GUI/VehicleAxleDialog.Designer.vb       | 50 ++++++++++++++-----
 VECTO/GUI/VehicleAxleDialog.vb                | 10 ++++
 VECTO/GUI/VehicleForm.Designer.vb             | 21 +++++---
 VECTO/GUI/VehicleForm.vb                      | 25 +++++++---
 VECTO/Input Files/Vehicle.vb                  | 11 +---
 VECTO/OutputData/JSONFileWriter.vb            |  7 ++-
 .../VectoCommon/Models/AxleConfiguration.cs   | 19 +++++++
 VectoCommon/VectoCommon/Utils/EnumHelper.cs   |  4 +-
 .../InputData/FileIO/JSON/JSONVehicleData.cs  | 14 ++++--
 .../DeclarationDataAdapter.cs                 |  8 +--
 .../SimulationComponent/Data/VehicleData.cs   |  8 +++
 11 files changed, 130 insertions(+), 47 deletions(-)

diff --git a/VECTO/GUI/VehicleAxleDialog.Designer.vb b/VECTO/GUI/VehicleAxleDialog.Designer.vb
index ee8e1bad03..a58d5ba7e9 100644
--- a/VECTO/GUI/VehicleAxleDialog.Designer.vb
+++ b/VECTO/GUI/VehicleAxleDialog.Designer.vb
@@ -56,6 +56,8 @@ Partial Class VehicleAxleDialog
 		Me.Label32 = New System.Windows.Forms.Label()
 		Me.Label8 = New System.Windows.Forms.Label()
 		Me.CbWheels = New System.Windows.Forms.ComboBox()
+		Me.cbAxleType = New System.Windows.Forms.ComboBox()
+		Me.Label11 = New System.Windows.Forms.Label()
 		Me.TableLayoutPanel1.SuspendLayout()
 		Me.PnAxle.SuspendLayout()
 		Me.SuspendLayout()
@@ -68,7 +70,7 @@ Partial Class VehicleAxleDialog
 		Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
 		Me.TableLayoutPanel1.Controls.Add(Me.OK_Button, 0, 0)
 		Me.TableLayoutPanel1.Controls.Add(Me.Cancel_Button, 1, 0)
-		Me.TableLayoutPanel1.Location = New System.Drawing.Point(303, 124)
+		Me.TableLayoutPanel1.Location = New System.Drawing.Point(309, 161)
 		Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
 		Me.TableLayoutPanel1.RowCount = 1
 		Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
@@ -122,7 +124,7 @@ Partial Class VehicleAxleDialog
 		'Label3
 		'
 		Me.Label3.AutoSize = True
-		Me.Label3.Location = New System.Drawing.Point(55, 66)
+		Me.Label3.Location = New System.Drawing.Point(55, 94)
 		Me.Label3.Name = "Label3"
 		Me.Label3.Size = New System.Drawing.Size(51, 13)
 		Me.Label3.TabIndex = 1
@@ -139,7 +141,7 @@ Partial Class VehicleAxleDialog
 		'
 		'TbRRC
 		'
-		Me.TbRRC.Location = New System.Drawing.Point(112, 63)
+		Me.TbRRC.Location = New System.Drawing.Point(112, 91)
 		Me.TbRRC.Name = "TbRRC"
 		Me.TbRRC.Size = New System.Drawing.Size(84, 20)
 		Me.TbRRC.TabIndex = 2
@@ -147,7 +149,7 @@ Partial Class VehicleAxleDialog
 		'Label5
 		'
 		Me.Label5.AutoSize = True
-		Me.Label5.Location = New System.Drawing.Point(67, 91)
+		Me.Label5.Location = New System.Drawing.Point(67, 119)
 		Me.Label5.Name = "Label5"
 		Me.Label5.Size = New System.Drawing.Size(39, 13)
 		Me.Label5.TabIndex = 1
@@ -164,7 +166,7 @@ Partial Class VehicleAxleDialog
 		'
 		'TbFzISO
 		'
-		Me.TbFzISO.Location = New System.Drawing.Point(112, 89)
+		Me.TbFzISO.Location = New System.Drawing.Point(112, 117)
 		Me.TbFzISO.Name = "TbFzISO"
 		Me.TbFzISO.Size = New System.Drawing.Size(84, 20)
 		Me.TbFzISO.TabIndex = 3
@@ -172,7 +174,7 @@ Partial Class VehicleAxleDialog
 		'Label9
 		'
 		Me.Label9.AutoSize = True
-		Me.Label9.Location = New System.Drawing.Point(248, 66)
+		Me.Label9.Location = New System.Drawing.Point(248, 94)
 		Me.Label9.Name = "Label9"
 		Me.Label9.Size = New System.Drawing.Size(146, 13)
 		Me.Label9.TabIndex = 1
@@ -181,7 +183,7 @@ Partial Class VehicleAxleDialog
 		'Label10
 		'
 		Me.Label10.AutoSize = True
-		Me.Label10.Location = New System.Drawing.Point(248, 89)
+		Me.Label10.Location = New System.Drawing.Point(248, 117)
 		Me.Label10.Name = "Label10"
 		Me.Label10.Size = New System.Drawing.Size(167, 26)
 		Me.Label10.TabIndex = 1
@@ -190,7 +192,7 @@ Partial Class VehicleAxleDialog
 		'CbTwinT
 		'
 		Me.CbTwinT.AutoSize = True
-		Me.CbTwinT.Location = New System.Drawing.Point(253, 12)
+		Me.CbTwinT.Location = New System.Drawing.Point(285, 39)
 		Me.CbTwinT.Name = "CbTwinT"
 		Me.CbTwinT.Size = New System.Drawing.Size(78, 17)
 		Me.CbTwinT.TabIndex = 1
@@ -205,7 +207,7 @@ Partial Class VehicleAxleDialog
 		Me.PnAxle.Controls.Add(Me.Label2)
 		Me.PnAxle.Controls.Add(Me.Label32)
 		Me.PnAxle.Controls.Add(Me.TbAxleShare)
-		Me.PnAxle.Location = New System.Drawing.Point(7, 37)
+		Me.PnAxle.Location = New System.Drawing.Point(7, 65)
 		Me.PnAxle.Name = "PnAxle"
 		Me.PnAxle.Size = New System.Drawing.Size(450, 23)
 		Me.PnAxle.TabIndex = 5
@@ -240,26 +242,46 @@ Partial Class VehicleAxleDialog
 		Me.Label8.AutoSize = True
 		Me.Label8.Location = New System.Drawing.Point(4, 13)
 		Me.Label8.Name = "Label8"
-		Me.Label8.Size = New System.Drawing.Size(43, 13)
+		Me.Label8.Size = New System.Drawing.Size(80, 13)
 		Me.Label8.TabIndex = 6
-		Me.Label8.Text = "Wheels"
+		Me.Label8.Text = "Tyre Dimension"
 		'
 		'CbWheels
 		'
 		Me.CbWheels.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
 		Me.CbWheels.FormattingEnabled = True
-		Me.CbWheels.Location = New System.Drawing.Point(53, 10)
+		Me.CbWheels.Location = New System.Drawing.Point(90, 10)
 		Me.CbWheels.Name = "CbWheels"
 		Me.CbWheels.Size = New System.Drawing.Size(176, 21)
 		Me.CbWheels.TabIndex = 7
 		'
+		'cbAxleType
+		'
+		Me.cbAxleType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
+		Me.cbAxleType.FormattingEnabled = True
+		Me.cbAxleType.Location = New System.Drawing.Point(90, 37)
+		Me.cbAxleType.Name = "cbAxleType"
+		Me.cbAxleType.Size = New System.Drawing.Size(176, 21)
+		Me.cbAxleType.TabIndex = 8
+		'
+		'Label11
+		'
+		Me.Label11.AutoSize = True
+		Me.Label11.Location = New System.Drawing.Point(4, 40)
+		Me.Label11.Name = "Label11"
+		Me.Label11.Size = New System.Drawing.Size(69, 13)
+		Me.Label11.TabIndex = 9
+		Me.Label11.Text = "Configuration"
+		'
 		'VehicleAxleDialog
 		'
 		Me.AcceptButton = Me.OK_Button
 		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
 		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
 		Me.CancelButton = Me.Cancel_Button
-		Me.ClientSize = New System.Drawing.Size(461, 165)
+		Me.ClientSize = New System.Drawing.Size(467, 202)
+		Me.Controls.Add(Me.Label11)
+		Me.Controls.Add(Me.cbAxleType)
 		Me.Controls.Add(Me.CbWheels)
 		Me.Controls.Add(Me.Label8)
 		Me.Controls.Add(Me.PnAxle)
@@ -308,5 +330,7 @@ Partial Class VehicleAxleDialog
 	Friend WithEvents Label32 As Label
 	Friend WithEvents Label8 As Label
 	Friend WithEvents CbWheels As ComboBox
+	Friend WithEvents cbAxleType As System.Windows.Forms.ComboBox
+	Friend WithEvents Label11 As System.Windows.Forms.Label
 
 End Class
diff --git a/VECTO/GUI/VehicleAxleDialog.vb b/VECTO/GUI/VehicleAxleDialog.vb
index dc6487f4a4..34a03ae633 100644
--- a/VECTO/GUI/VehicleAxleDialog.vb
+++ b/VECTO/GUI/VehicleAxleDialog.vb
@@ -30,6 +30,16 @@ Public Class VehicleAxleDialog
 
 		CbWheels.Items.Add("-")
 		CbWheels.Items.AddRange(DeclarationData.Wheels.GetWheelsDimensions())
+
+		cbAxleType.Items.Clear()
+		cbAxleType.ValueMember = "Value"
+		cbAxleType.DisplayMember = "Label"
+
+		cbAxleType.DataSource = [Enum].GetValues(GetType(AxleType)) _
+			.Cast(Of AxleType)() _
+			.Where(Function(type) Not Cfg.DeclMode OrElse type <> AxleType.Trailer) _
+			.Select(Function(type) New With {Key .Value = type, .Label = type.GetLabel()}).ToList()
+
 	End Sub
 
 	Public Sub Clear()
diff --git a/VECTO/GUI/VehicleForm.Designer.vb b/VECTO/GUI/VehicleForm.Designer.vb
index 47f013ea6a..ce19738794 100644
--- a/VECTO/GUI/VehicleForm.Designer.vb
+++ b/VECTO/GUI/VehicleForm.Designer.vb
@@ -139,6 +139,7 @@ Partial Class VehicleForm
 		Me.Label17 = New System.Windows.Forms.Label()
 		Me.btDelMaxTorqueEntry = New System.Windows.Forms.Button()
 		Me.btAddMaxTorqueEntry = New System.Windows.Forms.Button()
+		Me.ColumnHeader10 = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
 		Me.GroupBox6.SuspendLayout()
 		Me.ToolStrip1.SuspendLayout()
 		Me.GroupBox7.SuspendLayout()
@@ -169,9 +170,9 @@ Partial Class VehicleForm
 		Me.Label1.AutoSize = True
 		Me.Label1.Location = New System.Drawing.Point(62, 22)
 		Me.Label1.Name = "Label1"
-		Me.Label1.Size = New System.Drawing.Size(104, 13)
+		Me.Label1.Size = New System.Drawing.Size(95, 13)
 		Me.Label1.TabIndex = 0
-		Me.Label1.Text = "Curb Weight Vehicle"
+		Me.Label1.Text = "Curb Mass Vehicle"
 		'
 		'TbMass
 		'
@@ -514,9 +515,9 @@ Partial Class VehicleForm
 		Me.Label46.AutoSize = True
 		Me.Label46.Location = New System.Drawing.Point(6, 5)
 		Me.Label46.Name = "Label46"
-		Me.Label46.Size = New System.Drawing.Size(154, 13)
+		Me.Label46.Size = New System.Drawing.Size(145, 13)
 		Me.Label46.TabIndex = 31
-		Me.Label46.Text = "Curb Weight Extra Trailer/Body"
+		Me.Label46.Text = "Curb Mass Extra Trailer/Body"
 		'
 		'Label50
 		'
@@ -569,7 +570,7 @@ Partial Class VehicleForm
 		'
 		Me.LvRRC.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
 			Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
-		Me.LvRRC.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader7, Me.ColumnHeader8, Me.ColumnHeader2, Me.ColumnHeader9, Me.ColumnHeader1, Me.ColumnHeader3, Me.ColumnHeader4})
+		Me.LvRRC.Columns.AddRange(New System.Windows.Forms.ColumnHeader() {Me.ColumnHeader7, Me.ColumnHeader8, Me.ColumnHeader2, Me.ColumnHeader9, Me.ColumnHeader1, Me.ColumnHeader3, Me.ColumnHeader4, Me.ColumnHeader10})
 		Me.LvRRC.FullRowSelect = True
 		Me.LvRRC.GridLines = True
 		Me.LvRRC.HideSelection = False
@@ -610,7 +611,7 @@ Partial Class VehicleForm
 		'ColumnHeader3
 		'
 		Me.ColumnHeader3.Text = "Wheels"
-		Me.ColumnHeader3.Width = 181
+		Me.ColumnHeader3.Width = 100
 		'
 		'ColumnHeader4
 		'
@@ -923,7 +924,7 @@ Partial Class VehicleForm
 		Me.GroupBox3.Size = New System.Drawing.Size(137, 48)
 		Me.GroupBox3.TabIndex = 6
 		Me.GroupBox3.TabStop = False
-		Me.GroupBox3.Text = "Dynamic Tire Radius"
+		Me.GroupBox3.Text = "Dynamic Tyre Radius"
 		'
 		'GroupBox2
 		'
@@ -1138,6 +1139,11 @@ Partial Class VehicleForm
 		Me.btAddMaxTorqueEntry.TabIndex = 4
 		Me.btAddMaxTorqueEntry.UseVisualStyleBackColor = True
 		'
+		'ColumnHeader10
+		'
+		Me.ColumnHeader10.Text = "Axle Type"
+		Me.ColumnHeader10.Width = 130
+		'
 		'VehicleForm
 		'
 		Me.AcceptButton = Me.ButOK
@@ -1309,4 +1315,5 @@ Partial Class VehicleForm
 	Friend WithEvents lvTorqueLimits As System.Windows.Forms.ListView
 	Friend WithEvents ColumnHeader5 As System.Windows.Forms.ColumnHeader
 	Friend WithEvents ColumnHeader6 As System.Windows.Forms.ColumnHeader
+	Friend WithEvents ColumnHeader10 As System.Windows.Forms.ColumnHeader
 End Class
diff --git a/VECTO/GUI/VehicleForm.vb b/VECTO/GUI/VehicleForm.vb
index 728f981644..df567ac13e 100644
--- a/VECTO/GUI/VehicleForm.vb
+++ b/VECTO/GUI/VehicleForm.vb
@@ -32,6 +32,7 @@ Public Class VehicleForm
 		FzISO = 4
 		WheelsDimension = 5
 		Inertia = 6
+		AxleType = 7
 	End Enum
 
 	Private Enum TorqueLimitsTbl
@@ -163,7 +164,8 @@ Public Class VehicleForm
 			Dim i As Integer
 			If axleCount > i0 Then
 				For i = 1 To axleCount - LvRRC.Items.Count
-					LvRRC.Items.Add(CreateListViewItem(i + i0, Double.NaN, False, Double.NaN, Double.NaN, "", Double.NaN))
+					LvRRC.Items.Add(CreateListViewItem(i + i0, Double.NaN, False, Double.NaN, Double.NaN, "", Double.NaN,
+														AxleType.VehicleNonDriven))
 				Next
 
 			ElseIf axleCount < LvRRC.Items.Count Then
@@ -377,10 +379,10 @@ Public Class VehicleForm
 			If Cfg.DeclMode Then
 				Dim inertia As Double = DeclarationData.Wheels.Lookup(a0.Wheels).Inertia.Value()
 				LvRRC.Items.Add(CreateListViewItem(i, Double.NaN, a0.TwinTyres, a0.RollResistanceCoefficient,
-													a0.TyreTestLoad.Value(), a0.Wheels, inertia))
+													a0.TyreTestLoad.Value(), a0.Wheels, inertia, a0.AxleType))
 			Else
 				LvRRC.Items.Add(CreateListViewItem(i, a0.AxleWeightShare, a0.TwinTyres, a0.RollResistanceCoefficient,
-													a0.TyreTestLoad.Value(), a0.Wheels, a0.Inertia.Value()))
+													a0.TyreTestLoad.Value(), a0.Wheels, a0.Inertia.Value(), a0.AxleType))
 
 			End If
 		Next
@@ -392,7 +394,7 @@ Public Class VehicleForm
 
 		'TbMassExtra.Text = veh.MassExtra.ToGUIFormat()
 
-		TBcdA.Text = airdrag.AirDragArea.ToGUIFormat()
+		TBcdA.Text = If(airdrag.AirDragArea Is Nothing, "", airdrag.AirDragArea.ToGUIFormat())
 
 		cbPTOType.SelectedValue = pto.PTOTransmissionType
 		tbPTOLossMap.Text =
@@ -416,7 +418,7 @@ Public Class VehicleForm
 	End Sub
 
 	Private Function CreateListViewItem(axleNumber As Integer, share As Double, twinTire As Boolean, rrc As Double,
-										fzIso As Double, wheels As String, inertia As Double) As ListViewItem
+										fzIso As Double, wheels As String, inertia As Double, axletype As AxleType) As ListViewItem
 		Dim retVal As New ListViewItem
 		retVal.SubItems(0).Text = axleNumber.ToGUIFormat()
 		FillDoubleValue(retVal, share, "-")
@@ -425,6 +427,7 @@ Public Class VehicleForm
 		FillDoubleValue(retVal, fzIso)
 		retVal.SubItems.Add(wheels)
 		FillDoubleValue(retVal, inertia)
+		retVal.SubItems.Add(axletype.GetLabel())
 		Return retVal
 	End Function
 
@@ -447,7 +450,7 @@ Public Class VehicleForm
 		veh.MassExtra = TbMassExtra.Text.ToDouble(0)
 		veh.Loading = TbLoad.Text.ToDouble(0)
 
-		veh.CdA0 = TBcdA.Text.ToDouble(0)
+		veh.CdA0 = If(String.IsNullOrWhiteSpace(TBcdA.Text), Double.NaN, TBcdA.Text.ToDouble(0))
 
 		veh.DynamicTyreRadius = TBrdyn.Text.ToDouble(0)
 		veh.CrossWindCorrectionMode = CType(CbCdMode.SelectedValue, CrossWindCorrectionMode)
@@ -470,6 +473,7 @@ Public Class VehicleForm
 			a0.TyreTestLoad = entry.SubItems(AxleTbl.FzISO).Text.ToDouble(0).SI(Of Newton)()
 			a0.Wheels = entry.SubItems(AxleTbl.WheelsDimension).Text
 			a0.Inertia = entry.SubItems(AxleTbl.Inertia).Text.ToDouble(0).SI(Of KilogramSquareMeter)()
+			a0.AxleType = entry.SubItems(AxleTbl.AxleType).Text.ParseEnum(Of AxleType)()
 			veh.Axles.Add(a0)
 		Next
 
@@ -683,7 +687,7 @@ Public Class VehicleForm
 		If _axlDlog.ShowDialog = DialogResult.OK Then
 			LvRRC.Items.Add(CreateListViewItem(LvRRC.Items.Count + 1, _axlDlog.TbAxleShare.Text.ToDouble(0),
 												_axlDlog.CbTwinT.Checked, _axlDlog.TbRRC.Text.ToDouble(0), _axlDlog.TbFzISO.Text.ToDouble(0),
-												_axlDlog.CbWheels.Text, _axlDlog.TbI_wheels.Text.ToDouble(0)))
+												_axlDlog.CbWheels.Text, _axlDlog.TbI_wheels.Text.ToDouble(0), AxleType.VehicleNonDriven))
 			Change()
 			DeclInit()
 
@@ -747,6 +751,7 @@ Public Class VehicleForm
 		_axlDlog.TbFzISO.Text = lv0.SubItems(AxleTbl.FzISO).Text
 		_axlDlog.TbI_wheels.Text = lv0.SubItems(AxleTbl.Inertia).Text
 		_axlDlog.CbWheels.Text = lv0.SubItems(AxleTbl.WheelsDimension).Text
+		_axlDlog.cbAxleType.SelectedValue = lv0.SubItems(AxleTbl.AxleType).Text.ParseEnum(Of AxleType)()
 
 		If _axlDlog.ShowDialog = DialogResult.OK Then
 			lv0.SubItems(AxleTbl.RelativeLoad).Text = _axlDlog.TbAxleShare.Text
@@ -759,7 +764,7 @@ Public Class VehicleForm
 			lv0.SubItems(AxleTbl.FzISO).Text = _axlDlog.TbFzISO.Text
 			lv0.SubItems(AxleTbl.WheelsDimension).Text = _axlDlog.CbWheels.Text
 			lv0.SubItems(AxleTbl.Inertia).Text = _axlDlog.TbI_wheels.Text
-
+			lv0.SubItems(AxleTbl.AxleType).Text = CType(_axlDlog.cbAxleType.SelectedValue, AxleType).GetLabel()
 			Change()
 			DeclInit()
 		End If
@@ -825,6 +830,10 @@ Public Class VehicleForm
 
 	Private Sub cbPTOType_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbPTOType.SelectedIndexChanged
 
+		If (Cfg.DeclMode) Then
+			Exit Sub
+		End If
+
 		If (cbPTOType.SelectedIndex = 0) Then
 			pnPTO.Enabled = False
 			tbPTOLossMap.Text = ""
diff --git a/VECTO/Input Files/Vehicle.vb b/VECTO/Input Files/Vehicle.vb
index 79f729d7bf..ed421e8b2c 100644
--- a/VECTO/Input Files/Vehicle.vb	
+++ b/VECTO/Input Files/Vehicle.vb	
@@ -63,15 +63,6 @@ Public Class Vehicle
 	Public ReadOnly PtoCycle As SubPath
 	Public torqueLimitsList As List(Of ITorqueLimitInputData)
 
-	Public Class Axle
-		Public RRC As Double
-		Public Share As Double
-		Public TwinTire As Boolean
-		Public FzISO As Double
-		Public Wheels As String
-		Public Inertia As Double
-	End Class
-
 
 	Public Sub New()
 		_path = ""
@@ -368,7 +359,7 @@ Public Class Vehicle
 
 	Public ReadOnly Property AirDragArea As SquareMeter Implements IAirdragEngineeringInputData.AirDragArea
 		Get
-			Return CdA0.SI(Of SquareMeter)()
+			Return If(Double.IsNaN(CdA0), Nothing, CdA0.SI(Of SquareMeter)())
 		End Get
 	End Property
 
diff --git a/VECTO/OutputData/JSONFileWriter.vb b/VECTO/OutputData/JSONFileWriter.vb
index 6db99d6830..69fcd45e9e 100644
--- a/VECTO/OutputData/JSONFileWriter.vb
+++ b/VECTO/OutputData/JSONFileWriter.vb
@@ -206,7 +206,6 @@ Public Class JSONFileWriter
 				{"CurbWeightExtra", vehicle.CurbMassExtra.Value()},
 				{"Loading", vehicle.Loading.Value()},
 				{"MassMax", vehicle.GrossVehicleMassRating.ConvertTo().Ton.Value()},
-				{"CdA", airdrag.AirDragArea.Value()},
 				{"rdyn", vehicle.DynamicTyreRadius.ConvertTo().Milli.Meter.Value()},
 				{"CdCorrMode", airdrag.CrossWindCorrectionMode.GetName()},
 				{"CdCorrFile",
@@ -227,9 +226,13 @@ Public Class JSONFileWriter
 				{"AxleWeightShare", axle.AxleWeightShare},
 				{"TwinTyres", axle.TwinTyres},
 				{"RRCISO", axle.RollResistanceCoefficient},
-				{"FzISO", axle.TyreTestLoad.Value()}
+				{"FzISO", axle.TyreTestLoad.Value()},
+				{"Type", axle.AxleType.ToString()}
 				}}}}}
 
+		If (Not IsNothing(airdrag.AirDragArea)) Then
+			body("CdA") = airdrag.AirDragArea.Value()
+		End If
 		WriteFile(header, body, filename)
 	End Sub
 
diff --git a/VectoCommon/VectoCommon/Models/AxleConfiguration.cs b/VectoCommon/VectoCommon/Models/AxleConfiguration.cs
index 7317e3aa7a..8bfd04e068 100644
--- a/VectoCommon/VectoCommon/Models/AxleConfiguration.cs
+++ b/VectoCommon/VectoCommon/Models/AxleConfiguration.cs
@@ -29,6 +29,8 @@
 *   Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
 */
 
+using System;
+using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using TUGraz.VectoCommon.Utils;
 
@@ -55,6 +57,23 @@ namespace TUGraz.VectoCommon.Models
 		Trailer
 	}
 
+	public static class AxleTypeHelper
+	{
+		public static string GetLabel(this AxleType self)
+		{
+			switch (self) {
+				case AxleType.VehicleDriven:
+					return "Vehicle driven";
+				case AxleType.VehicleNonDriven:
+					return "Vehicle non-driven";
+				case AxleType.Trailer:
+					return "Trailer";
+				default:
+					throw new ArgumentOutOfRangeException("self", self, null);
+			}
+		}
+	}
+
 	public static class AxleConfigurationHelper
 	{
 		private const string Prefix = "AxleConfig_";
diff --git a/VectoCommon/VectoCommon/Utils/EnumHelper.cs b/VectoCommon/VectoCommon/Utils/EnumHelper.cs
index 965a26231e..6090b81e9b 100644
--- a/VectoCommon/VectoCommon/Utils/EnumHelper.cs
+++ b/VectoCommon/VectoCommon/Utils/EnumHelper.cs
@@ -32,6 +32,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text.RegularExpressions;
 
 namespace TUGraz.VectoCommon.Utils
 {
@@ -39,7 +40,8 @@ namespace TUGraz.VectoCommon.Utils
 	{
 		public static T ParseEnum<T>(this string s, bool ignoreCase = true)
 		{
-			return (T)Enum.Parse(typeof(T), s.RemoveWhitespace(), ignoreCase);
+			var r = new Regex("[^a-zA-Z0-9_]");
+			return (T)Enum.Parse(typeof(T), r.Replace(s, ""), ignoreCase);
 		}
 
 		public static IEnumerable<T> GetValues<T>()
diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs
index e8c4a01dce..04f9e81a99 100644
--- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs
+++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs
@@ -142,7 +142,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 		{
 			return
 				Body.GetEx(JsonKeys.Vehicle_AxleConfiguration).GetEx(JsonKeys.Vehicle_AxleConfiguration_Axles).Select(
-					axle => new AxleInputData {
+					(axle, idx) => new AxleInputData {
 						SourceType = DataSourceType.JSONFile,
 						Source = Source,
 						Inertia = axle.GetEx<double>(JsonKeys.Vehicle_Axles_Inertia).SI<KilogramSquareMeter>(),
@@ -150,7 +150,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 						TwinTyres = axle.GetEx<bool>(JsonKeys.Vehicle_Axles_TwinTyres),
 						RollResistanceCoefficient = axle.GetEx<double>(JsonKeys.Vehicle_Axles_RollResistanceCoefficient),
 						TyreTestLoad = axle.GetEx<double>(JsonKeys.Vehicle_Axles_TyreTestLoad).SI<Newton>(),
-						AxleWeightShare = axle.GetEx<double>("AxleWeightShare")
+						AxleWeightShare = axle.GetEx<double>("AxleWeightShare"),
+						AxleType =
+							axle["Type"] != null
+								? axle.GetEx<string>("Type").ParseEnum<AxleType>()
+								: (idx == 1 ? AxleType.VehicleDriven : AxleType.VehicleNonDriven)
 					});
 		}
 
@@ -160,7 +164,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 
 		public virtual SquareMeter AirDragArea
 		{
-			get { return Body.GetEx<double>(JsonKeys.Vehicle_DragCoefficient).SI<SquareMeter>(); }
+			get {
+				return Body[JsonKeys.Vehicle_DragCoefficient] == null
+					? null
+					: Body.GetEx<double>(JsonKeys.Vehicle_DragCoefficient).SI<SquareMeter>();
+			}
 		}
 
 		public virtual CrossWindCorrectionMode CrossWindCorrectionMode
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
index d89d573859..a9f500f1a6 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
@@ -243,7 +243,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				var gear = gearsInput[(int)i];
 				var lossMap = CreateGearLossMap(gear, i, useEfficiencyFallback, true);
 
-				var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(gearbox.Type, (int)i, engine.FullLoadCurves[i+1], gearsInput, engine,
+				var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(gearbox.Type, (int)i, engine.FullLoadCurves[i + 1],
+					gearsInput, engine,
 					axlegearRatio, dynamicTyreRadius);
 
 				var gearData = new GearData {
@@ -278,7 +279,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				var ratio = double.IsNaN(retVal.Gears[1].Ratio) ? 1 : retVal.Gears[1].TorqueConverterRatio / retVal.Gears[1].Ratio;
 				retVal.PowershiftShiftTime = DeclarationData.Gearbox.PowershiftShiftTime;
 				retVal.TorqueConverterData = TorqueConverterDataReader.Create(gearbox.TorqueConverter.TCData,
-					DeclarationData.TorqueConverter.ReferenceRPM, DeclarationData.TorqueConverter.MaxInputSpeed, ExecutionMode.Declaration, ratio,
+					DeclarationData.TorqueConverter.ReferenceRPM, DeclarationData.TorqueConverter.MaxInputSpeed,
+					ExecutionMode.Declaration, ratio,
 					DeclarationData.TorqueConverter.CLUpshiftMinAcceleration, DeclarationData.TorqueConverter.CCUpshiftMinAcceleration);
 			}
 
@@ -443,7 +445,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 		public AirdragData CreateAirdragData(IAirdragDeclarationInputData airdragInputData, Mission mission,
 			Segment segment)
 		{
-			if (airdragInputData == null) {
+			if (airdragInputData == null || airdragInputData.AirDragArea == null) {
 				return DefaultAirdragData(mission, segment);
 			}
 
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
index 23baa05605..5dc0905838 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/VehicleData.cs
@@ -240,6 +240,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 				}
 			}
 
+
 			if (vehicleData.TotalRollResistanceCoefficient <= 0) {
 				return
 					new ValidationResult(string.Format("Total rolling resistance must be greater than 0! {0}",
@@ -268,6 +269,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 					string.Format("Total Vehicle Weight is greater than GrossVehicleWeight! Weight: {0},  GVW: {1}",
 						vehicleData.TotalVehicleWeight, gvwTotal));
 			}
+
+			var numDrivenAxles = vehicleData._axleData.Count(x => x.AxleType == AxleType.VehicleDriven);
+			if (numDrivenAxles != 1) {
+				return new ValidationResult("Exactly one axle has to be defined as driven!");
+			}
+
+
 			return ValidationResult.Success;
 		}
 	}
-- 
GitLab