예제 #1
0
        /// <summary>
        /// Predict the state of the map in the next iteration
        /// given the trajectory of the vehicle.
        /// </summary>
        /// <param name="measurements">Sensor measurements in range-bearing  form.</param>
        /// <param name="pose">Vehicle pose that conditions the mapping.</param>
        /// <param name="model">Associated map model.</param>
        /// <param name="unexplored">Input/Output, unexplored candidates from previous timestep..</param>
        /// <returns>Predicted map model.</returns>
        /// <remarks>Though in theory the predict doesn't depend on the measurements,
        /// the birth region (i.e. the unexplored areas) is large to represent on gaussians.
        /// To diminish the computational time, only the areas near the new measurements are
        /// used (i.e. the same measurements). This is equivalent to artificially increasing
        /// belief on the new measurements (when in a new area).</remarks>
        public Map PredictConditional(List <MeasurementT> measurements,
                                      SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose,
                                      Map model, List <double[]> unexplored)
        {
            // gaussian are born on any unexplored areas,
            // as something is expected to be there,
            // but this is too resource-intensive so
            // here's a little cheat: only do it on areas
            // there has been a new measurement lately
            Map predicted = new Map(model);

            unexplored.Clear();

            foreach (MeasurementT measurement in measurements)
            {
                double[] candidate = pose.Measurer.MeasureToMap(pose.Pose, measurement);
                if (!Explored(model, candidate))
                {
                    unexplored.Add(candidate);
                }
            }

            // birth RFS
            foreach (double[] candidate in unexplored)
            {
                predicted.Add(new Gaussian(candidate, BirthCovariance, BirthWeight));
            }

            return(predicted);
        }
예제 #2
0
 /// <summary>
 /// Copy constructor. Perform a deep copy of another simulated vehicle.
 /// </summary>
 /// <param name="that">Copied simulated vehicle.</param>
 /// <param name="copytrajectory">If true, the vehicle historic trajectory is copied. Relatively heavy operation.</param>
 public SimulatedVehicle(SimulatedVehicle <MeasurerT, PoseT, MeasurementT> that,
                         bool copytrajectory = false)
     : this((Vehicle <MeasurerT, PoseT, MeasurementT>)that, copytrajectory)
 {
     this.detectionProbability = that.detectionProbability;
     this.ClutterDensity       = that.ClutterDensity;
     this.ClutterCount         = that.ClutterCount;
     this.clutterGen           = that.clutterGen;
 }
예제 #3
0
        /// <summary>
        /// Generate a log-likelihood matrix relating each measurement with each landmark.
        /// </summary>
        /// <param name="measurements">Sensor measurements in pixel-range form.</param>
        /// <param name="map">Map model.</param>
        /// <param name="pose">Vehicle pose.</param>
        /// <returns>Set log-likelihood matrix.</returns>
        public static SparseMatrix SetLogLikeMatrix(List <MeasurementT> measurements, IMap map,
                                                    SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose)
        {
            // exact calculation if there are few components/measurements;
            // use the most probable components approximation otherwise
            SparseMatrix logprobs = new SparseMatrix(map.Count + measurements.Count, map.Count + measurements.Count, double.NegativeInfinity);

            double logclutter = Math.Log(pose.ClutterDensity);

            Gaussian[] zprobs = new Gaussian[map.Count];

            int n = 0;

            foreach (Gaussian landmark in map)
            {
                MeasurementT m       = pose.Measurer.MeasurePerfect(pose.Pose, landmark.Mean);
                double[]     mlinear = m.ToLinear();
                zprobs[n] = new Gaussian(mlinear, pose.MeasurementCovariance, pose.DetectionProbabilityM(m));
                n++;
            }

            for (int i = 0; i < zprobs.Length; i++)
            {
                for (int k = 0; k < measurements.Count; k++)
                {
                    double d = zprobs[i].Mahalanobis(measurements[k].ToLinear());
                    if (d < 5)
                    {
                        // prob = log (pD * zprob(measurement))
                        // this way multiplying probabilities equals to adding (negative) profits
                        logprobs[i, k] = Math.Log(zprobs[i].Weight) + Math.Log(zprobs[i].Multiplier) - 0.5 * d * d;
                    }
                }
            }

            for (int i = 0; i < map.Count; i++)
            {
                logprobs[i, measurements.Count + i] = Math.Log(1 - zprobs[i].Weight);
            }

            for (int i = 0; i < measurements.Count; i++)
            {
                logprobs[map.Count + i, i] = logclutter;
            }

            return(logprobs);
        }
예제 #4
0
        /// <summary>
        /// Construct a simulation from its components.
        /// </summary>
        /// <param name="title">Window title.</param>
        /// <param name="explorer">Main vehicle in the simulation. This is the only entity the user directly controls.</param>
        /// <param name="navigator">SLAM solver.</param>
        /// <param name="commands">List of stored commands for the vehicle as odometry readings.</param>
        /// <param name="realtime">If true, the system works at the highest speed it can;
        /// otherwise, the framerate is fixed and even if processing takes longer than the timestep, the simulation works
        /// as it had taken exactly the nominal rate.</param>
        /// <param name="noterminate"> If true, the simulation will remain active after cues
        /// like command depletion or vehicle requirements ask to do so.</param>
        public Simulation(string title,
                          Vehicle <MeasurerT, PoseT, MeasurementT> explorer,
                          Navigator <MeasurerT, PoseT, MeasurementT> navigator,
                          List <double[]> commands,
                          bool realtime, bool noterminate)
            : base(title, explorer, navigator, realtime)
        {
            Commands        = commands;
            commandindex    = 0;
            commanddepleted = false;

            this.noterminate = noterminate;

            timer = new Stopwatch();
            timer.Start();

            InitVehicle     = new SimulatedVehicle <MeasurerT, PoseT, MeasurementT>(explorer);
            SidebarHistory  = new List <Color[]>();
            WayMeasurements = new TimedMeasurements();
            // note that WayMeasurements starts empty as measurements are between frames
            // so it will have a length |frames| - 1
        }
예제 #5
0
        /// <summary>
        /// Update the weights of each vehicle using the sequential importance sampling technique.
        /// It uses most-probable-components approximation to solve the problem in polynomial time.
        /// </summary>
        /// <param name="measurements">Sensor measurements in pixel-range form.</param>
        /// <param name="predicted">Predicted map model.</param>
        /// <param name="corrected">Corrected map model.</param>
        /// <param name="pose">Vehicle pose.</param>
        /// <returns>Total weight update factor.</returns>
        public double WeightAlpha(List <MeasurementT> measurements, Map predicted, Map corrected,
                                  SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose)
        {
            IMap jmap = corrected.BestMapEstimate;

            double ploglikelihood = 0;
            double cloglikelihood = 0;

            foreach (var component in jmap)
            {
                ploglikelihood += Math.Log(predicted.Evaluate(component.Mean));
                cloglikelihood += Math.Log(corrected.Evaluate(component.Mean));
            }

            double pcount = predicted.ExpectedSize;
            double ccount = corrected.ExpectedSize;

            double setloglikelihood   = SetLogLikelihood(measurements, jmap, pose);
            double loglikelihoodratio = (ploglikelihood - pcount) - (cloglikelihood - ccount);

            return(Math.Exp(setloglikelihood + loglikelihoodratio));
        }
예제 #6
0
        FromFiles(string scenefile, string commandfile = "", int particlecount = 5,
                  VehicleType input             = VehicleType.Simulation,
                  NavigationAlgorithm algorithm = NavigationAlgorithm.PHD,
                  bool onlymapping = false, bool realtime   = false,
                  bool sidebar     = true, bool noterminate = false)
        {
            Vehicle <MeasurerT, PoseT, MeasurementT>   explorer;
            Navigator <MeasurerT, PoseT, MeasurementT> navigator;
            List <double[]> commands;

            // batch methods extra information
            TimedState        estimate     = null;
            TimedArray        odometry     = null;
            TimedMeasurements measurements = null;

            try {
                switch (input)
                {
                case VehicleType.Kinect:
                    if (typeof(MeasurementT) == typeof(PixelRangeMeasurement) &&
                        typeof(PoseT) == typeof(Pose3D) &&
                        typeof(MeasurerT) == typeof(KinectMeasurer))
                    {
                        explorer = KinectVehicle.FromSensor(scenefile, sidebar) as
                                   Vehicle <MeasurerT, PoseT, MeasurementT>;
                    }
                    else
                    {
                        throw new ArgumentException("KinectVehicle can only handle 3D Pose + PixelRange");
                    }
                    break;

                case VehicleType.Record:
                    if (algorithm == NavigationAlgorithm.LoopyPHD)
                    {
                        Console.WriteLine("reading Loopy PHD initialization data from file");
                        explorer = RecordVehicle <MeasurerT, PoseT, MeasurementT> .
                                   FromFile(scenefile, true, out estimate, out odometry, out measurements);
                    }
                    else
                    {
                        explorer = RecordVehicle <MeasurerT, PoseT, MeasurementT> .
                                   FromFile(scenefile, false, out estimate, out odometry, out measurements);
                    }
                    break;

                case VehicleType.Simulation:
                default:
                    explorer = SimulatedVehicle <MeasurerT, PoseT, MeasurementT> .
                               FromFile(File.ReadAllText(scenefile));

                    break;
                }
            }
            catch (IOException) {
                Console.WriteLine("Couldn't open vehicle file/device: " + scenefile);
                explorer = new SimulatedVehicle <MeasurerT, PoseT, MeasurementT>();
            }

            try {
                if (!string.IsNullOrEmpty(commandfile))
                {
                    commands = FP.CommandsFromDescriptor(File.ReadAllLines(commandfile));
                }
                else
                {
                    commands = new List <double[]>();
                }
            }
            catch (FileNotFoundException) {
                Console.WriteLine("command file not found: " + commandfile);
                commands = new List <double[]>();
            }

            switch (algorithm)
            {
            case NavigationAlgorithm.Odometry:
                navigator = new OdometryNavigator <MeasurerT, PoseT, MeasurementT>(explorer);
                break;

            case NavigationAlgorithm.ISAM2:
                navigator = new ISAM2Navigator <MeasurerT, PoseT, MeasurementT>(explorer, onlymapping);
                break;

            case NavigationAlgorithm.LoopyPHD:
                Console.WriteLine("initializing Loopy PHD");
                if (estimate != null)
                {
                    navigator = new LoopyPHDNavigator <MeasurerT, PoseT, MeasurementT>(explorer, estimate,
                                                                                       odometry, measurements);
                }
                else
                {
                    navigator = new LoopyPHDNavigator <MeasurerT, PoseT, MeasurementT>(explorer, commands,
                                                                                       new PHDNavigator <MeasurerT, PoseT, MeasurementT>(explorer, particlecount, onlymapping));
                }

                explorer = new FakeVehicle <MeasurerT, PoseT, MeasurementT>(explorer, true);

                Console.WriteLine("Loopy PHD initialized");

                break;

            case NavigationAlgorithm.PHD:
            default:
                navigator = new PHDNavigator <MeasurerT, PoseT, MeasurementT>(explorer, particlecount, onlymapping);
                break;
            }

            string title = "monorfs - simulating " + scenefile + " [" + algorithm + "]";

            return(new Simulation <MeasurerT, PoseT, MeasurementT>(title, explorer, navigator, commands, realtime, noterminate));
        }
예제 #7
0
 /// <summary>
 /// Copy constructor. Perform a deep copy of another tracker vehicle.
 /// </summary>
 /// <param name="that">Copied simulated vehicle.</param>
 /// <param name="copytrajectory">If true, the vehicle historic trajectory is copied. Relatively heavy operation.</param>
 public TrackVehicle(SimulatedVehicle <MeasurerT, PoseT, MeasurementT> that,
                     bool copytrajectory = false)
     : base(that, copytrajectory)
 {
 }
예제 #8
0
        FromFile(string datafile, bool extrainfo, out TimedState estimate,
                 out TimedArray xodometry, out TimedMeasurements xmeasurements)
        {
            string tmpdir  = Util.TemporaryDir();
            string datadir = Path.Combine(tmpdir, "data");

            ZipFile.ExtractToDirectory(datafile, datadir);

            string scenefile      = Path.Combine(datadir, "scene.world");
            string trajectoryfile = Path.Combine(datadir, "trajectory.out");
            string estimatefile   = Path.Combine(datadir, "estimate.out");
            string odometryfile   = Path.Combine(datadir, "odometry.out");
            string measurefile    = Path.Combine(datadir, "measurements.out");
            string vismapfile     = Path.Combine(datadir, "vismaps.out");
            string tagfile        = Path.Combine(datadir, "tags.out");

            if (!File.Exists(scenefile))
            {
                throw new ArgumentException("Missing scene file");
            }

            if (extrainfo && !File.Exists(estimatefile))
            {
                throw new ArgumentException("Missing estimate file");
            }

            if (!File.Exists(trajectoryfile))
            {
                throw new ArgumentException("Missing trajectory file");
            }

            if (!File.Exists(odometryfile))
            {
                throw new ArgumentException("Missing odometry file");
            }

            if (!File.Exists(measurefile))
            {
                throw new ArgumentException("Missing measurement file");
            }

            if (!File.Exists(vismapfile))
            {
                vismapfile = "";
            }

            if (!File.Exists(tagfile))
            {
                tagfile = "";
            }

            RecordVehicle <MeasurerT, PoseT, MeasurementT> explorer;
            TimedState        trajectory;
            TimedArray        odometry;
            TimedMeasurements measurements;
            TimedMapModel     vismap;
            TimedMessage      tags;

            var template = SimulatedVehicle <MeasurerT, PoseT, MeasurementT> .
                           FromFile(File.ReadAllText(scenefile));

            trajectory   = FP.TimedArrayFromDescriptor(File.ReadAllLines(trajectoryfile), StateSize);
            odometry     = FP.TimedArrayFromDescriptor(File.ReadAllLines(odometryfile), OdoSize);
            measurements = FP.MeasurementsFromDescriptor(File.ReadAllText(measurefile), MeasureSize);

            if (!string.IsNullOrEmpty(vismapfile))
            {
                vismap = FP.MapHistoryFromDescriptor(File.ReadAllText(vismapfile), 3);

                for (int i = vismap.Count; i < trajectory.Count; i++)
                {
                    vismap.Add(Tuple.Create(trajectory[i].Item1, new Map(3)));
                }
            }
            else
            {
                vismap = new TimedMapModel();

                foreach (var entry in trajectory)
                {
                    vismap.Add(Tuple.Create(entry.Item1, new Map(3)));
                }
            }

            if (!string.IsNullOrEmpty(tagfile))
            {
                tags = FP.TimedMessageFromDescriptor(File.ReadAllLines(tagfile));
            }
            else
            {
                tags = new TimedMessage();
            }

            explorer = new RecordVehicle <MeasurerT, PoseT, MeasurementT>(trajectory, odometry, measurements, tags, template.Landmarks,
                                                                          template.Measurer);

            explorer.WayVisibleMaps = vismap;

            if (extrainfo)
            {
                TimedTrajectory fullestimate = FP.TrajectoryHistoryFromDescriptor(File.ReadAllText(estimatefile), StateSize, false);

                estimate           = fullestimate[fullestimate.Count - 1].Item2;
                explorer.WayPoints = trajectory;
                xodometry          = odometry;
                xmeasurements      = measurements;
            }
            else
            {
                estimate      = null;
                xodometry     = null;
                xmeasurements = null;
            }

            Directory.Delete(tmpdir, true);

            return(explorer);
        }
예제 #9
0
        /// <summary>
        /// Create a visualization object from a pair of formatted description files.
        /// </summary>
        /// <param name="datafile">Compressed prerecorded data file.</param>
        /// <param name="filterhistory">If true, show the filtered trajectory history, otherwise, the smooth one,
        /// i.e. the smooth history may change retroactively from future knowledge. Note however that the
        /// recorded vehicle may not support smoothing and may perform the same in both modes.
        /// Note also that this is not the algorithm mode, only the visualization; the algorithm
        /// could still take past information into account, but it won't be visualized.</param>
        /// <param name="screenshotmode">If true, skip to the screenshot tags,
        /// set the camera, take the shots and close the file.</param>
        /// <param name="tmpdir">Temporary data directory, to be removed after use.</param>
        /// <returns>Prepared visualization object.</returns>
        /// <remarks>All file must be previously sorted by time value. This property is assumed.</remarks>
        public static Viewer <MeasurerT, PoseT, MeasurementT> FromFiles(string datafile, bool filterhistory,
                                                                        double reftime, bool screenshotmode, out string tmpdir)
        {
            tmpdir = Util.TemporaryDir();
            string datadir = Path.Combine(tmpdir, "data");

            ZipFile.ExtractToDirectory(datafile, datadir);

            string scenefile    = Path.Combine(datadir, "scene.world");
            string vehiclefile  = Path.Combine(datadir, "trajectory.out");
            string estimatefile = Path.Combine(datadir, "estimate.out");
            string mapfile      = Path.Combine(datadir, "maps.out");
            string measurefile  = Path.Combine(datadir, "measurements.out");
            string tagfile      = Path.Combine(datadir, "tags.out");
            string sidebarfile  = Path.Combine(datadir, "sidebar.avi");

            if (!File.Exists(scenefile))
            {
                scenefile = "";
            }

            if (!File.Exists(measurefile))
            {
                measurefile = "";
            }

            if (!File.Exists(tagfile))
            {
                tagfile = "";
            }

            if (!File.Exists(sidebarfile))
            {
                sidebarfile = "";
            }

            SimulatedVehicle <MeasurerT, PoseT, MeasurementT> explorer;
            TimedState        trajectory;
            TimedTrajectory   estimate;
            TimedMapModel     map;
            TimedMeasurements measurements;
            TimedMessage      tags;

            PoseT        dummyP = new PoseT();
            MeasurementT dummyM = new MeasurementT();

            trajectory = FP.TimedArrayFromDescriptor(File.ReadAllLines(vehiclefile), dummyP.StateSize);
            estimate   = FP.TrajectoryHistoryFromDescriptor(File.ReadAllText(estimatefile), dummyP.StateSize, filterhistory);
            map        = FP.MapHistoryFromDescriptor(File.ReadAllText(mapfile), 3);

            if (!string.IsNullOrEmpty(measurefile))
            {
                measurements = FP.MeasurementsFromDescriptor(File.ReadAllText(measurefile), dummyM.Size);
            }
            else
            {
                measurements = new TimedMeasurements();
            }

            if (!string.IsNullOrEmpty(tagfile))
            {
                tags = FP.TimedMessageFromDescriptor(File.ReadAllLines(tagfile));
            }
            else
            {
                tags = new TimedMessage();
            }

            if (!string.IsNullOrEmpty(scenefile))
            {
                explorer = SimulatedVehicle <MeasurerT, PoseT, MeasurementT> .
                           FromFile(File.ReadAllText(scenefile));
            }
            else
            {
                explorer = new SimulatedVehicle <MeasurerT, PoseT, MeasurementT>(new PoseT().IdentityP(), new List <double[]>());
            }

            bool online = (estimate[0].Item2.Count < estimate[estimate.Count - 1].Item2.Count &&
                           estimate.Count == trajectory.Count);

            return(new Viewer <MeasurerT, PoseT, MeasurementT>("monorfs - viewing " + datafile, explorer,
                                                               trajectory, estimate, map, measurements, tags,
                                                               reftime, online, 30, sidebarfile, screenshotmode));
        }
예제 #10
0
        /// <summary>
        /// Construct a visualization from its components.
        /// </summary>
        /// <param name="title">Window title.</param>
        /// <param name="explorer">Main vehicle in the visualization.</param>
        /// <param name="trajectory">Recorded vehicle trajectory.</param>
        /// <param name="estimate">Recorded estimated vehicle trajectory.</param>
        /// <param name="map">Recorded maximum-a-posteriori estimate for the map.</param>
        /// <param name="measurements">Recorded vehicle measurements.</param>
        /// <param name="tags">Tags in the timeline.</param>
        /// <param name="reftime">Reference time.</param>
        /// <param name="online">True if the navigator works
        /// incrementally with each time step.</param>
        /// <param name="fps">Frame rate.</param>
        /// <param name="sidebarfile">Sidebar video filename.</param>
        /// <param name="screenshotmode">If true, skip to the screenshot tags,
        /// set the camera, take the shots and close the file.</param>
        public Viewer(string title,
                      SimulatedVehicle <MeasurerT, PoseT, MeasurementT> explorer,
                      TimedState trajectory, TimedTrajectory estimate,
                      TimedMapModel map, TimedMeasurements measurements, TimedMessage tags,
                      double reftime, bool online, double fps, string sidebarfile, bool screenshotmode)
            : base(title, explorer, new FakeNavigator <MeasurerT, PoseT, MeasurementT>(explorer, online), false, fps)
        {
            xnavigator   = Navigator as FakeNavigator <MeasurerT, PoseT, MeasurementT>;
            Trajectory   = trajectory;
            Estimate     = estimate;
            Map          = map;
            Measurements = measurements;
            Tags         = tags;
            FrameIndex   = 0;
            TagChanged   = false;

            VehicleWaypoints = new TimedTrajectory();

            if (xnavigator.Online)
            {
                for (int i = 0; i < Trajectory.Count; i++)
                {
                    TimedState partialtrajectory = new TimedState();

                    for (int k = 0; k <= i; k++)
                    {
                        partialtrajectory.Add(Tuple.Create(Trajectory[k].Item1, Trajectory[k].Item2));
                    }

                    VehicleWaypoints.Add(Tuple.Create(Trajectory[i].Item1, partialtrajectory));
                }

                for (int i = VehicleWaypoints.Count; i < Estimate.Count; i++)
                {
                    VehicleWaypoints.Add(Tuple.Create(Estimate[i].Item1, Trajectory));
                }
            }
            else
            {
                for (int i = 0; i < Estimate.Count; i++)
                {
                    VehicleWaypoints.Add(Tuple.Create(Estimate[i].Item1, Trajectory));
                }
            }

            Measurements.Insert(0, Tuple.Create(0.0, new List <double[]>()));

            while (Measurements.Count < map.Count)
            {
                Measurements.Add(Tuple.Create(map[Measurements.Count].Item1, new List <double[]>()));
            }

            ScreenshotMode = screenshotmode;

            if (screenshotmode)
            {
                List <int> shotindices = new List <int>();

                foreach (var entry in Tags)
                {
                    double time = entry.Item1;
                    string tag  = entry.Item2;

                    if (tag.StartsWith("screenshot"))
                    {
                        int index = map.BinarySearch(Tuple.Create(time, new Map(3)),
                                                     new ComparisonComparer <Tuple <double, Map> >(
                                                         (Tuple <double, Map> a, Tuple <double, Map> b) =>
                                                         Math.Sign(a.Item1 - b.Item1)));

                        if (index != ~Tags.Count)
                        {
                            if (index < 0)
                            {
                                index = ~index;
                            }

                            if (Math.Abs(map[index].Item1 - time) < 1e-5)
                            {
                                shotindices.Add(index);
                            }
                        }
                    }
                }

                trajectory   = new TimedState();
                estimate     = new TimedTrajectory();
                map          = new TimedMapModel();
                measurements = new TimedMeasurements();
                var waypoints = new TimedTrajectory();

                foreach (int index in shotindices)
                {
                    trajectory.Add(Trajectory      [index]);
                    estimate.Add(Estimate        [index]);
                    map.Add(Map             [index]);
                    measurements.Add(Measurements    [index]);
                    waypoints.Add(VehicleWaypoints[index]);
                }

                Trajectory       = trajectory;
                Estimate         = estimate;
                Map              = map;
                Measurements     = measurements;
                VehicleWaypoints = waypoints;
            }
            else
            {
                RefTime = Trajectory.BinarySearch(Tuple.Create(reftime, new double[0]),
                                                  new ComparisonComparer <Tuple <double, double[]> >(
                                                      (Tuple <double, double[]> a, Tuple <double, double[]> b) =>
                                                      Math.Sign(a.Item1 - b.Item1)));
                RefTime = (RefTime >= 0) ? RefTime : (RefTime != ~Trajectory.Count) ? ~RefTime : 0;

                PoseT dummy = new PoseT();

                for (int i = 0; i < Estimate.Count; i++)
                {
                    if (Estimate[i].Item2.Count > RefTime)
                    {
                        double[] delta = dummy.FromState(Trajectory[RefTime].Item2).Subtract(
                            dummy.FromState(Estimate[i].Item2[RefTime].Item2));
                        PoseT deltaP = dummy.FromLinear(delta);

                        double[]   dtranslation = deltaP.Location;
                        double[][] drotation    = deltaP.Orientation.ToMatrix();
                        double[]   rotcenter    = dummy.FromState(Estimate[i].Item2[RefTime].Item2).Location;

                        for (int k = 0; k < Estimate[i].Item2.Count; k++)
                        {
                            PoseT transformed = dummy.FromState(Estimate[i].Item2[k].Item2).Add(delta);
                            Estimate[i].Item2[k] = Tuple.Create(Estimate[i].Item2[k].Item1, transformed.State);
                        }

                        Map refmap = new Map(3);

                        foreach (var component in Map[i].Item2)
                        {
                            double[] transformed = drotation.Multiply(component.Mean.Subtract(rotcenter)).Add(rotcenter).
                                                   Add(dtranslation);

                            refmap.Add(new Gaussian(transformed,
                                                    drotation.Multiply(component.Covariance).MultiplyByTranspose(drotation),
                                                    component.Weight));
                        }

                        Map[i] = Tuple.Create(Map[i].Item1, refmap);
                    }
                }
            }

            mapindices = new int[estimate.Count];

            int h = 0;

            for (int k = 0; k < estimate.Count; k++)
            {
                while (h < map.Count - 1 && map[h].Item1 < estimate[k].Item1)
                {
                    h++;
                }

                mapindices[k] = h;
            }

            // note that the sidebar video read has to wait until LoadContent to get an appropiate Graphics context
            this.sidebarfile = sidebarfile;
            IsFixedTimeStep  = true;

            // override base class behavior (that is based on explorer HasSidebar)
            if (!string.IsNullOrEmpty(sidebarfile))
            {
                SidebarWidth  = 640;
                SidebarHeight = 2 * 480;
                ScreenCut     = 0.7;
            }
        }
예제 #11
0
        /// <summary>
        /// Correct the estimated map given the localization
        /// using a set of measurements.
        /// </summary>
        /// <param name="measurements">Sensor measurements in range-bearing  form.</param>
        /// <param name="pose">Vehicle pose that conditions the mapping.</param>
        /// <param name="model">Associated map model.</param>
        /// <returns>Corrected map model.</returns>
        public Map CorrectConditional(List <MeasurementT> measurements,
                                      SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose,
                                      Map model)
        {
            Map corrected = new Map(3);

            // reduce predicted weight to acocunt for misdetection
            // v += (1-PD) v
            foreach (Gaussian component in model)
            {
                corrected.Add(component.Reweight((1 - pose.DetectionProbability(component.Mean)) *
                                                 component.Weight));
            }

            // measurement PHD update
            double[][]   R  = pose.MeasurementCovariance;
            double[][]   I  = Accord.Math.Matrix.Identity(3).ToArray();
            double[][]   m  = new double  [model.Count][];
            double[][]   mp = new double  [model.Count][];
            double[][][] H  = new double  [model.Count][][];
            double[][][] P  = new double  [model.Count][][];
            double[][][] PH = new double  [model.Count][][];
            double[][][] S  = new double  [model.Count][][];
            double[]     PD = new double  [model.Count];
            Gaussian[]   mc = new Gaussian[model.Count];

            var          qindex = new Dictionary <Gaussian, int>();
            MeasurementT dummyM = new MeasurementT();

            int n = 0;

            foreach (Gaussian component in model)
            {
                m [n] = component.Mean;
                mp[n] = pose.Measurer.MeasurePerfect(pose.Pose, m[n]).ToLinear();
                H [n] = pose.Measurer.MeasurementJacobianL(pose.Pose, m[n]);
                P [n] = component.Covariance;
                PH[n] = P[n].MultiplyByTranspose(H[n]);
                S [n] = H[n].Multiply(PH[n]).Add(R);
                mc[n] = new Gaussian(mp[n], S[n], component.Weight);
                PD[n] = pose.DetectionProbabilityM(dummyM.FromLinear(mp[n]));

                qindex[component] = n;
                n++;
            }

            // for each measurement z and a priori map component,
            // v += w' N(x, m', P'), where
            // w'   = PD w q(z) / (k(z) + sum over components(PD w q(z)))
            // m'   = m + K (z - h(m))
            // P'   = [I - K H] P
            // K    = P H^T (H P H^T + R)^-1
            // q(z) = N(z, h(m), H P H^T + R)
            // R is the measurement covariance
            // H is the measurement linear operator (jacobian) from the model
            foreach (MeasurementT measurement in measurements)
            {
                Map      near      = model.Near(pose.Measurer.MeasureToMap(pose.Pose, measurement), DensityDistanceThreshold);
                double[] mlinear   = measurement.ToLinear();
                double   weightsum = 0;

                foreach (Gaussian landmark in near)
                {
                    int      i         = qindex[landmark];
                    Gaussian mlandmark = mc[i];
                    weightsum += PD[i] * mlandmark.Weight * mlandmark.Evaluate(mlinear);
                }

                foreach (var landmark in near)
                {
                    int i = qindex[landmark];

                    double[][] gain       = PH[i].Multiply(mc[i].CovarianceInverse);
                    double[]   mean       = m[i].Add(gain.Multiply(mlinear.Subtract(mp[i])));
                    double[][] covariance = I.Subtract(gain.Multiply(H[i])).Multiply(P[i]);

                    double weight = PD[i] * mc[i].Weight * mc[i].Evaluate(mlinear) / (pose.ClutterDensity + weightsum);

                    corrected.Add(new Gaussian(mean, covariance, weight));
                }
            }

            return(corrected);
        }
예제 #12
0
        /// <summary>
        /// Calculate the set log-likelihood log(P(Z|X, M)), but do not consider visibility
        /// (everything is fully visible). This is used to avoid uninteresting solution to the
        /// optimization problem max_X log(P(Z|X, M)). Also gives the pose gradient at the evaluated pose.
        /// </summary>
        /// <param name="measurements">Sensor measurements in pixel-range form.</param>
        /// <param name="map">Map model.</param>
        /// <param name="pose">Vehicle pose.</param>
        /// <param name="calcgradient">If true, calculate the gradient; otherwise, the gradient param will be null.</param>
        /// <param name="gradient">Log-likelihood gradient wrt. the pose.</param>
        /// <returns>Set log-likelihood.</returns>
        private static double quasiSetLogLikelihood(List <MeasurementT> measurements, IMap map,
                                                    SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose,
                                                    bool calcgradient, out double[] gradient)
        {
            // exact calculation if there are few components/measurements;
            // use the most probable components approximation otherwise
            SparseMatrix llmatrix = new SparseMatrix(map.Count + measurements.Count, map.Count + measurements.Count, double.NegativeInfinity);
            var          dlldp    = new SparseMatrix <double[]>();

            if (calcgradient)
            {
                dlldp = new SparseMatrix <double[]>(map.Count + measurements.Count, map.Count + measurements.Count, new double[OdoSize]);
            }

            double logPD      = Math.Log(pose.PD);
            double log1PD     = Math.Log(1 - pose.PD);
            double logclutter = Math.Log(pose.ClutterDensity);

            Gaussian[]   zprobs     = new Gaussian[map.Count];
            double[][][] zjacobians = (calcgradient) ? new double[map.Count][][] : null;

            int n = 0;

            foreach (Gaussian landmark in map)
            {
                MeasurementT m       = pose.Measurer.MeasurePerfect(pose.Pose, landmark.Mean);
                double[]     mlinear = m.ToLinear();
                zprobs[n] = new Gaussian(mlinear, pose.MeasurementCovariance, 1);
                n++;
            }

            if (calcgradient)
            {
                n = 0;
                foreach (Gaussian landmark in map)
                {
                    zjacobians[n] = pose.Measurer.MeasurementJacobianP(pose.Pose, landmark.Mean);
                    n++;
                }
            }

            if (calcgradient)
            {
                for (int i = 0; i < zprobs.Length; i++)
                {
                    for (int k = 0; k < measurements.Count; k++)
                    {
                        double[] m = measurements[k].ToLinear();
                        double   d = zprobs[i].Mahalanobis(m);

                        if (d < 12)
                        {
                            // prob = log (pD * zprob(measurement))
                            // this way multiplying probabilities equals to adding (negative) profits
                            llmatrix[i, k] = logPD + Math.Log(zprobs[i].Multiplier) - 0.5 * d * d;
                            dlldp   [i, k] = (m.Subtract(zprobs[i].Mean)).Transpose().
                                             Multiply(zprobs[i].CovarianceInverse).
                                             Multiply(zjacobians[i]).
                                             GetRow(0);
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < zprobs.Length; i++)
                {
                    for (int k = 0; k < measurements.Count; k++)
                    {
                        double[] m = measurements[k].ToLinear();
                        double   d = zprobs[i].Mahalanobis(m);

                        if (d < 12)
                        {
                            // prob = log (pD * zprob(measurement))
                            // this way multiplying probabilities equals to adding (negative) profits
                            llmatrix[i, k] = logPD + Math.Log(zprobs[i].Multiplier) - 0.5 * d * d;
                        }
                    }
                }
            }

            for (int i = 0; i < map.Count; i++)
            {
                llmatrix[i, measurements.Count + i] = log1PD;
            }

            for (int i = 0; i < measurements.Count; i++)
            {
                llmatrix[map.Count + i, i] = logclutter;
            }

            List <SparseMatrix> connectedfull = GraphCombinatorics.ConnectedComponents(llmatrix);

            double[]   logcomp    = new double[200];
            double[][] dlogcompdp = (calcgradient) ? new double[200][] : null;
            double     total      = 0;

            gradient = (calcgradient) ? new double[OdoSize] : null;

            for (int i = 0; i < connectedfull.Count; i++)
            {
                int[]                   rows;
                int[]                   cols;
                SparseMatrix            component = connectedfull[i].Compact(out rows, out cols);
                SparseMatrix <double[]> dcomp     = (calcgradient) ? dlldp.Submatrix(rows, cols) : null;

                // fill the (Misdetection x Clutter) quadrant of the matrix with zeros (don't contribute)
                // NOTE this is filled after the connected components partition because
                //      otherwise everything would be connected through this quadrant
                for (int k = 0; k < rows.Length; k++)
                {
                    if (rows[k] >= map.Count)
                    {
                        for (int h = 0; h < cols.Length; h++)
                        {
                            if (cols[h] >= measurements.Count)
                            {
                                component[k, h] = 0;
                            }
                        }
                    }
                }

                IEnumerable <Tuple <int[], double> > assignments;
                bool enumerateall = false;
                if (component.Rows.Count <= 5)
                {
                    assignments  = GraphCombinatorics.LexicographicalPairing(component, map.Count);
                    enumerateall = true;
                }
                else
                {
                    assignments  = GraphCombinatorics.MurtyPairing(component);
                    enumerateall = false;
                }

                int m = 0;

                if (calcgradient)
                {
                    foreach (Tuple <int[], double> assignment in assignments)
                    {
                        if (m >= logcomp.Length || (!enumerateall && logcomp[m] - logcomp[0] < -10))
                        {
                            break;
                        }

                        logcomp   [m] = assignment.Item2;
                        dlogcompdp[m] = new double[OdoSize];

                        for (int p = 0; p < assignment.Item1.Length; p++)
                        {
                            dlogcompdp[m] = dlogcompdp[m].Add(dcomp[p, assignment.Item1[p]]);
                        }

                        m++;
                    }
                }
                else
                {
                    foreach (Tuple <int[], double> assignment in assignments)
                    {
                        if (m >= logcomp.Length || (!enumerateall && logcomp[m] - logcomp[0] < -10))
                        {
                            break;
                        }

                        logcomp[m] = assignment.Item2;
                        m++;
                    }
                }

                total += logcomp.LogSumExp(0, m);

                if (calcgradient)
                {
                    gradient = gradient.Add(dlogcompdp.TemperedAverage(logcomp, 0, m));
                }
            }

            return(total);
        }
예제 #13
0
 /// <summary>
 /// Calculate the set log-likelihood log(P(Z|X, M)), but do not consider visibility
 /// (everything is fully visible). This is used to avoid uninteresting solution to the
 /// optimization problem max_X log(P(Z|X, M)). Also gives the pose gradient at the evaluated pose.
 /// </summary>
 /// <param name="measurements">Sensor measurements in pixel-range form.</param>
 /// <param name="map">Map model.</param>
 /// <param name="pose">Vehicle pose.</param>
 /// <param name="gradient">Log-likelihood gradient wrt. the pose.</param>
 /// <returns>Set log-likelihood.</returns>
 public static double QuasiSetLogLikelihood(List <MeasurementT> measurements, IMap map,
                                            SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose,
                                            out double[] gradient)
 {
     return(quasiSetLogLikelihood(measurements, map, pose, true, out gradient));
 }
예제 #14
0
 /// <summary>
 /// Calculate the set log-likelihood log(P(Z|X, M)), but do not consider visibility
 /// (everything is fully visible). This is used to avoid uninteresting solution to the
 /// optimization problem max_X log(P(Z|X, M)).
 /// </summary>
 /// <param name="measurements">Sensor measurements in pixel-range form.</param>
 /// <param name="map">Map model.</param>
 /// <param name="pose">Vehicle pose.</param>
 /// <returns>Set log-likelihood.</returns>
 public static double QuasiSetLogLikelihood(List <MeasurementT> measurements, IMap map,
                                            SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose)
 {
     double[] dummy = null;
     return(quasiSetLogLikelihood(measurements, map, pose, false, out dummy));
 }
예제 #15
0
        /// <summary>
        /// Calculate the set log-likelihood log(P(Z|X, M)).
        /// </summary>
        /// <param name="measurements">Sensor measurements in pixel-range form.</param>
        /// <param name="map">Map model.</param>
        /// <param name="pose">Vehicle pose.</param>
        /// <returns>Set log-likelihood.</returns>
        public static double SetLogLikelihood(List <MeasurementT> measurements, IMap map,
                                              SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose)
        {
            // exact calculation if there are few components/measurements;
            // use the most probable components approximation otherwise
            SparseMatrix        llmatrix      = SetLogLikeMatrix(measurements, map, pose);
            List <SparseMatrix> connectedfull = GraphCombinatorics.ConnectedComponents(llmatrix);

            double[] logcomp = new double[200];
            double   total   = 0;

            for (int i = 0; i < connectedfull.Count; i++)
            {
                int[]        rows;
                int[]        cols;
                SparseMatrix component = connectedfull[i].Compact(out rows, out cols);

                // fill the (Misdetection x Clutter) quadrant of the matrix with zeros (don't contribute)
                // NOTE this is filled after the connected components partition because
                //      otherwise everything would be connected through this quadrant
                for (int k = 0; k < rows.Length; k++)
                {
                    if (rows[k] >= map.Count)
                    {
                        for (int h = 0; h < cols.Length; h++)
                        {
                            if (cols[h] >= measurements.Count)
                            {
                                component[k, h] = 0;
                            }
                        }
                    }
                }

                IEnumerable <Tuple <int[], double> > assignments;
                bool enumerateall = false;
                if (component.Rows.Count <= 5)
                {
                    assignments  = GraphCombinatorics.LexicographicalPairing(component, map.Count);
                    enumerateall = true;
                }
                else
                {
                    assignments  = GraphCombinatorics.MurtyPairing(component);
                    enumerateall = false;
                }

                int m = 0;
                foreach (Tuple <int[], double> assignment in assignments)
                {
                    if (m >= logcomp.Length || (!enumerateall && logcomp[m] - logcomp[0] < -10))
                    {
                        break;
                    }

                    logcomp[m] = assignment.Item2;
                    m++;
                }

                total += logcomp.LogSumExp(0, m);
            }

            return(total);
        }
예제 #16
0
 /// <summary>
 /// Calculate the set likelihood P(Z|X, M).
 /// </summary>
 /// <param name="measurements">Sensor measurements in pixel-range form.</param>
 /// <param name="map">Map model.</param>
 /// <param name="pose">Vehicle pose.</param>
 /// <returns>Set likelihood.</returns>
 public static double SetLikelihood(List <MeasurementT> measurements, IMap map,
                                    SimulatedVehicle <MeasurerT, PoseT, MeasurementT> pose)
 {
     return(Math.Exp(SetLogLikelihood(measurements, map, pose)));
 }