Example #1
0
        public void TestRotateBy()
        {
            var another = new Translation2d(Length.FromMeters(3), Length.FromMeters(0));
            var rotated = another.RotateBy(new Rotation2d(Angle.FromDegrees(90)));

            AssertEqualLengths(Length.FromMeters(0.0), rotated.X);
            AssertEqualLengths(Length.FromMeters(3.0), rotated.Y);
        }
Example #2
0
        /**
         * fits a parabola to 3 points
         *
         * @return the x coordinate of the vertex of the parabola
         */
        private static double fitParabola(Translation2d p1, Translation2d p2, Translation2d p3)
        {
            double A = (p3.x() * (p2.y() - p1.y()) + p2.x() * (p1.y() - p3.y()) + p1.x() * (p3.y() - p2.y()));
            double B = (p3.x() * p3.x() * (p1.y() - p2.y()) + p2.x() * p2.x() * (p3.y() - p1.y())
                        + p1.x() * p1.x() * (p2.y() - p3.y()));

            return(-B / (2 * A));
        }
Example #3
0
        public void TestDifference()
        {
            var one = new Translation2d(Length.FromMeters(1), Length.FromMeters(3));
            var two = new Translation2d(Length.FromMeters(2), Length.FromMeters(5));

            var diff = one - two;

            AssertEqualLengths(Length.FromMeters(-1.0), diff.X);
            AssertEqualLengths(Length.FromMeters(-2.0), diff.Y);
        }
Example #4
0
        public void TestSum()
        {
            var one = new Translation2d(Length.FromMeters(1), Length.FromMeters(3));
            var two = new Translation2d(Length.FromMeters(2), Length.FromMeters(5));

            var sum = one + two;

            AssertEqualLengths(Length.FromMeters(3.0), sum.X);
            AssertEqualLengths(Length.FromMeters(8.0), sum.Y);
        }
        private static void getSegmentArc(Spline s, ref List <Pose2dWithCurvature> rv, double t0, double t1, double maxDx,
                                          double maxDy, double maxDTheta)
        {
            Translation2d p0             = s.getPoint(t0);
            Translation2d p1             = s.getPoint(t1);
            Rotation2d    r0             = s.getHeading(t0);
            Rotation2d    r1             = s.getHeading(t1);
            Pose2d        transformation = new Pose2d(new Translation2d(p0, p1).rotateBy(r0.inverse()), r1.rotateBy(r0.inverse()));
            Twist2d       twist          = Pose2d.log(transformation);

            if (twist.dy > maxDy || twist.dx > maxDx || twist.dtheta > maxDTheta)
            {
                getSegmentArc(s, ref rv, t0, (t0 + t1) / 2, maxDx, maxDy, maxDTheta);
                getSegmentArc(s, ref rv, (t0 + t1) / 2, t1, maxDx, maxDy, maxDTheta);
            }
            else
            {
                rv.Add(s.getPose2dWithCurvature(t1));
            }
        }
Example #6
0
        public static void DrawFunctionOutput(this Bitmap self, Func <double, double, double> func, Translation2d translation)
        {
            double min = double.MaxValue;
            double max = double.MinValue;

            double[,] outputs = new double[self.Width, self.Height];

            for (int py = 0; py < self.Height; py++)
            {
                for (int px = 0; px < self.Width; px++)
                {
                    translation(px, py, out double x, out double y);
                    double output = func(x, y);
                    outputs[px, py] = output;
                    if (output < min)
                    {
                        min = output;
                    }
                    if (output > max)
                    {
                        max = output;
                    }
                }
            }

            for (int py = 0; py < self.Height; py++)
            {
                for (int px = 0; px < self.Width; px++)
                {
                    //translation(px, py, out double x, out double y);
                    double output = outputs[px, py];

                    if (output < 0)
                    {
                        int c = (int)(255.0 / +min * output);
                        self.SetPixel(px, py, Color.FromArgb(c, 255, 255));
                    }
                    else
                    {
                        int c = (int)(255.0 / max * output);
                        self.SetPixel(px, py, Color.FromArgb(255, 255, c));
                    }
                }
            }
        }
Example #7
0
 public static void DrawTestData(this Bitmap self, IEnumerable <Projection> testData, Func <double[], Pen> classifier, Translation2d translation)
 {
     if (testData != null)
     {
         using (Graphics graphics = Graphics.FromImage(self))
         {
             foreach (Projection testItem in testData)
             {
                 translation(testItem.Input[0], testItem.Input[1], out double px, out double py);
                 Pen pen = classifier(testItem.Output);//[0] < 0 ? Pens.Blue : Pens.Red;
                 graphics.DrawEllipse(pen, px - 3, py - 3, 6, 6);
             }
         }
     }
 }
Example #8
0
        /**
         * Runs a single optimization iteration
         */
        private static void runOptimizationIteration(ref List <QuinticSpline> splines)
        {
            // can't optimize anything with less than 2 splines
            if (splines.Count <= 1)
            {
                return;
            }

            ControlPoint[] controlPoints = new ControlPoint[splines.Count - 1];
            double         magnitude     = 0;

            for (int i = 0; i < splines.Count - 1; ++i)
            {
                // don't try to optimize colinear points
                if (splines[i].getStartPose().isColinear(splines[i + 1].getStartPose()) ||
                    splines[i].getEndPose().isColinear(splines[i + 1].getEndPose()))
                {
                    continue;
                }
                double        original = sumDCurvature2(splines);
                QuinticSpline temp, temp1;

                temp             = splines[i];
                temp1            = splines[i + 1];
                controlPoints[i] = new ControlPoint(); // holds the gradient at a control point

                // calculate partial derivatives of sumDCurvature2
                splines[i] = new QuinticSpline(temp.x0, temp.x1, temp.dx0, temp.dx1, temp.ddx0,
                                               temp.ddx1 + kEpsilon, temp.y0, temp.y1, temp.dy0, temp.dy1, temp.ddy0, temp.ddy1);
                splines[i + 1] = new QuinticSpline(temp1.x0, temp1.x1, temp1.dx0, temp1.dx1, temp1.ddx0 + kEpsilon,
                                                   temp1.ddx1, temp1.y0, temp1.y1, temp1.dy0, temp1.dy1, temp1.ddy0, temp1.ddy1);
                controlPoints[i].ddx = (sumDCurvature2(splines) - original) / kEpsilon;
                splines[i]           = new QuinticSpline(temp.x0, temp.x1, temp.dx0, temp.dx1, temp.ddx0, temp.ddx1, temp.y0,
                                                         temp.y1, temp.dy0, temp.dy1, temp.ddy0, temp.ddy1 + kEpsilon);
                splines[i + 1] = new QuinticSpline(temp1.x0, temp1.x1, temp1.dx0, temp1.dx1, temp1.ddx0,
                                                   temp1.ddx1, temp1.y0, temp1.y1, temp1.dy0, temp1.dy1, temp1.ddy0 + kEpsilon, temp1.ddy1);
                controlPoints[i].ddy = (sumDCurvature2(splines) - original) / kEpsilon;

                splines[i]     = temp;
                splines[i + 1] = temp1;
                magnitude     += controlPoints[i].ddx * controlPoints[i].ddx + controlPoints[i].ddy * controlPoints[i].ddy;
            }

            magnitude = Math.Sqrt(magnitude);

            // minimize along the direction of the gradient
            // first calculate 3 points along the direction of the gradient
            Translation2d p1, p2, p3;

            p2 = new Translation2d(0, sumDCurvature2(splines)); // middle point is at the current location

            for (int i = 0; i < splines.Count - 1; ++i)
            { // first point is offset from the middle location by -stepSize
                if (splines[i].getStartPose().isColinear(splines[i + 1].getStartPose()) ||
                    splines[i].getEndPose().isColinear(splines[i + 1].getEndPose()))
                {
                    continue;
                }
                // normalize to step size
                controlPoints[i].ddx *= kStepSize / magnitude;
                controlPoints[i].ddy *= kStepSize / magnitude;

                // move opposite the gradient by step size amount
                splines[i].ddx1     -= controlPoints[i].ddx;
                splines[i].ddy1     -= controlPoints[i].ddy;
                splines[i + 1].ddx0 -= controlPoints[i].ddx;
                splines[i + 1].ddy0 -= controlPoints[i].ddy;

                // recompute the spline's coefficients to account for new second derivatives
                splines[i].computeCoefficients();
                splines[i + 1].computeCoefficients();
            }
            p1 = new Translation2d(-kStepSize, sumDCurvature2(splines));

            for (int i = 0; i < splines.Count - 1; ++i)
            { // last point is offset from the middle location by +stepSize
                if (splines[i].getStartPose().isColinear(splines[i + 1].getStartPose()) ||
                    splines[i].getEndPose().isColinear(splines[i + 1].getEndPose()))
                {
                    continue;
                }
                // move along the gradient by 2 times the step size amount (to return to
                // original location and move by 1
                // step)
                splines[i].ddx1     += 2 * controlPoints[i].ddx;
                splines[i].ddy1     += 2 * controlPoints[i].ddy;
                splines[i + 1].ddx0 += 2 * controlPoints[i].ddx;
                splines[i + 1].ddy0 += 2 * controlPoints[i].ddy;

                // recompute the spline's coefficients to account for new second derivatives
                splines[i].computeCoefficients();
                splines[i + 1].computeCoefficients();
            }

            p3 = new Translation2d(kStepSize, sumDCurvature2(splines));

            double stepSize = fitParabola(p1, p2, p3); // approximate step size to minimize sumDCurvature2 along the

            // gradient

            for (int i = 0; i < splines.Count - 1; ++i)
            {
                if (splines[i].getStartPose().isColinear(splines[i + 1].getStartPose()) ||
                    splines[i].getEndPose().isColinear(splines[i + 1].getEndPose()))
                {
                    continue;
                }
                // move by the step size calculated by the parabola fit (+1 to offset for the
                // final transformation to find
                // p3)
                controlPoints[i].ddx *= 1 + stepSize / kStepSize;
                controlPoints[i].ddy *= 1 + stepSize / kStepSize;

                splines[i].ddx1     += controlPoints[i].ddx;
                splines[i].ddy1     += controlPoints[i].ddy;
                splines[i + 1].ddx0 += controlPoints[i].ddx;
                splines[i + 1].ddy0 += controlPoints[i].ddy;

                // recompute the spline's coefficients to account for new second derivatives
                splines[i].computeCoefficients();
                splines[i + 1].computeCoefficients();
            }
        }