示例#1
0
        /// <summary>
        /// Return the velocity of the wheel on the ground to do the rotation, based on the angular velocity required
        /// </summary>
        /// <param name="robot">robot parameters, notably width and length</param>
        /// <param name="rv">the angular velocity in degrees per second</param>
        /// <returns></returns>
        private double RotationalToGround(RobotParams robot, double rv)
        {
            double diameter = Math.Sqrt(robot.Width * robot.Width + robot.Length * robot.Length);
            double circum   = diameter * Math.PI;

            return(rv * circum / 360.0);
        }
示例#2
0
        private double GroundToRotational(RobotParams robot, double gr)
        {
            double diameter = Math.Sqrt(robot.Width * robot.Width + robot.Length * robot.Length);
            double circum   = diameter * Math.PI;

            return(gr * 360.0 / circum);
        }
示例#3
0
        /// <summary>
        /// Returns the rotational speed profile to rotate the robot
        /// </summary>
        /// <param name="robot"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private TrapezoidalProfile CreateRotationProfile(RobotParams robot, double start, double end, double time, double vel)
        {
            double accel  = GroundToRotational(robot, robot.MaxAcceleration);
            double maxvel = GroundToRotational(robot, vel);

            double diff = end - start;

            if (diff > 180.0)
            {
                diff -= 360.0;
            }
            else if (diff <= -180.0)
            {
                diff += 360.0;
            }

            TrapezoidalProfile tp;

            tp = new TrapezoidalProfile(accel, maxvel);
            tp.Update(diff, 0.0, 0.0);

            if (tp.TotalTime > time)
            {
                throw new SwerveDriveModifier.VelocitySplitException();
            }

            return(tp);
        }
示例#4
0
        /// <summary>
        /// Return a vector, perpendicular to the requested wheel (e.g. a rotational vector) with the
        /// magnitude given.
        /// </summary>
        /// <param name="robot">robot parameters, provides the width and length of the robot</param>
        /// <param name="w">the wheel of interest</param>
        /// <param name="magnitude">the magintude of the vector</param>
        /// <returns>vector perpendicular to the requested wheel</returns>
        private XeroVector GetWheelPerpendicularVector(RobotParams robot, Wheel w, double magnitude)
        {
            double dx = 0.0, dy = 0.0;

            switch (w)
            {
            case Wheel.FL:
                dx = robot.Length / 2.0;
                dy = robot.Width / 2.0;
                break;

            case Wheel.FR:
                dx = robot.Length / 2.0;
                dy = -robot.Width / 2.0;
                break;

            case Wheel.BL:
                dx = -robot.Length / 2.0;
                dy = robot.Width / 2.0;
                break;

            case Wheel.BR:
                dx = -robot.Length / 2.0;
                dy = -robot.Width / 2.0;
                break;
            }

            return(new XeroVector(dx, dy).Normalize().Perpendicular().Scale(magnitude));
        }
示例#5
0
        private void GenerateSegmentsForPath(RobotParams robot, RobotPath path)
        {
            PathSegment[] segs = null;
            Dictionary <string, PathSegment[]> add = null; DriveModifier mod = null;
            double rotpercent = 0.0;
            bool   running    = true;

            if (robot.DriveType == RobotParams.TankDriveType)
            {
                mod = new TankDriveModifier();
            }
            else if (robot.DriveType == RobotParams.SwerveDriveType)
            {
                mod = new SwerveDriveModifier();
            }

            while (running)
            {
                RobotParams nrobot = new RobotParams(robot);
                nrobot.MaxVelocity = (1 - rotpercent) * robot.MaxVelocity;

                segs = GenerateDetailedPath(nrobot, path);
                try
                {
                    add     = mod.ModifyPath(robot, path, segs, rotpercent * robot.MaxVelocity);
                    running = false;
                }
                catch (DriveModifier.VelocitySplitException)
                {
                    rotpercent += 0.05;
                }
            }
            path.SetSegments(segs, add);
        }
示例#6
0
 public RobotParams(RobotParams p)
 {
     Width           = p.Width;
     Length          = p.Length;
     MaxVelocity     = p.MaxVelocity;
     MaxAcceleration = p.MaxAcceleration;
     MaxJerk         = p.MaxJerk;
     DriveType       = p.DriveType;
     LengthUnits     = p.LengthUnits;
     TimeStep        = p.TimeStep;
 }
示例#7
0
        public PathFile(PathFile pf)
        {
            Robot  = new RobotParams(pf.Robot);
            Groups = new PathGroup[pf.Groups.Length];

            for (int i = 0; i < Groups.Length; i++)
            {
                Groups[i] = new PathGroup(pf.Groups[i]);
            }

            IsDirty    = true;
            m_filename = pf.m_filename;
        }
示例#8
0
        public void GenerateSegments(RobotParams robot, RobotPath path)
        {
            PathGenerationStateChangeEvent args  = null;
            Tuple <RobotParams, RobotPath> entry = new Tuple <RobotParams, RobotPath>(robot, path);

            lock (m_lock)
            {
                m_queue.Add(entry);
                int running = m_active ? 1 : 0;
                int queued  = m_queue.Count;
                args = new PathGenerationStateChangeEvent(running, queued);
            }
            OnJobStateChanged(args);
        }
示例#9
0
        public void AddPath(RobotParams robot, string name)
        {
            RobotPath path = new RobotPath(name);

            path.MaxVelocity     = robot.MaxVelocity;
            path.MaxAcceleration = robot.MaxAcceleration;
            path.MaxJerk         = robot.MaxJerk;

            Array.Resize <RobotPath>(ref Paths, Paths.Length + 1);
            Paths[Paths.Length - 1] = path;

            double length = UnitConverter.Convert(100.0, "inches", robot.LengthUnits);

            path.AddPoint(new WayPoint(0.0, 0.0, 0.0, 0.0));
            path.AddPoint(new WayPoint(length, 0.0, 0.0, 0.0));
        }
示例#10
0
        public void GenerateSegments(RobotParams robot, PathGenerator gen)
        {
            bool needgen = false;

            lock (m_lock)
            {
                if (m_segments == null || m_segments_dirty)
                {
                    needgen          = true;
                    m_segments       = null;
                    m_segments_dirty = false;
                }
            }

            if (needgen)
            {
                gen.GenerateSegments(robot, this);
            }
        }
示例#11
0
        public static void Diff(RobotParams p1, RobotParams p2, List <string> diff)
        {
            if (p1.DriveType != p2.DriveType)
            {
                diff.Add("DriveType:p1 = " + p1.DriveType + ", p2 = " + p2.DriveType);
            }

            if (p1.LengthUnits != p2.LengthUnits)
            {
                diff.Add("Units: p1 = " + p1.LengthUnits + ", p2 = " + p2.LengthUnits);
            }

            if (Math.Abs(p1.Length - p2.Length) > kEpsilon)
            {
                diff.Add("Length: p1 = " + p1.Length.ToString() + ", p2 = " + p2.Length.ToString());
            }

            if (Math.Abs(p1.Width - p2.Width) > kEpsilon)
            {
                diff.Add("Width: p1 = " + p1.Width.ToString() + ", p2 = " + p2.Width.ToString());
            }

            if (Math.Abs(p1.MaxVelocity - p2.MaxVelocity) > kEpsilon)
            {
                diff.Add("MaxVelocity: p1 = " + p1.MaxVelocity.ToString() + ", p2 = " + p2.MaxVelocity.ToString());
            }

            if (Math.Abs(p1.MaxAcceleration - p2.MaxAcceleration) > kEpsilon)
            {
                diff.Add("MaxAcceleration: p1 = " + p1.MaxAcceleration.ToString() + ", p2 = " + p2.MaxAcceleration.ToString());
            }

            if (Math.Abs(p1.MaxJerk - p2.MaxJerk) > kEpsilon)
            {
                diff.Add("MaxJerk: p1 = " + p1.MaxJerk.ToString() + ", p2 = " + p2.MaxJerk.ToString());
            }

            if (Math.Abs(p1.TimeStep - p2.TimeStep) > kEpsilon)
            {
                diff.Add("TimeStep: p1 = " + p1.TimeStep.ToString() + ", p2 = " + p2.TimeStep.ToString());
            }
        }
示例#12
0
        protected bool GeneratePathFile(RobotParams robot, RobotPath path, string filename)
        {
            bool     ret = true;
            PathFile pf  = new PathFile();

            pf.Robot = robot;
            pf.AddPathGroup("tmp");
            pf.AddPath("tmp", path);

            string json = JsonConvert.SerializeObject(pf);

            try
            {
                File.WriteAllText(filename, json);
            }
            catch (Exception)
            {
                ret = false;
            }

            return(ret);
        }
示例#13
0
 public PathFile()
 {
     Groups = new PathGroup[0];
     Robot  = new RobotParams(RobotParams.TankDriveType, "inches", "degrees", 0.02, 24.0, 32.0, 96.0, 96.0, 96.0);
 }
示例#14
0
 public abstract Dictionary <string, PathSegment[]> ModifyPath(RobotParams robot, RobotPath path, PathSegment[] segs, double rotvel);
示例#15
0
        public override Dictionary <string, PathSegment[]> ModifyPath(RobotParams robot, RobotPath path, PathSegment[] segs, double rotvel)
        {
            Dictionary <string, PathSegment[]> result = new Dictionary <string, PathSegment[]>();

            if (segs == null)
            {
                return(null);
            }

            double             total   = segs[segs.Length - 1].GetValue("time");
            double             rtime   = total - path.FacingAngleStartDelay - path.FacingAngleEndDelay;
            TrapezoidalProfile profile = CreateRotationProfile(robot, path.StartFacingAngle, path.EndFacingAngle, rtime, rotvel);

            if (profile == null)
            {
                throw new DriveModifier.VelocitySplitException();
            }

            PathSegment[] fl = new PathSegment[segs.Length];
            PathSegment[] fr = new PathSegment[segs.Length];
            PathSegment[] bl = new PathSegment[segs.Length];
            PathSegment[] br = new PathSegment[segs.Length];

            result["fl"] = fl;
            result["fr"] = fr;
            result["bl"] = bl;
            result["br"] = br;

            for (int i = 0; i < segs.Length; i++)
            {
                //
                // The time in the path
                //
                double time = segs[i].GetValue("time");

                //
                // The current facing angle based on the rotational trapezoidal profile
                //
                double current = XeroUtils.BoundDegrees(path.StartFacingAngle + profile.GetDistance(time - path.FacingAngleStartDelay));

                //
                // Get the required velocity to perform the rotation.  This is the
                // linear ground based velocity for the wheel that must be applied to
                // each wheel in direction perpendicular to the vector from the center of
                // the robot to the center of the wheel.
                //
                double rv = RotationalToGround(robot, profile.GetVelocity(time - path.FacingAngleStartDelay));
                double ra = RotationalToGround(robot, profile.GetAcceleration(time - path.FacingAngleStartDelay));

                //
                // Get the velocity vector and acceleration vector relative to each of the
                // wheels to rotate the robot based on the desired rotational velocity.
                //
                XeroVector rotflvel = GetWheelPerpendicularVector(robot, Wheel.FL, rv);
                XeroVector rotfrvel = GetWheelPerpendicularVector(robot, Wheel.FR, rv);
                XeroVector rotblvel = GetWheelPerpendicularVector(robot, Wheel.BL, rv);
                XeroVector rotbrvel = GetWheelPerpendicularVector(robot, Wheel.BR, rv);

                XeroVector rotflacc = GetWheelPerpendicularVector(robot, Wheel.FL, ra);
                XeroVector rotfracc = GetWheelPerpendicularVector(robot, Wheel.FR, ra);
                XeroVector rotblacc = GetWheelPerpendicularVector(robot, Wheel.BL, ra);
                XeroVector rotbracc = GetWheelPerpendicularVector(robot, Wheel.BR, ra);

                //
                // Get the translational velocity vector to follow the path
                //
                XeroVector pathvel = XeroVector.FromDegreesMagnitude(segs[i].GetValue("heading"), segs[i].GetValue("velocity")).RotateDegrees(-current);
                XeroVector pathacc = XeroVector.FromDegreesMagnitude(segs[i].GetValue("heading"), segs[i].GetValue("acceleration")).RotateDegrees(-current);



                //
                // For each wheel, the velocity vector is the sum of the rotational vector and the translational vector
                //
                XeroVector flv = rotflvel + pathvel;
                XeroVector frv = rotfrvel + pathvel;
                XeroVector blv = rotblvel + pathvel;
                XeroVector brv = rotbrvel + pathvel;
                XeroVector fla = rotflacc + pathvel;
                XeroVector fra = rotfracc + pathvel;
                XeroVector bla = rotblacc + pathvel;
                XeroVector bra = rotbracc + pathvel;

                //
                // Now calculate the wheel positions based on the path position and the
                // facing angle
                //
                XeroVector flpos = new XeroVector(robot.Length / 2.0, robot.Width / 2.0).RotateDegrees(current).Translate(segs[i].GetValue("x"), segs[i].GetValue("y"));
                XeroVector frpos = new XeroVector(robot.Length / 2.0, -robot.Width / 2.0).RotateDegrees(current).Translate(segs[i].GetValue("x"), segs[i].GetValue("y"));
                XeroVector blpos = new XeroVector(-robot.Length / 2.0, robot.Width / 2.0).RotateDegrees(current).Translate(segs[i].GetValue("x"), segs[i].GetValue("y"));
                XeroVector brpos = new XeroVector(-robot.Length / 2.0, -robot.Width / 2.0).RotateDegrees(current).Translate(segs[i].GetValue("x"), segs[i].GetValue("y"));

                PathSegment newseg = new PathSegment(segs[i]);
                newseg.SetValue("x", flpos.X);
                newseg.SetValue("y", flpos.Y);
                newseg.SetValue("velocity", flv.Magnitude());
                newseg.SetValue("heading", flv.AngleDegrees());
                newseg.SetValue("acceleration", fla.Magnitude());
                fl[i] = newseg;

                newseg = new PathSegment(segs[i]);
                newseg.SetValue("x", frpos.X);
                newseg.SetValue("y", frpos.Y);
                newseg.SetValue("velocity", frv.Magnitude());
                newseg.SetValue("heading", frv.AngleDegrees());
                newseg.SetValue("acceleration", fra.Magnitude());
                fr[i] = newseg;

                newseg = new PathSegment(segs[i]);
                newseg.SetValue("x", blpos.X);
                newseg.SetValue("y", blpos.Y);
                newseg.SetValue("velocity", blv.Magnitude());
                newseg.SetValue("heading", blv.AngleDegrees());
                newseg.SetValue("acceleration", bla.Magnitude());
                bl[i] = newseg;

                newseg = new PathSegment(segs[i]);
                newseg.SetValue("x", brpos.X);
                newseg.SetValue("y", brpos.Y);
                newseg.SetValue("velocity", brv.Magnitude());
                newseg.SetValue("heading", brv.AngleDegrees());
                newseg.SetValue("acceleration", bra.Magnitude());
                br[i] = newseg;
            }

            return(result);
        }
示例#16
0
        public override Dictionary <string, PathSegment[]> ModifyPath(RobotParams robot, RobotPath path, PathSegment[] segs, double rotvel)
        {
            Dictionary <string, PathSegment[]> result = new Dictionary <string, PathSegment[]>();

            if (segs == null)
            {
                return(null);
            }

            double lvel, lacc, ljerk, lpos = 0.0;
            double rvel, racc, rjerk, rpos = 0.0;
            double plx = 0.0, ply = 0.0;
            double prx = 0.0, pry = 0.0;
            double plvel = 0.0, prvel = 0.0;
            double placc = 0.0, pracc = 0.0;

            PathSegment[] lsegs = new PathSegment[segs.Length];
            PathSegment[] rsegs = new PathSegment[segs.Length];

            result["left"]  = lsegs;
            result["right"] = rsegs;

            for (int i = 0; i < segs.Length; i++)
            {
                double time    = segs[i].GetValue("time");
                double heading = XeroUtils.DegreesToRadians(segs[i].GetValue("heading"));
                double ca      = Math.Cos(heading);
                double sa      = Math.Sin(heading);

                double px = segs[i].GetValue("x");
                double py = segs[i].GetValue("y");

                double lx = px - robot.Width * sa / 2.0;
                double ly = py + robot.Width * ca / 2.0;
                double rx = px + robot.Width * sa / 2.0;
                double ry = py - robot.Width * ca / 2.0;

                if (i == 0)
                {
                    lvel  = 0.0;
                    lacc  = 0.0;
                    lpos  = 0.0;
                    ljerk = 0.0;

                    rvel  = 0.0;
                    racc  = 0.0;
                    rpos  = 0.0;
                    rjerk = 0.0;
                }
                else
                {
                    double dt    = segs[i].GetValue("time") - segs[i - 1].GetValue("time");
                    double ldist = Math.Sqrt((lx - plx) * (lx - plx) + (ly - ply) * (ly - ply));
                    double rdist = Math.Sqrt((rx - prx) * (rx - prx) + (ry - pry) * (ry - pry));

                    lvel = ldist / dt;
                    rvel = rdist / dt;

                    lacc = (lvel - plvel) / dt;
                    racc = (rvel - prvel) / dt;

                    ljerk = (lacc - placc) / dt;
                    rjerk = (racc - pracc) / dt;

                    lpos += ldist;
                    rpos += rdist;
                }

                PathSegment left = new PathSegment();
                left.SetValue("time", time);
                left.SetValue("x", lx);
                left.SetValue("y", ly);
                left.SetValue("heading", segs[i].GetValue("heading"));
                left.SetValue("position", lpos);
                left.SetValue("velocity", lvel);
                left.SetValue("acceleration", lacc);
                left.SetValue("jerk", ljerk);
                lsegs[i] = left;

                PathSegment right = new PathSegment();
                right.SetValue("time", segs[i].GetValue("time"));
                right.SetValue("x", rx);
                right.SetValue("y", ry);
                right.SetValue("heading", segs[i].GetValue("heading"));
                right.SetValue("position", rpos);
                right.SetValue("velocity", rvel);
                right.SetValue("acceleration", racc);
                right.SetValue("jerk", rjerk);
                rsegs[i] = right;

                plx   = lx;
                ply   = ly;
                prx   = rx;
                pry   = ry;
                plvel = lvel;
                prvel = rvel;
                placc = lacc;
                pracc = racc;
            }

            return(result);
        }
示例#17
0
 public abstract PathSegment[] GenerateDetailedPath(RobotParams robot, RobotPath path);