示例#1
0
      private void btnExtract_Click(object sender, EventArgs e) {
         this.DispatchToBackground(() => {
            var A = new List<AnalyzedActivity>();
            using (var dbConn = DatabaseManager.DbConn()) {

               A.AddRange(dbConn.ExecuteBpl(new TelemetryVehicleActivityGetAll()).Select(a => new AnalyzedActivity { Activity = a }));
               _report("Activities: {0}", A.Count);

               for (var i = 0; i < A.Count; i++) {
                  var a = A[i];
                  a.StartMeters = dbConn.ExecuteBpl(new TelemetryVehicleActivityMetersGetByActivityIdType { ActivityId = a.Activity.ActivityId, RecordType = VehicleMetersRecordType.StartMeters });
                  a.FinishMeters = dbConn.ExecuteBpl(new TelemetryVehicleActivityMetersGetByActivityIdType { ActivityId = a.Activity.ActivityId, RecordType = VehicleMetersRecordType.FinishMeters });
               }
               A.RemoveAll(a => a.Activity.ActivityType != VehicleMode.Driving || (a.FinishMeters.Odometer - a.StartMeters.Odometer) < (Distance)10);
               _report("Usable driving activities: {0}", A.Count);

               var AA = A.ToDictionary(a => a.Activity.ActivityId.ToString(false));

               var T = dbConn.ExecuteBpl(new TelemetryGetAll());
               _report("Records: {0}", T.Count);

               var TT = new Dictionary<string, VehicleTelemetry>();
               for (var i = 0; i < T.Count; i++) {
                  var dbt = T[i];
                  if (!dbt.Telemetry.IsManaged) continue;

                  var a = AA.TryGet(dbt.Telemetry.ActivityId.ToString(false));
                  if (a == null) continue;

                  var t = TT.TryGet(dbt.TelemetryId.ToString(false));
                  if (t == null) {
                     t = dbt.Telemetry;
                     a.Telemetry.Add(t);
                     TT.Add(dbt.TelemetryId.ToString(false), t);
                  }
                  t.FutureDrivingSteps.Add(dbt.Step);
               }
            }
            A.RemoveAll(a => a.Telemetry.Count == 0);
            _report("Usable planned driving Activities: {0}", A.Count);

            // fix: all key in DB are 0 due to client bug in 2.9.7 (fixed in 2.9.8)
            foreach (var a in A) {
               // Log.Info("Activity: {0}, {1} records", a.Activity.ActivityId, a.Telemetry.Count);
               var lastDta = Distance.Undefined;
               var lastIndex = -1;
               var firstStepKey = -1;
               foreach (var t in a.Telemetry) {
                  // Log.Info("     #{0} | {1} | Planned:{2} | {3} - O:{4}, S:{5}, i:{6}", t.RecordNo, t.TimeStamp, t.IsManaged, t.RecordType, t.Odometer, t.Battery.Soc, t.DrivingSegmentIndex);
                  var stepCount = t.FutureDrivingSteps.Count;
                  if (stepCount == 0) {
                     lastDta = Distance.Undefined;
                     lastIndex = -1;
                     firstStepKey = -1;
                     continue;
                  }

                  if (t.RecordType == TelemetryRecordType.DrivingPlanChanged || firstStepKey == -1 || lastIndex == -1) {
                     lastDta = t.FutureDrivingSteps[0].Dta;
                     lastIndex = t.DrivingSegmentIndex;
                     firstStepKey = (int)Distance.ToMeters(t.FutureDrivingSteps[0].Dta);
                  }

                  // fix rule is: 
                  // - if index is 0, plan may change, so unless dDistance is 0 or very small - assume plan change
                  // - if index dropped (from X to 0) - assume plan change
                  // - some times index is dropped, but a bit later, so look at large dDistance change, as a fallback
                  //   (this is heuristics, but this is the best possible one, even though it's not precise - it's helpful sometimes)
                  // - distance in meters used as a key, to fight cases with round-trip route where two steps have very similar distance (in meters - it will be different)
                  //
                  var dta = t.FutureDrivingSteps[0].Dta;
                  var index = t.DrivingSegmentIndex;
                  var ddta = (dta - lastDta).Abs();
                  var dindex = (index - lastIndex);
                  if ((index == 0 && ddta < (Distance)0.5) || dindex < 0 || ddta > (Distance)2) {
                     firstStepKey = (int)Distance.ToMeters(t.FutureDrivingSteps[0].Dta);
                  }
                  lastDta = dta;
                  lastIndex = index;

                  t.FutureDrivingSteps[0].Key = firstStepKey;
                  for (var i = 1; i < t.FutureDrivingSteps.Count; i++) {
                     t.FutureDrivingSteps[i].Key = (int)Distance.ToMeters(t.FutureDrivingSteps[i].Dta);
                  }
                  /*
                  var str = "";
                  foreach (var s in t.FutureDrivingSteps) {
                     str += "{0,7:#.000} | {1,6}, ".Substitute((double)s.Dta, s.Key);
                  }
                  Log.Info("         {0}", str);
                  */
               }
            }
            _report("Key fix applied");

            _report("Saving extracted activities");
            _activitiesList = new AnalyzedActivityList();
            _activitiesList.Activities.AddRange(A);
            var formatter = BplXmlFormatter.Minimal;
            formatter.Format(_activitiesList);
            var xml = formatter.Output;
            File.WriteAllText("extracted.bpl", xml);
            _report("Extracting done");
         });
      }
示例#2
0
      private void btnAnalyze_Click(object sender, EventArgs e) {
         this.DispatchToBackground(() => {
            if (_activitiesList == null) {
               _report("Reading extracted activities");
               var xml = File.ReadAllText("extracted.bpl");
               var parser = new BplXmlParser();
               parser.Parse(xml);
               _activitiesList = parser.Output as AnalyzedActivityList;
            }
            var A = _activitiesList.Activities;

            // create list of activities with telemetry segments longer than 10km of driving without structured plan changes
            _report("Start Analyzing. Total activities {0}", A.Count);
            var partSize = (Distance)20;
            var activities = new List<AnalyzedActivity>();
            foreach (var a in A) {
               var telemetry = new List<VehicleTelemetry>();

               Action tryAdd = () => {
                  // plan change - measure part size, and if too short - clear and ignore
                  var t0 = telemetry.FirstOrDefault();
                  var t1 = telemetry.LastOrDefault();
                  if (t0 == null || t1 == null) return;
                  var d = t1.Odometer - t0.Odometer;
                  if (d < partSize) {
                     telemetry.Clear();
                     return;
                  }

                  var anew = new AnalyzedActivity { Activity = a.Activity.Clone() };
                  anew.Telemetry.AddRange(telemetry);
                  activities.Add(anew);
                  telemetry.Clear();
               };

               var tryadded = false;
               var partStarted = false;
               var lastKey = -1;
               for (var i = 0; i < a.Telemetry.Count; i++) {
                  var t = a.Telemetry[i];
                  if (t.RecordType != TelemetryRecordType.DrivingPlanChanged && t.RecordType != TelemetryRecordType.DrivingRoadSegmentPassed) continue;

                  // skip anything before first plan creation
                  if (!partStarted) {
                     if (t.RecordType == TelemetryRecordType.DrivingPlanChanged) partStarted = true;
                     continue;
                  }

                  if (lastKey == -1) {
                     var s = t.FutureDrivingSteps.FirstOrDefault();
                     if (s == null) continue;
                     lastKey = s.Key;
                  }

                  // aggregate telemetry (with nearest destination only) as long as there's no plan change
                  if (t.RecordType == TelemetryRecordType.DrivingRoadSegmentPassed) {
                     var tnew = t.Clone();
                     if (tnew.OriginalDrivingSegmentEstimates.Eea.IsUndefined) continue;
                     var snew = tnew.FutureDrivingSteps.FirstOrDefault().Clone();
                     if (snew == null) continue;

                     if (snew.Key == lastKey) {
                        tnew.FutureDrivingSteps.Clear();
                        tnew.FutureDrivingSteps.Add(snew);
                        telemetry.Add(tnew);
                        continue;
                     }
                     lastKey = snew.Key;
                  } else if (t.RecordType == TelemetryRecordType.DrivingPlanChanged) {
                     var s = t.FutureDrivingSteps.FirstOrDefault();
                     if (s == null) continue;
                     lastKey = s.Key;
                  }

                  tryAdd();
                  tryadded = true;
               }
               if (!tryadded) tryAdd(); // try add remainings
            }
            _report("Done Analyzing. {0} - long usable planned driving activities: {1}", partSize, activities.Count);

            foreach (var a in activities) {
               var t0 = a.Telemetry.First();
               var t1 = a.Telemetry.Last();

               var slopeU = 0.0;
               var slenU = 0.0;
               var slopeD = 0.0;
               var slenD = 0.0;
               a.Telemetry.Apply(t => {
                  var s = t.Segment;
                  if (s.Slope > (Percent)0.04) {
                     slopeU = (slopeU * slenU + (double)s.Slope * (double)s.Length) / (slenU + (double)s.Length);
                     slenU += (double)s.Length;
                  } else if (s.Slope < (Percent)(-0.04)) {
                     slopeD = (slopeD * slenD + (double)s.Slope * (double)s.Length) / (slenD + (double)s.Length);
                     slenD += (double)s.Length;
                  }
               });
               slopeU = (slopeU * 100.0).Round(1);
               slenU = slenU.Round(3);
               slopeD = (slopeD * 100.0).Round(1);
               slenD = slenD.Round(3);

               var o0 = t0.Odometer;
               var e0 = t0.Battery.Energy;
               var s0 = t0.Battery.Soc;
               // var a0 = t0.Gps.Location.Altitude;

               var o1 = t1.Odometer;
               var e1 = t1.Battery.Energy;
               var s1 = t1.Battery.Soc;
               // var a1 = t1.Gps.Location.Altitude;

               var dOdo = ((double)(o1 - o0)).Round(0);
               // var dAlt = ((double)(a1 - a0) * 1000).Round(0);
               var eest = ((double)t1.OriginalDrivingSegmentEstimates.Eea).Round(1);
               var eact = ((double)e1).Round(1);

               Debug.WriteLine("Distance: {0}, SlopeU: {1}, SlenU: {2}, SlopeD: {3}, SlenD: {4}, Eea: {5} ({6}%), E.actual: {7} ({8}%), Err: {9}%, ActivityId: {10}, Device: {11}, TimeStamp: {12}".Substitute(
                  dOdo,
                  slopeU, slenU,
                  slopeD, slenD,
                  eest, ((eest * 100) / 21.0).Round(0),
                  eact, ((eact * 100) / 21.0).Round(0),
                  ((eact * 100) / 21.0).Round(0) - ((eest * 100) / 21.0).Round(0),
                  a.Activity.ActivityId,
                  a.Activity.DeviceId,
                  t1.TimeStamp
                  ));
            }
            _report("Done Reporting");

         });
      }