Exemplo n.º 1
0
 private void PadVelocities(TimeSeriesCollection tsc)
 {
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearSpeed], 1);
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearHorizontalVelocity], 1);
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearVerticalVelocity], 1);
     return;
 }
Exemplo n.º 2
0
 private void PadAccelerations(TimeSeriesCollection tsc)
 {
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearAcceleration], 2);
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearHorizontalAcceleration], 2);
     TimeSeriesPadder.Pad(tsc[Kinematics.LinearVerticalAcceleration], 2);
     return;
 }
Exemplo n.º 3
0
        private void ComputeAcceleration(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper)
        {
            if (tsc.Length <= 2)
            {
                PadAccelerations(tsc);
                return;
            }

            for (int i = 1; i < tsc.Length - 1; i++)
            {
                float v1    = velocities[i - 1];
                float v2    = velocities[i + 1];
                float t     = calibrationHelper.GetTime(2);
                float alpha = (v2 - v1) / t;

                tsc[Kinematics.AngularAcceleration][i] = (double)calibrationHelper.ConvertAngularAcceleration(alpha);

                float at = radii[i] * alpha;
                tsc[Kinematics.TangentialAcceleration][i] = (double)calibrationHelper.ConvertAcceleration(at);

                float ac = radii[i] * velocities[i] * velocities[i];
                tsc[Kinematics.CentripetalAcceleration][i] = (double)calibrationHelper.ConvertAcceleration(ac);

                float a = (float)Math.Sqrt(at * at + ac * ac);
                tsc[Kinematics.ResultantLinearAcceleration][i] = (double)calibrationHelper.ConvertAcceleration(a);
            }

            PadAccelerations(tsc);
        }
Exemplo n.º 4
0
        private void ImportOtherDrawingsData(Metadata metadata)
        {
            LinearKinematics linearKinematics = new LinearKinematics();

            // Trackable drawing's individual points.
            foreach (ITrackable trackable in metadata.TrackableDrawings())
            {
                Dictionary <string, TrackablePoint> trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(trackable);

                if (trackablePoints == null)
                {
                    continue;
                }

                foreach (var pair in trackablePoints)
                {
                    TrackablePoint        tp       = pair.Value;
                    Timeline <TrackFrame> timeline = pair.Value.Timeline;
                    if (timeline.Count == 0)
                    {
                        continue;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    TimeSeriesCollection tsc = linearKinematics.BuildKinematics(traj, metadata.CalibrationHelper);

                    string name  = trackable.Name;
                    Color  color = trackable.Color;

                    // Custom drawings may have dedicated names for their handles.
                    DrawingGenericPosture dgp = trackable as DrawingGenericPosture;
                    if (dgp == null)
                    {
                        name = name + " - " + pair.Key;
                    }
                    else
                    {
                        foreach (var handle in dgp.GenericPostureHandles)
                        {
                            if (handle.Reference.ToString() != pair.Key)
                            {
                                continue;
                            }

                            name  = name + " - " + (string.IsNullOrEmpty(handle.Name) ? pair.Key : handle.Name);
                            color = handle.Color == Color.Transparent ? trackable.Color : handle.Color;
                            break;
                        }
                    }

                    TimeSeriesPlotData data = new TimeSeriesPlotData(name, color, tsc);
                    timeSeriesData.Add(data);
                    filteredTrajectories.Add(data, traj);
                }
            }
        }
Exemplo n.º 5
0
 private void PadAccelerations(TimeSeriesCollection tsc)
 {
     TimeSeriesPadder.Pad(tsc[Kinematics.AngularAcceleration], 2);
     TimeSeriesPadder.Pad(tsc[Kinematics.TangentialAcceleration], 2);
     TimeSeriesPadder.Pad(tsc[Kinematics.CentripetalAcceleration], 2);
     TimeSeriesPadder.Pad(tsc[Kinematics.ResultantLinearAcceleration], 2);
     return;
 }
Exemplo n.º 6
0
        private void ComputeDistances(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Func <int, PointF> getCoord)
        {
            PointF o = getCoord(0);

            tsc[Kinematics.LinearDistance][0] = 0;
            tsc[Kinematics.LinearHorizontalDisplacement][0] = 0;
            tsc[Kinematics.LinearVerticalDisplacement][0]   = 0;

            for (int i = 1; i < tsc.Length; i++)
            {
                PointF a = getCoord(i - 1);
                PointF b = getCoord(i);
                tsc[Kinematics.LinearDistance][i] = tsc[Kinematics.LinearDistance][i - 1] + GetDistance(a, b, Component.Magnitude);
                tsc[Kinematics.LinearHorizontalDisplacement][i] = GetDistance(o, b, Component.Horizontal);
                tsc[Kinematics.LinearVerticalDisplacement][i]   = GetDistance(o, b, Component.Vertical);
            }
        }
Exemplo n.º 7
0
        public TimeSeriesCollection BuildKinematics(FilteredTrajectory traj, CalibrationHelper calibrationHelper)
        {
            TimeSeriesCollection tsc = new TimeSeriesCollection(traj.Length);

            if (traj.Length == 0)
            {
                return(tsc);
            }

            tsc.AddTimes(traj.Times);
            tsc.AddComponent(Kinematics.XRaw, traj.RawXs);
            tsc.AddComponent(Kinematics.YRaw, traj.RawYs);
            tsc.AddComponent(Kinematics.X, traj.Xs);
            tsc.AddComponent(Kinematics.Y, traj.Ys);

            Func <int, PointF> getCoord;

            if (traj.CanFilter)
            {
                getCoord = traj.Coordinates;
            }
            else
            {
                getCoord = traj.RawCoordinates;
            }

            tsc.InitializeKinematicComponents(new List <Kinematics>()
            {
                Kinematics.LinearDistance,
                Kinematics.LinearHorizontalDisplacement,
                Kinematics.LinearVerticalDisplacement,
                Kinematics.LinearSpeed,
                Kinematics.LinearHorizontalVelocity,
                Kinematics.LinearVerticalVelocity,
                Kinematics.LinearAcceleration,
                Kinematics.LinearHorizontalAcceleration,
                Kinematics.LinearVerticalAcceleration,
            });

            ComputeDistances(tsc, calibrationHelper, getCoord);
            ComputeVelocities(tsc, calibrationHelper, getCoord);
            ComputeAccelerations(tsc, calibrationHelper, getCoord);

            return(tsc);
        }
Exemplo n.º 8
0
        private void ComputeAccelerations(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Func <int, PointF> getCoord)
        {
            if (tsc.Length <= 4)
            {
                PadAccelerations(tsc);
                return;
            }

            // First pass: average speed over 2t centered on each data point.
            for (int i = 2; i < tsc.Length - 2; i++)
            {
                float t = calibrationHelper.GetTime(2);

                double acceleration = (tsc[Kinematics.LinearSpeed][i + 1] - tsc[Kinematics.LinearSpeed][i - 1]) / t;
                tsc[Kinematics.LinearAcceleration][i] = calibrationHelper.ConvertAccelerationFromVelocity((float)acceleration);

                double horizontalAcceleration = (tsc[Kinematics.LinearHorizontalVelocity][i + 1] - tsc[Kinematics.LinearHorizontalVelocity][i - 1]) / t;
                tsc[Kinematics.LinearHorizontalAcceleration][i] = calibrationHelper.ConvertAccelerationFromVelocity((float)horizontalAcceleration);

                double verticalAcceleration = (tsc[Kinematics.LinearVerticalVelocity][i + 1] - tsc[Kinematics.LinearVerticalVelocity][i - 1]) / t;
                tsc[Kinematics.LinearVerticalAcceleration][i] = calibrationHelper.ConvertAccelerationFromVelocity((float)verticalAcceleration);
            }

            PadAccelerations(tsc);

            // Second pass: extra smoothing derivatives.
            // This is only applied for high speed videos where the digitization is very noisy
            // due to the combination of increased time resolution and decreased spatial resolution.
            double        constantAccelerationSpan = 50;
            MovingAverage filter = new MovingAverage();

            double[] averagedAcceleration           = filter.FilterSamples(tsc[Kinematics.LinearAcceleration], calibrationHelper.CaptureFramesPerSecond, constantAccelerationSpan, 2);
            double[] averagedHorizontalAcceleration = filter.FilterSamples(tsc[Kinematics.LinearHorizontalAcceleration], calibrationHelper.CaptureFramesPerSecond, constantAccelerationSpan, 2);
            double[] averagedVerticalAcceleration   = filter.FilterSamples(tsc[Kinematics.LinearVerticalAcceleration], calibrationHelper.CaptureFramesPerSecond, constantAccelerationSpan, 2);

            for (int i = 0; i < tsc.Length; i++)
            {
                tsc[Kinematics.LinearAcceleration][i]           = averagedAcceleration[i];
                tsc[Kinematics.LinearHorizontalAcceleration][i] = averagedHorizontalAcceleration[i];
                tsc[Kinematics.LinearVerticalAcceleration][i]   = averagedVerticalAcceleration[i];
            }
        }
Exemplo n.º 9
0
        public TimeSeriesCollection BuildKinematics(Dictionary <string, FilteredTrajectory> trajs, AngleOptions angleOptions, CalibrationHelper calibrationHelper)
        {
            if (trajs == null || trajs.Count != 3)
            {
                throw new InvalidProgramException();
            }

            // Assume o, a, b keys for now.
            // We also use the "o" key as a reference, this implies that all three trajectories must have data at the same time points.
            // We must take care during tracking to keep the length of trajectories the same.
            TimeSeriesCollection tsc = new TimeSeriesCollection(trajs["o"].Length);

            tsc.AddTimes(trajs["o"].Times);

            tsc.InitializeKinematicComponents(new List <Kinematics>()
            {
                Kinematics.AngularPosition,
                Kinematics.AngularDisplacement,
                Kinematics.TotalAngularDisplacement,
                Kinematics.AngularVelocity,
                Kinematics.TangentialVelocity,
                Kinematics.AngularAcceleration,
                Kinematics.TangentialAcceleration,
                Kinematics.CentripetalAcceleration,
                Kinematics.ResultantLinearAcceleration
            });

            // Keep series in the reference unit.
            radii         = new float[tsc.Length];
            positions     = new float[tsc.Length];
            velocities    = new float[tsc.Length];
            accelerations = new float[tsc.Length];

            ComputeAngles(tsc, calibrationHelper, trajs, angleOptions);
            ComputeVelocity(tsc, calibrationHelper);
            ComputeAcceleration(tsc, calibrationHelper);

            return(tsc);
        }
Exemplo n.º 10
0
        private void ComputeDistances(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Func <int, PointF> getCoord)
        {
            PointF o = getCoord(0);

            tsc[Kinematics.LinearDistance][0] = 0;
            tsc[Kinematics.LinearHorizontalDisplacement][0] = 0;
            tsc[Kinematics.LinearVerticalDisplacement][0]   = 0;

            for (int i = 1; i < tsc.Length; i++)
            {
                PointF a = getCoord(i - 1);
                PointF b = getCoord(i);
                tsc[Kinematics.LinearDistance][i] = tsc[Kinematics.LinearDistance][i - 1] + GetDistance(a, b, Component.Magnitude);

                // FIXME.
                // Linear component displacement: X or Y offset but relative to the trajectory origin.
                // First we need to recompute the trajectory origin at the current time.

                tsc[Kinematics.LinearHorizontalDisplacement][i] = GetDistance(o, b, Component.Horizontal);
                tsc[Kinematics.LinearVerticalDisplacement][i]   = GetDistance(o, b, Component.Vertical);
            }
        }
Exemplo n.º 11
0
        private void ComputeVelocities(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Func <int, PointF> getCoord)
        {
            if (tsc.Length <= 2)
            {
                PadVelocities(tsc);
                return;
            }

            for (int i = 1; i < tsc.Length - 1; i++)
            {
                PointF a = getCoord(i - 1);
                PointF b = getCoord(i + 1);
                float  t = calibrationHelper.GetTime(2);

                tsc[Kinematics.LinearSpeed][i] = (double)calibrationHelper.ConvertSpeed(GetSpeed(a, b, t, Component.Magnitude));
                tsc[Kinematics.LinearHorizontalVelocity][i] = (double)calibrationHelper.ConvertSpeed(GetSpeed(a, b, t, Component.Horizontal));
                tsc[Kinematics.LinearVerticalVelocity][i]   = (double)calibrationHelper.ConvertSpeed(GetSpeed(a, b, t, Component.Vertical));
            }

            PadVelocities(tsc);

            // Second pass: apply extra smoothing to the derivatives.
            // This is only applied for high speed videos where the digitization is very noisy
            // due to the combination of increased time resolution and decreased spatial resolution.
            double        constantVelocitySpan = 40;
            MovingAverage filter = new MovingAverage();

            double[] averagedVelocity           = filter.FilterSamples(tsc[Kinematics.LinearSpeed], calibrationHelper.CaptureFramesPerSecond, constantVelocitySpan, 1);
            double[] averagedHorizontalVelocity = filter.FilterSamples(tsc[Kinematics.LinearHorizontalVelocity], calibrationHelper.CaptureFramesPerSecond, constantVelocitySpan, 1);
            double[] averagedVerticalVelocity   = filter.FilterSamples(tsc[Kinematics.LinearVerticalVelocity], calibrationHelper.CaptureFramesPerSecond, constantVelocitySpan, 1);

            for (int i = 0; i < tsc.Length; i++)
            {
                tsc[Kinematics.LinearSpeed][i] = averagedVelocity[i];
                tsc[Kinematics.LinearHorizontalVelocity][i] = averagedHorizontalVelocity[i];
                tsc[Kinematics.LinearVerticalVelocity][i]   = averagedVerticalVelocity[i];
            }
        }
Exemplo n.º 12
0
        private static void ImportAngleDrawingsData(Metadata metadata, List <TimeSeriesPlotData> timeSeriesData)
        {
            // Create three filtered trajectories named o, a, b directly based on the trackable points.
            foreach (DrawingAngle drawingAngle in metadata.Angles())
            {
                Dictionary <string, FilteredTrajectory> trajs           = new Dictionary <string, FilteredTrajectory>();
                Dictionary <string, TrackablePoint>     trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(drawingAngle);

                bool tracked = true;

                foreach (string key in trackablePoints.Keys)
                {
                    Timeline <TrackFrame> timeline = trackablePoints[key].Timeline;
                    if (timeline.Count == 0)
                    {
                        tracked = false;
                        break;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    trajs.Add(key, traj);
                }

                if (!tracked)
                {
                    continue;
                }

                TimeSeriesCollection tsc  = angularKinematics.BuildKinematics(trajs, drawingAngle.AngleOptions, metadata.CalibrationHelper);
                TimeSeriesPlotData   data = new TimeSeriesPlotData(drawingAngle.Name, drawingAngle.Color, tsc);
                timeSeriesData.Add(data);
            }
        }
Exemplo n.º 13
0
        private void ComputeVelocity(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper)
        {
            if (tsc.Length <= 2)
            {
                PadVelocities(tsc);
                return;
            }

            for (int i = 1; i < tsc.Length - 1; i++)
            {
                float a1    = positions[i - 1];
                float a2    = positions[i + 1];
                float t     = calibrationHelper.GetTime(2);
                float omega = (a2 - a1) / t;

                velocities[i] = omega;
                tsc[Kinematics.AngularVelocity][i] = (double)calibrationHelper.ConvertAngularVelocity(omega);

                float v = radii[i] * omega;
                tsc[Kinematics.TangentialVelocity][i] = (double)calibrationHelper.ConvertSpeed(v);
            }

            PadVelocities(tsc);
        }
Exemplo n.º 14
0
 private void PadVelocities(TimeSeriesCollection tsc)
 {
     TimeSeriesPadder.Pad(tsc[Kinematics.AngularVelocity], 1);
     TimeSeriesPadder.Pad(tsc[Kinematics.TangentialVelocity], 1);
     return;
 }
Exemplo n.º 15
0
        private void ComputeAngles(TimeSeriesCollection tsc, CalibrationHelper calibrationHelper, Dictionary <string, FilteredTrajectory> trajs, AngleOptions angleOptions)
        {
            for (int i = 0; i < tsc.Length; i++)
            {
                PointF o = PointF.Empty;
                PointF a = PointF.Empty;
                PointF b = PointF.Empty;

                if (trajs["o"].CanFilter)
                {
                    o = trajs["o"].Coordinates(i);
                    a = trajs["a"].Coordinates(i);
                    b = trajs["b"].Coordinates(i);
                }
                else
                {
                    o = trajs["o"].RawCoordinates(i);
                    a = trajs["a"].RawCoordinates(i);
                    b = trajs["b"].RawCoordinates(i);
                }

                // Compute the actual angle value. The logic here should match the one in AngleHelper.Update().
                // They work on different type of inputs so it's difficult to factorize the functions.
                if (angleOptions.Supplementary)
                {
                    // Create a new point by point reflection of a around o.
                    PointF c = new PointF(2 * o.X - a.X, 2 * o.Y - a.Y);
                    a = b;
                    b = c;
                }

                float angle = 0;
                if (angleOptions.CCW)
                {
                    angle = GeometryHelper.GetAngle(o, a, b);
                }
                else
                {
                    angle = GeometryHelper.GetAngle(o, b, a);
                }

                if (!angleOptions.Signed && angle < 0)
                {
                    angle = (float)(TAU + angle);
                }

                positions[i] = angle;
                radii[i]     = GeometryHelper.GetDistance(o, b);

                tsc[Kinematics.AngularPosition][i] = calibrationHelper.ConvertAngle(angle);

                if (i == 0)
                {
                    tsc[Kinematics.AngularDisplacement][i]      = 0;
                    tsc[Kinematics.TotalAngularDisplacement][i] = 0;
                }
                else
                {
                    float totalDisplacementAngle = angle - positions[0];
                    float displacementAngle      = angle - positions[i - 1];
                    tsc[Kinematics.AngularDisplacement][i]      = calibrationHelper.ConvertAngle(displacementAngle);
                    tsc[Kinematics.TotalAngularDisplacement][i] = calibrationHelper.ConvertAngle(totalDisplacementAngle);
                }
            }
        }
Exemplo n.º 16
0
        private static void ImportCustomDrawingsData(Metadata metadata, List <TimeSeriesPlotData> timeSeriesData)
        {
            // Collect angular trajectories for all the angles in all the custom tools.

            foreach (DrawingGenericPosture drawing in metadata.GenericPostures())
            {
                Dictionary <string, TrackablePoint> trackablePoints = metadata.TrackabilityManager.GetTrackablePoints(drawing);

                // First create trajectories for all the trackable points in the drawing.
                // This avoids duplicating the filtering operation for points shared by more than one angle.
                // Here the trajectories are indexed by the original alias in the custom tool, based on the index.
                Dictionary <string, FilteredTrajectory> trajs = new Dictionary <string, FilteredTrajectory>();
                bool tracked = true;

                foreach (string key in trackablePoints.Keys)
                {
                    Timeline <TrackFrame> timeline = trackablePoints[key].Timeline;

                    if (timeline.Count == 0)
                    {
                        // The point is trackable but doesn't have any timeline data.
                        // This happens if the user is not tracking that drawing, so we don't need to go further.
                        tracked = false;
                        break;
                    }

                    List <TimedPoint>  samples = timeline.Enumerate().Select(p => new TimedPoint(p.Location.X, p.Location.Y, p.Time)).ToList();
                    FilteredTrajectory traj    = new FilteredTrajectory();
                    traj.Initialize(samples, metadata.CalibrationHelper);

                    trajs.Add(key, traj);
                }

                if (!tracked)
                {
                    continue;
                }

                // Loop over all angles in this drawing and find the trackable aliases of the points making up the particular angle.
                // The final collection of trajectories for each angle should have indices named o, a, b.
                foreach (GenericPostureAngle gpa in drawing.GenericPostureAngles)
                {
                    // From integer indices to tracking aliases.
                    string keyO = gpa.Origin.ToString();
                    string keyA = gpa.Leg1.ToString();
                    string keyB = gpa.Leg2.ToString();

                    // All points in an angle must be trackable as there is currently no way to get the static point coordinate.
                    if (!trajs.ContainsKey(keyO) || !trajs.ContainsKey(keyA) || !trajs.ContainsKey(keyB))
                    {
                        continue;
                    }

                    // Remap to oab.
                    Dictionary <string, FilteredTrajectory> angleTrajs = new Dictionary <string, FilteredTrajectory>();
                    angleTrajs.Add("o", trajs[keyO]);
                    angleTrajs.Add("a", trajs[keyA]);
                    angleTrajs.Add("b", trajs[keyB]);

                    AngleOptions         options = new AngleOptions(gpa.Signed, gpa.CCW, gpa.Supplementary);
                    TimeSeriesCollection tsc     = angularKinematics.BuildKinematics(angleTrajs, options, metadata.CalibrationHelper);

                    string name = drawing.Name;
                    if (!string.IsNullOrEmpty(gpa.Name))
                    {
                        name = name + " - " + gpa.Name;
                    }

                    Color color             = gpa.Color == Color.Transparent ? drawing.Color : gpa.Color;
                    TimeSeriesPlotData data = new TimeSeriesPlotData(name, color, tsc);

                    timeSeriesData.Add(data);
                }
            }
        }
 public TimeSeriesPlotData(string label, Color color, TimeSeriesCollection timeSeriesCollection)
 {
     this.Label = label;
     this.Color = color;
     this.TimeSeriesCollection = timeSeriesCollection;
 }