Пример #1
0
 public Controller(Manipulator manipulator, PathPlanner pathPlanner, InverseKinematicsSolver inverseKinematicsSolver, MotionController motionController)
 {
     Manipulator             = manipulator;
     InverseKinematicsSolver = inverseKinematicsSolver;
     PathPlanner             = pathPlanner;
     MotionController        = motionController;
 }
Пример #2
0
        public void Trim(Manipulator manipulator, InverseKinematicsSolver solver)
        {
            switch (Mode)
            {
            case TreeBehaviour.Cyclic:
                var source = new Queue <Node>();
                source.Enqueue(Root);
                while (source.Count != 0)
                {
                    var childs = new List <Node>(source.Dequeue().Childs);
                    foreach (var child in childs)
                    {
                        manipulator.q = child.q;
                        if (manipulator.CollisionTest().Contains(true))
                        {
                            RemoveNode(child);
                        }
                        else
                        {
                            source.Enqueue(child);
                        }
                    }
                }
                break;

            case TreeBehaviour.Recursive:
                foreach (var child in Root.Childs)
                {
                    TrimRecursive(manipulator, solver, child);
                }
                break;
            }
        }
Пример #3
0
        public void TrimRecursive(Manipulator manipulator, InverseKinematicsSolver solver, Node node)
        {
            manipulator.q = node.q;
            if (manipulator.CollisionTest().Contains(true))
            {
                RemoveNode(node);
                return;
            }

            var childs = new List <Node>(node.Childs);

            foreach (var child in childs)
            {
                TrimRecursive(manipulator, solver, child);
            }
        }
Пример #4
0
        public PathPlanningResult Run(Manipulator manipulator, Vector3 goal, InverseKinematicsSolver solver, CancellationToken cancellationToken = default)
        {
            var res = new PathPlanningResult();

            try
            {
                // restart measuring execution time
                Timer.Restart();

                // turn the controller on
                State = ControllerState.Running;

                // execute path planning
                using (var manipulatorCopy = manipulator.DeepCopy())
                {
                    res = RunAbstract(manipulatorCopy, goal, solver, cancellationToken);
                }

                // turn the controller off
                State = ControllerState.Idle;
            }
            catch (OperationCanceledException oce)
            {
                // TODO: provide some log info
                Reset();

                // indicate that the process has been aborted
                State = ControllerState.Aborted;
            }
            finally
            {
                // stop measuring execution time
                Timer.Stop();
            }

            return(res);
        }
Пример #5
0
 protected abstract PathPlanningResult RunAbstract(Manipulator manipulator, Vector3 goal, InverseKinematicsSolver solver, CancellationToken cancellationToken);
Пример #6
0
        protected override PathPlanningResult RunAbstract(Manipulator manipulator, Vector3 goal, InverseKinematicsSolver solver, CancellationToken cancellationToken)
        {
            if (manipulator.DistanceTo(goal) < _threshold)
            {
                // the goal is already reached
                return new PathPlanningResult
                       {
                           Iterations = 0,
                           Path       = null
                       }
            }
            ;

            // create new tree
            Tree = new Tree(new Tree.Node(null, manipulator.GripperPos, manipulator.q), _maxIterations + 1);

            // define local attractors as the goal attractor and copies of static attractors
            var attractors = new List <Attractor>()
            {
                new Attractor(goal)
            };

            attractors.AddRange(_attractors);

            // recalculate attractors' weights
            Attractor.RecalculateWeights(attractors, manipulator, _threshold);

            // sort attractors
            attractors = attractors.OrderBy(a => a.Weight).ToList();

            // create necessary locals
            Attractor attractorFirst = attractors.First();
            Attractor attractorLast  = attractors.Last(); // TODO: last attractor has too big radius (~5 units for 0.04 step); fix!

            float mu    = attractorFirst.Weight;
            float sigma = (attractorLast.Weight - attractorFirst.Weight) / 2.0f;

            List <float> weights = new List <float>();

            Iterations = 0;
            while (Iterations < _maxIterations)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Iterations++;

                // trim tree
                if (_enableTrimming && Iterations % _trimPeriod == 0)
                {
                    Tree.Trim(manipulator, solver);
                }

                // generate normally distributed weight
                float num = RandomThreadStatic.NextGaussian(mu, sigma);
                weights.Add(num);

                // get the index of the most relevant attractor
                int index = attractors.IndexOfNearest(num, a => a.Weight);

                // get point of the obtained attractor
                Vector3 sample = attractors[index].Center;

                // find the closest node to that attractor
                Tree.Node nodeClosest = Tree.Closest(sample);

                // get new tree node point
                Vector3 point = nodeClosest.Point + Vector3.Normalize(sample - nodeClosest.Point) * _step;

                if (!(_collisionCheck && ObstacleHandler.ContainmentTest(point, out _)))
                {
                    // solve inverse kinematics for the new node
                    manipulator.q = nodeClosest.q;
                    var ikRes = solver.Execute(manipulator, point);
                    if (ikRes.Converged && !(_collisionCheck && manipulator.CollisionTest().Contains(true)))  // TODO: is convergence check really needed?
                    {
                        manipulator.q = ikRes.Configuration;

                        // add node to the tree
                        Tree.Node node = new Tree.Node(nodeClosest, manipulator.GripperPos, manipulator.q);
                        Tree.AddNode(node);

                        // check exit condition
                        if (point.DistanceTo(attractors[index].Center) < attractors[index].Radius)
                        {
                            if (index == 0)
                            {
                                // stop in case the main attractor has been hit
                                continue;//break;
                            }
                            else
                            {
                                // remove attractor if it has been hit
                                attractors.RemoveAt(index);
                            }
                        }
                    }
                }
            }

            // retrieve resultant path along with respective configurations
            return(new PathPlanningResult
            {
                Iterations = Iterations,
                Path = Tree.GetPath(manipulator, Tree.Closest(goal))  // TODO: refactor! tree should be written to temp variable in path planner, not permanent in manipulator
            });
        }
    }
Пример #7
0
        protected override PathPlanningResult RunAbstract(Manipulator manipulator, Vector3 goal, InverseKinematicsSolver solver, CancellationToken cancellationToken)
        {
            if (manipulator.DistanceTo(goal) < _threshold)
            {
                // the goal is already reached
                return new PathPlanningResult
                       {
                           Iterations = 0,
                           Path       = null
                       }
            }
            ;

            // create new tree
            Tree = new Tree(new Tree.Node(null, manipulator.GripperPos, manipulator.q), _maxIterations + 1);

            Iterations = 0;
            while (Iterations < _maxIterations)
            {
                cancellationToken.ThrowIfCancellationRequested();

                Iterations++;

                // trim tree
                if (_enableTrimming && Iterations % _trimPeriod == 0)
                {
                    Tree.Trim(manipulator, solver);
                }

                // get sample point
                Vector3 sample;
                if (Iterations % _goalBiasPeriod == 0)
                {
                    // use goal bias
                    sample = goal;
                }
                else
                {
                    // generate sample
                    sample = RandomThreadStatic.NextPointSphere(manipulator.WorkspaceRadius) + manipulator.Base;
                }

                // find the closest node to the generated sample point
                Tree.Node nodeClosest = Tree.Closest(sample);

                // get new tree node point
                Vector3 point = nodeClosest.Point + Vector3.Normalize(sample - nodeClosest.Point) * _step;

                if (!(_collisionCheck && ObstacleHandler.ContainmentTest(point, out _)))
                {
                    // solve inverse kinematics for the new node to obtain the agent configuration
                    manipulator.q = nodeClosest.q;
                    var ikRes = solver.Execute(manipulator, point);
                    if (ikRes.Converged && !(_collisionCheck && manipulator.CollisionTest().Contains(true)))
                    {
                        manipulator.q = ikRes.Configuration;

                        // add new node to the tree
                        Tree.Node node = new Tree.Node(nodeClosest, manipulator.GripperPos, manipulator.q);
                        Tree.AddNode(node);

                        // check exit condition
                        if (manipulator.DistanceTo(goal) < _threshold)
                        {
                            break;
                        }
                    }
                }
            }

            // retrieve resultant path along with respective configurations
            return(new PathPlanningResult
            {
                Iterations = Iterations,
                Path = Tree.GetPath(manipulator, Tree.Closest(goal))  // TODO: refactor! tree should be written to temp variable in path planner, not permanent in manipulator
            });
        }
Пример #8
0
        protected override PathPlanningResult RunAbstract(Manipulator manipulator, Vector3 goal, InverseKinematicsSolver solver, CancellationToken cancellationToken)
        {
            if (manipulator.DistanceTo(goal) < _threshold)
            {
                // the goal is already reached
                return new PathPlanningResult
                       {
                           Iterations = 0,
                           Path       = null
                       }
            }
            ;

            _manipulator          = manipulator;
            _initialConfiguration = manipulator.q;
            _solver = solver;
            _goal   = goal;

            var generation = new List <Chromosome>();

            // get initial solution
            var bezierInitial     = ConstructBezier(_manipulator.GripperPos, goal, _bezierControlPointsCount);
            var pathInitial       = ConstructPath(bezierInitial, _bezierStep);
            var chromosomeInitial = new Chromosome(bezierInitial, pathInitial, Rate(pathInitial));

            generation.Add(chromosomeInitial);

            Dominant = chromosomeInitial;
            Changed  = true;

            // evolve generations
            Console.SetCursorPosition(0, 10);
            Console.WriteLine("Starting genetic algorithm...");
            Iterations = 0;
            while (generation[0].Weight > 0 && Iterations++ < _maxIterations)
            {
                cancellationToken.ThrowIfCancellationRequested();

                // get new generation
                generation = Evolve(generation, _offspringSize, _survivalSize);

                Console.SetCursorPosition(0, 11);
                Console.WriteLine($"Generations passed: {Iterations}");
                Console.WriteLine($"Best fit: {generation[0].Weight}");

                if (!Locked)
                {
                    Dominant = generation[0];  // TODO: it seems like previous dominant is not disposed properly; fix!!
                    Changed  = true;
                }
            }

            Console.SetCursorPosition(0, 15);
            Console.WriteLine("Found path's Bezier curve:");
            foreach (var point in generation[0].BezierCurve.Points)
            {
                Console.WriteLine(point);
            }

            var path = generation[0].Path;

            path.SetModel();

            return(new PathPlanningResult
            {
                Iterations = Iterations - 1,
                Path = path
            });
        }