コード例 #1
0
ファイル: RRT.cpp プロジェクト: jvgomez/ompl
void ompl::control::RRT::setup()
{
    base::Planner::setup();
    if (!nn_)
        nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
    nn_->setDistanceFunction([this](const Motion *a, const Motion *b)
                             {
                                 return distanceFunction(a, b);
                             });
}
コード例 #2
0
ファイル: RRTConnect.cpp プロジェクト: davetcoleman/ompl
void ompl::geometric::RRTConnect::setup()
{
    Planner::setup();
    tools::SelfConfig sc(si_, getName());
    sc.configurePlannerRange(maxDistance_);

    if (!tStart_)
        tStart_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
    if (!tGoal_)
        tGoal_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
    tStart_->setDistanceFunction([this](const Motion *a, const Motion *b)
                                 {
                                     return distanceFunction(a, b);
                                 });
    tGoal_->setDistanceFunction([this](const Motion *a, const Motion *b)
                                {
                                    return distanceFunction(a, b);
                                });
}
コード例 #3
0
ファイル: LBTRRT.cpp プロジェクト: RickOne16/ompl
double ompl::geometric::LBTRRT::lazilyUpdateApxParent(Motion *child, Motion *parent)
{
    double dist = distanceFunction(parent, child);
    removeFromParentApx(child);
    double deltaApx = parent->costApx_ + dist - child->costApx_;
    child->parentApx_ = parent;
    parent->childrenApx_.push_back(child);
    child->costApx_ = parent->costApx_ + dist;

    return deltaApx;
}
コード例 #4
0
ファイル: LazyLBTRRT.cpp プロジェクト: jvgomez/ompl
void ompl::geometric::LazyLBTRRT::setup()
{
    Planner::setup();
    tools::SelfConfig sc(si_, getName());
    sc.configurePlannerRange(maxDistance_);

    if (!nn_)
        nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
    nn_->setDistanceFunction([this](const Motion *a, const Motion *b)
                             {
                                 return distanceFunction(a, b);
                             });
}
コード例 #5
0
ファイル: SPARS.cpp プロジェクト: davetcoleman/ompl
void ompl::geometric::SPARS::setup()
{
    Planner::setup();
    if (!nn_)
        nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<DenseVertex>(this));
    nn_->setDistanceFunction([this](const DenseVertex a, const DenseVertex b)
                             {
                                 return distanceFunction(a, b);
                             });
    if (!snn_)
        snn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<SparseVertex>(this));
    snn_->setDistanceFunction([this](const SparseVertex a, const SparseVertex b)
                              {
                                  return sparseDistanceFunction(a, b);
                              });
    if (!connectionStrategy_)
        connectionStrategy_ = KStarStrategy<DenseVertex>(
            [this]
            {
                return milestoneCount();
            },
            nn_, si_->getStateDimension());
    double maxExt = si_->getMaximumExtent();
    sparseDelta_ = sparseDeltaFraction_ * maxExt;
    denseDelta_ = denseDeltaFraction_ * maxExt;

    // Setup optimization objective
    //
    // If no optimization objective was specified, then default to
    // optimizing path length as computed by the distance() function
    // in the state space.
    if (pdef_)
    {
        if (pdef_->hasOptimizationObjective())
        {
            opt_ = pdef_->getOptimizationObjective();
            if (!dynamic_cast<base::PathLengthOptimizationObjective *>(opt_.get()))
                OMPL_WARN("%s: Asymptotic optimality has only been proven with path length optimizaton; convergence "
                          "for other optimizaton objectives is not guaranteed.",
                          getName().c_str());
        }
        else
            opt_ = std::make_shared<base::PathLengthOptimizationObjective>(si_);
    }
    else
    {
        OMPL_INFORM("%s: problem definition is not set, deferring setup completion...", getName().c_str());
        setup_ = false;
    }
}
コード例 #6
0
ファイル: RRTXstatic.cpp プロジェクト: ompl/ompl
void ompl::geometric::RRTXstatic::setup()
{
    Planner::setup();
    tools::SelfConfig sc(si_, getName());
    sc.configurePlannerRange(maxDistance_);
    if (!si_->getStateSpace()->hasSymmetricDistance() || !si_->getStateSpace()->hasSymmetricInterpolate())
    {
        OMPL_WARN("%s requires a state space with symmetric distance and symmetric interpolation.", getName().c_str());
    }

    if (!nn_)
        nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
    nn_->setDistanceFunction([this](const Motion *a, const Motion *b) { return distanceFunction(a, b); });

    // Setup optimization objective
    //
    // If no optimization objective was specified, then default to
    // optimizing path length as computed by the distance() function
    // in the state space.
    if (pdef_)
    {
        if (pdef_->hasOptimizationObjective())
            opt_ = pdef_->getOptimizationObjective();
        else
        {
            OMPL_INFORM("%s: No optimization objective specified. Defaulting to optimizing path length for the allowed "
                        "planning time.",
                        getName().c_str());
            opt_ = std::make_shared<base::PathLengthOptimizationObjective>(si_);

            // Store the new objective in the problem def'n
            pdef_->setOptimizationObjective(opt_);
        }
        mc_ = MotionCompare(opt_, pdef_);
        q_ = BinaryHeap<Motion *, MotionCompare>(mc_);
    }
    else
    {
        OMPL_INFORM("%s: problem definition is not set, deferring setup completion...", getName().c_str());
        setup_ = false;
    }

    // Calculate some constants:
    calculateRewiringLowerBounds();

    // Set the bestCost_ and prunedCost_ as infinite
    bestCost_ = opt_->infiniteCost();
}
コード例 #7
0
ファイル: SyclopRRT.cpp プロジェクト: davetcoleman/ompl
void ompl::control::SyclopRRT::setup()
{
    Syclop::setup();
    sampler_ = si_->allocStateSampler();
    controlSampler_ = siC_->allocDirectedControlSampler();
    lastGoalMotion_ = nullptr;

    // Create a default GNAT nearest neighbors structure if the user doesn't want
    // the default regionalNN check from the discretization
    if (!nn_ && !regionalNN_)
    {
        nn_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));
        nn_->setDistanceFunction([this](Motion *a, const Motion *b)
                                 {
                                     return distanceFunction(a, b);
                                 });
    }
}
コード例 #8
0
ファイル: ElementGroup.cpp プロジェクト: Sgw32/AIR3-System
Vector3 AIElementGroupSwarm::rule2(AIElement* b)
{
    //LogManager::getSingleton().logMessage("Swarm step.");
    Vector3 res=Vector3::ZERO;
    int i;
    for (i=0; i!=nodes.size(); i++)
    {
        if (nodes[i]!=b)
        {
            Vector3 dist = nodes[i]->getPosition() - b->getPosition();

            float force = distanceFunction(dist.length());
            res-=(nodes[i]->getPosition() - b->getPosition())*(force);

        }
    }
    return res/mParams.RULE2_BYPASS;
}
コード例 #9
0
ファイル: TRRT.cpp プロジェクト: jvgomez/ompl
void ompl::geometric::TRRT::setup()
{
    Planner::setup();
    tools::SelfConfig selfConfig(si_, getName());

    if (!pdef_ || !pdef_->hasOptimizationObjective())
    {
        OMPL_INFORM("%s: No optimization objective specified.  Defaulting to mechanical work minimization.",
                    getName().c_str());
        opt_ = std::make_shared<base::MechanicalWorkOptimizationObjective>(si_);
    }
    else
        opt_ = pdef_->getOptimizationObjective();

    // Set maximum distance a new node can be from its nearest neighbor
    if (maxDistance_ < std::numeric_limits<double>::epsilon())
    {
        selfConfig.configurePlannerRange(maxDistance_);
        maxDistance_ *= magic::COST_MAX_MOTION_LENGTH_AS_SPACE_EXTENT_FRACTION;
    }

    // Set the threshold that decides if a new node is a frontier node or non-frontier node
    if (frontierThreshold_ < std::numeric_limits<double>::epsilon())
    {
        frontierThreshold_ = si_->getMaximumExtent() * 0.01;
        OMPL_DEBUG("%s: Frontier threshold detected to be %lf", getName().c_str(), frontierThreshold_);
    }

    // Create the nearest neighbor function the first time setup is run
    if (!nearestNeighbors_)
        nearestNeighbors_.reset(tools::SelfConfig::getDefaultNearestNeighbors<Motion *>(this));

    // Set the distance function
    nearestNeighbors_->setDistanceFunction([this](const Motion *a, const Motion *b)
                                           {
                                               return distanceFunction(a, b);
                                           });

    // Setup TRRT specific variables ---------------------------------------------------------
    temp_ = initTemperature_;
    nonfrontierCount_ = 1;
    frontierCount_ = 1;  // init to 1 to prevent division by zero error
    bestCost_ = worstCost_ = opt_->identityCost();
}
コード例 #10
0
ファイル: SST.cpp プロジェクト: HRZaheri/batch-informed-trees
ompl::control::SST::Witness* ompl::control::SST::findClosestWitness(ompl::control::SST::Motion *node)
{
    if(witnesses_->size() > 0)
    {
        Witness* closest = static_cast<Witness*>(witnesses_->nearest(node));
        if (distanceFunction(closest,node) > pruningRadius_)
        {
            closest = new Witness(siC_);
            closest->linkRep(node);
            si_->copyState(closest->state_, node->state_);
            witnesses_->add(closest);
        }
        return closest;
    }
    else
    {
        Witness* closest = new Witness(siC_);
        closest->linkRep(node);
        si_->copyState(closest->state_, node->state_);
        witnesses_->add(closest);
        return closest;
    }
}
コード例 #11
0
ファイル: LazyLBTRRT.cpp プロジェクト: jvgomez/ompl
ompl::base::PlannerStatus ompl::geometric::LazyLBTRRT::solve(const base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    // update goal and check validity
    base::Goal *goal = pdef_->getGoal().get();
    auto *goal_s = dynamic_cast<base::GoalSampleableRegion *>(goal);

    if (goal == nullptr)
    {
        OMPL_ERROR("%s: Goal undefined", getName().c_str());
        return base::PlannerStatus::INVALID_GOAL;
    }

    while (const base::State *st = pis_.nextStart())
    {
        startMotion_ = createMotion(goal_s, st);
        break;
    }

    if (nn_->size() == 0)
    {
        OMPL_ERROR("%s: There are no valid initial states!", getName().c_str());
        return base::PlannerStatus::INVALID_START;
    }

    if (!sampler_)
        sampler_ = si_->allocStateSampler();

    OMPL_INFORM("%s: Starting planning with %u states already in datastructure", getName().c_str(), nn_->size());

    bool solved = false;

    auto *rmotion = new Motion(si_);
    base::State *xstate = si_->allocState();

    goalMotion_ = createGoalMotion(goal_s);

    CostEstimatorLb costEstimatorLb(goal, idToMotionMap_);
    LPAstarLb_ = new LPAstarLb(startMotion_->id_, goalMotion_->id_, graphLb_, costEstimatorLb);  // rooted at source
    CostEstimatorApx costEstimatorApx(this);
    LPAstarApx_ = new LPAstarApx(goalMotion_->id_, startMotion_->id_, graphApx_, costEstimatorApx);  // rooted at target
    double approxdif = std::numeric_limits<double>::infinity();
    // e+e/d.  K-nearest RRT*
    double k_rrg = boost::math::constants::e<double>() +
                   boost::math::constants::e<double>() / (double)si_->getStateSpace()->getDimension();

    ////////////////////////////////////////////
    // step (1) - RRT
    ////////////////////////////////////////////
    bestCost_ = std::numeric_limits<double>::infinity();
    rrt(ptc, goal_s, xstate, rmotion, approxdif);
    if (!ptc())
    {
        solved = true;

        ////////////////////////////////////////////
        // step (2) - Lazy construction of G_lb
        ////////////////////////////////////////////
        idToMotionMap_.push_back(goalMotion_);
        int k = getK(idToMotionMap_.size(), k_rrg);
        std::vector<Motion *> nnVec;
        nnVec.reserve(k);
        BOOST_FOREACH (Motion *motion, idToMotionMap_)
        {
            nn_->nearestK(motion, k, nnVec);
            BOOST_FOREACH (Motion *neighbor, nnVec)
                if (neighbor->id_ != motion->id_ && !edgeExistsLb(motion, neighbor))
                    addEdgeLb(motion, neighbor, distanceFunction(motion, neighbor));
        }
コード例 #12
0
ファイル: BFRRT.cpp プロジェクト: bmagyar/exotica
    base::PlannerStatus BFRRT::solve(
        const base::PlannerTerminationCondition &ptc)
    {
      checkValidity();
      base::GoalSampleableRegion *goal =
          dynamic_cast<base::GoalSampleableRegion*>(pdef_->getGoal().get());

      if (!goal)
      {
        OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
        return base::PlannerStatus::UNRECOGNIZED_GOAL_TYPE;
      }
      TreeGrowingInfo tgi;
      while (const base::State *st = pis_.nextStart())
      {
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, st);
        motion->root = motion->state;
        tStart_->add(motion);
        tgi.last_s = motion;
      }

      if (tStart_->size() == 0)
      {
        OMPL_ERROR("%s: Motion planning start tree could not be initialized!",
            getName().c_str());
        return base::PlannerStatus::INVALID_START;
      }

      if (!goal->couldSample())
      {
        OMPL_ERROR("%s: Insufficient states in sampleable goal region",
            getName().c_str());
        return base::PlannerStatus::INVALID_GOAL;
      }

      if (!sampler_) sampler_ = si_->allocStateSampler();

      OMPL_INFORM(
          "%s: Starting planning with %d states already in datastructure",
          getName().c_str(), (int )(tStart_->size() + tGoal_->size()));

      Motion *rmotion = new Motion(si_);
      bool startTree = true;
      bool solved = false;

      while (ptc == false)
      {
        TreeData &tree = startTree ? tStart_ : tGoal_;
        tgi.start = startTree;
        startTree = !startTree;
        TreeData &otherTree = startTree ? tStart_ : tGoal_;

        if (tGoal_->size() == 0
            || pis_.getSampledGoalsCount() < tGoal_->size() / 2)
        {
          const base::State *st =
              tGoal_->size() == 0 ? pis_.nextGoal(ptc) : pis_.nextGoal();
          if (st)
          {
            Motion *motion = new Motion(si_);
            si_->copyState(motion->state, st);
            motion->root = motion->state;
            tGoal_->add(motion);
            tgi.last_g = motion;
          }

          if (tGoal_->size() == 0)
          {
            OMPL_ERROR("%s: Unable to sample any valid states for goal tree",
                getName().c_str());
            break;
          }
        }
        static double nearest_r = 0.05
            * distanceFunction(tgi.last_s, tgi.last_g);
        ///	Get a random state
        bool r_ok = false;
        do
        {
          sampler_->sampleUniform(rmotion->state);
          r_ok = si_->getStateValidityChecker()->isValid(rmotion->state);
        } while (!r_ok && ptc == false);
        Motion *nearest_s = tStart_->nearest(rmotion);
        Motion *nearest_g = tGoal_->nearest(rmotion);
        Motion *last_valid_motion = new Motion(si_);
        std::pair<ompl::base::State*, double> last_valid(
            last_valid_motion->state, 0);

        Motion *new_s = NULL;
        Motion *new_g = NULL;
        ///	Connect random node to start tree
        bool succ_s = si_->checkMotion(nearest_s->state, rmotion->state,
            last_valid);
        if (succ_s)
        {
          Motion *motion = new Motion(si_);
          si_->copyState(motion->state, rmotion->state);
          motion->parent = nearest_s;
          tStart_->add(motion);
          new_s = motion;
        }
        else
        {
          if (last_valid.second == 0) last_valid_motion->state = NULL;
          Eigen::VectorXd eigen_g((int) si_->getStateDimension());
          memcpy(eigen_g.data(),
              rmotion->state->as<ompl::base::RealVectorStateSpace::StateType>()->values,
              sizeof(double) * eigen_g.rows());
          local_map_->jointRef = eigen_g;
          local_solver_->getProblem()->setTau(1e-4);
          Motion *new_motion = new Motion(si_);
          if (localSolve(nearest_s, last_valid_motion->state, new_motion))
          {
            new_s = new_motion;
            tStart_->add(new_motion);
            succ_s = true;
          }
          else if (new_motion->internal_path)
          {
            si_->copyState(rmotion->state, new_motion->state);
            bool addNew = true;
//						std::vector<Motion*> n_motions;
//						tStart_->nearestR(new_motion, nearest_r, n_motions);
//						for (int i = 0; i < n_motions.size(); i++)
//							if (!n_motions[i]->global_valid_)
//							{
//								addNew = false;
//								break;
//							}
            if (addNew)
            {
              new_motion->global_valid_ = false;
              tStart_->add(new_motion);
              si_->copyState(rmotion->state, new_motion->state);
            }
          }
        }

        ///	For goal tree, do the same thing
        last_valid.second = 0;
        bool succ_g = si_->checkMotion(nearest_g->state, rmotion->state,
            last_valid);
        if (succ_g)
        {
          Motion *motion = new Motion(si_);
          si_->copyState(motion->state, rmotion->state);
          motion->parent = nearest_g;
          tGoal_->add(motion);
          new_g = motion;
        }
        else
        {
          if (last_valid.second == 0) last_valid_motion->state = NULL;
          Eigen::VectorXd eigen_g((int) si_->getStateDimension());
          memcpy(eigen_g.data(),
              rmotion->state->as<ompl::base::RealVectorStateSpace::StateType>()->values,
              sizeof(double) * eigen_g.rows());
          local_map_->jointRef = eigen_g;
          local_solver_->getProblem()->setTau(1e-4);
          Motion *new_motion = new Motion(si_);
          if (localSolve(nearest_g, last_valid_motion->state, new_motion))
          {
            new_g = new_motion;
            succ_g = true;
          }
          else if (new_motion->internal_path)
          {
            si_->copyState(rmotion->state, new_motion->state);
            bool addNew = true;
//						std::vector<Motion*> n_motions;
//						tGoal_->nearestR(new_motion, nearest_r, n_motions);
//						for (int i = 0; i < n_motions.size(); i++)
//							if (!n_motions[i]->global_valid_)
//							{
//								addNew = false;
//								break;
//							}
            if (addNew)
            {
              new_motion->global_valid_ = false;
              tGoal_->add(new_motion);
            }
          }
        }

        ///	If succeeded both ways, the a solution is found
        if (succ_s && succ_g)
        {
          connectionPoint_ = std::make_pair(new_s->state, new_g->state);
          Motion *solution = new_s;
          std::vector<Motion*> mpath1;
          while (solution != NULL)
          {
            if (solution->internal_path != nullptr)
            {
              for (int i = solution->internal_path->rows() - 1; i > 0; i--)
              {
                Motion *local_motion = new Motion(si_);
                Eigen::VectorXd tmp = solution->internal_path->row(i);
                memcpy(
                    local_motion->state->as<
                        ompl::base::RealVectorStateSpace::StateType>()->values,
                    tmp.data(),
                    sizeof(double) * (int) si_->getStateDimension());
                mpath1.push_back(local_motion);
              }
              if (solution->inter_state != NULL)
              {
                Motion *local_motion = new Motion(si_);
                si_->copyState(local_motion->state, solution->inter_state);
                mpath1.push_back(local_motion);
              }
            }
            else
              mpath1.push_back(solution);
            solution = solution->parent;
          }

          solution = new_g;
          std::vector<Motion*> mpath2;
          while (solution != NULL)
          {
            if (solution->internal_path != nullptr)
            {
              for (int i = solution->internal_path->rows() - 1; i > 0; i--)
              {
                Motion *local_motion = new Motion(si_);
                Eigen::VectorXd tmp = solution->internal_path->row(i);
                memcpy(
                    local_motion->state->as<
                        ompl::base::RealVectorStateSpace::StateType>()->values,
                    tmp.data(),
                    sizeof(double) * (int) si_->getStateDimension());
                mpath2.push_back(local_motion);
              }
              if (solution->inter_state != NULL)
              {
                Motion *local_motion = new Motion(si_);
                si_->copyState(local_motion->state, solution->inter_state);
                mpath2.push_back(local_motion);
              }
            }
            else
              mpath2.push_back(solution);
            solution = solution->parent;
          }

          PathGeometric *path = new PathGeometric(si_);
          path->getStates().reserve(mpath1.size() + mpath2.size());
          for (int i = mpath1.size() - 1; i >= 0; --i)
            path->append(mpath1[i]->state);
          for (unsigned int i = 0; i < mpath2.size(); ++i)
            path->append(mpath2[i]->state);

          pdef_->addSolutionPath(base::PathPtr(path), false, 0.0, getName());
          solved = true;
          break;
        }
      }

      si_->freeState(rmotion->state);
      delete rmotion;

      OMPL_INFORM("%s: Created %u states (%u start + %u goal)",
          getName().c_str(), tStart_->size() + tGoal_->size(), tStart_->size(),
          tGoal_->size());

      return
          solved ?
              base::PlannerStatus::EXACT_SOLUTION : base::PlannerStatus::TIMEOUT;
    }
コード例 #13
0
ファイル: SyclopRRT.cpp プロジェクト: davetcoleman/ompl
void ompl::control::SyclopRRT::selectAndExtend(Region &region, std::vector<Motion *> &newMotions)
{
    auto *rmotion = new Motion(siC_);
    base::StateSamplerPtr sampler(si_->allocStateSampler());
    std::vector<double> coord(decomp_->getDimension());
    decomp_->sampleFromRegion(region.index, rng_, coord);
    decomp_->sampleFullState(sampler, coord, rmotion->state);

    Motion *nmotion;
    if (regionalNN_)
    {
        /* Instead of querying the nearest neighbors datastructure over the entire tree of motions,
         * here we perform a linear search over all motions in the selected region and its neighbors. */
        std::vector<int> searchRegions;
        decomp_->getNeighbors(region.index, searchRegions);
        searchRegions.push_back(region.index);

        std::vector<Motion *> motions;
        for (const auto &i : searchRegions)
        {
            const std::vector<Motion *> &regionMotions = getRegionFromIndex(i).motions;
            motions.insert(motions.end(), regionMotions.begin(), regionMotions.end());
        }

        std::vector<Motion *>::const_iterator i = motions.begin();
        nmotion = *i;
        double minDistance = distanceFunction(rmotion, nmotion);
        ++i;
        while (i != motions.end())
        {
            Motion *m = *i;
            const double dist = distanceFunction(rmotion, m);
            if (dist < minDistance)
            {
                nmotion = m;
                minDistance = dist;
            }
            ++i;
        }
    }
    else
    {
        assert(nn_);
        nmotion = nn_->nearest(rmotion);
    }

    unsigned int duration =
        controlSampler_->sampleTo(rmotion->control, nmotion->control, nmotion->state, rmotion->state);
    if (duration >= siC_->getMinControlDuration())
    {
        rmotion->steps = duration;
        rmotion->parent = nmotion;
        newMotions.push_back(rmotion);
        if (nn_)
            nn_->add(rmotion);
        lastGoalMotion_ = rmotion;
    }
    else
    {
        si_->freeState(rmotion->state);
        siC_->freeControl(rmotion->control);
        delete rmotion;
    }
}
コード例 #14
0
ファイル: LBTRRT.cpp プロジェクト: RickOne16/ompl
ompl::base::PlannerStatus ompl::geometric::LBTRRT::solve(const base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    // update goal and check validity
    base::Goal                 *goal   = pdef_->getGoal().get();
    base::GoalSampleableRegion *goal_s = dynamic_cast<base::GoalSampleableRegion*>(goal);

    if (!goal)
    {
        OMPL_ERROR("%s: Goal undefined", getName().c_str());
        return base::PlannerStatus::INVALID_GOAL;
    }

    // update start and check validity
    while (const base::State *st = pis_.nextStart())
    {
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state_, st);
        motion->id_ = nn_->size();
        idToMotionMap_.push_back(motion);
        nn_->add(motion);
        lowerBoundGraph_.addVertex(motion->id_);
    }

    if (nn_->size() == 0)
    {
        OMPL_ERROR("%s: There are no valid initial states!", getName().c_str());
        return base::PlannerStatus::INVALID_START;
    }

    if (nn_->size() > 1)
    {
        OMPL_ERROR("%s: There are multiple start states - currently not supported!", getName().c_str());
        return base::PlannerStatus::INVALID_START;
    }

    if (!sampler_)
        sampler_ = si_->allocStateSampler();

    OMPL_INFORM("%s: Starting planning with %u states already in datastructure", getName().c_str(), nn_->size());

    Motion *solution  = lastGoalMotion_;
    Motion *approxSol = nullptr;
    double  approxdif = std::numeric_limits<double>::infinity();
    // e*(1+1/d)  K-nearest constant, as used in RRT*
    double k_rrg      = boost::math::constants::e<double>() +
                        boost::math::constants::e<double>() / (double)si_->getStateDimension();

    Motion *rmotion   = new Motion(si_);
    base::State *rstate = rmotion->state_;
    base::State *xstate = si_->allocState();
    unsigned int statesGenerated = 0;

    bestCost_ = lastGoalMotion_ ? lastGoalMotion_->costApx_ : std::numeric_limits<double>::infinity();
    while (ptc() == false)
    {
        iterations_++;
        /* sample random state (with goal biasing) */
        if (goal_s && rng_.uniform01() < goalBias_ && goal_s->canSample())
            goal_s->sampleGoal(rstate);
        else
            sampler_->sampleUniform(rstate);

        /* find closest state in the tree */
        Motion *nmotion = nn_->nearest(rmotion);
        base::State *dstate = rstate;

        /* find state to add */
        double d = si_->distance(nmotion->state_, rstate);
        if (d == 0) // this takes care of the case that the goal is a single point and we re-sample it multiple times
            continue;
        if (d > maxDistance_)
        {
            si_->getStateSpace()->interpolate(nmotion->state_, rstate, maxDistance_ / d, xstate);
            dstate = xstate;
        }

        if (checkMotion(nmotion->state_, dstate))
        {
            statesGenerated++;
            /* create a motion */
            Motion *motion = new Motion(si_);
            si_->copyState(motion->state_, dstate);

            /* update fields */
            double distN = distanceFunction(nmotion, motion);

            motion->id_ = nn_->size();
            idToMotionMap_.push_back(motion);
            lowerBoundGraph_.addVertex(motion->id_);
            motion->parentApx_ = nmotion;

            std::list<std::size_t> dummy;
            lowerBoundGraph_.addEdge(nmotion->id_, motion->id_, distN, false, dummy);

            motion->costLb_ = nmotion->costLb_ + distN;
            motion->costApx_ = nmotion->costApx_ + distN;
            nmotion->childrenApx_.push_back(motion);

            std::vector<Motion*> nnVec;
            unsigned int k = std::ceil(k_rrg * log((double)(nn_->size() + 1)));
            nn_->nearestK(motion, k, nnVec);
            nn_->add(motion); // if we add the motion before the nearestK call, we will get ourselves...

            IsLessThan isLessThan(this, motion);
            std::sort(nnVec.begin(), nnVec.end(), isLessThan);

            //-------------------------------------------------//
            //  Rewiring Part (i) - find best parent of motion //
            //-------------------------------------------------//
            if (motion->parentApx_ != nnVec.front())
            {
                for (std::size_t i(0); i < nnVec.size(); ++i)
                {
                    Motion *potentialParent = nnVec[i];
                    double dist = distanceFunction(potentialParent, motion);
                    considerEdge(potentialParent, motion, dist);
                }
            }

            //------------------------------------------------------------------//
            //  Rewiring Part (ii)                                              //
            //  check if motion may be a better parent to one of its neighbors  //
            //------------------------------------------------------------------//
            for (std::size_t i(0); i < nnVec.size(); ++i)
            {
                Motion *child = nnVec[i];
                double dist = distanceFunction(motion, child);
                considerEdge(motion, child, dist);
            }

            double dist = 0.0;
            bool sat = goal->isSatisfied(motion->state_, &dist);

            if (sat)
            {
                approxdif = dist;
                solution = motion;
            }
            if (dist < approxdif)
            {
                approxdif = dist;
                approxSol = motion;
            }

            if (solution != nullptr && bestCost_ != solution->costApx_)
            {
                OMPL_INFORM("%s: approximation cost = %g", getName().c_str(),
                    solution->costApx_);
                bestCost_ = solution->costApx_;
            }
        }
    }

    bool solved = false;
    bool approximate = false;

    if (solution == nullptr)
    {
        solution = approxSol;
        approximate = true;
    }

    if (solution != nullptr)
    {
        lastGoalMotion_ = solution;

        /* construct the solution path */
        std::vector<Motion*> mpath;
        while (solution != nullptr)
        {
            mpath.push_back(solution);
            solution = solution->parentApx_;
        }

        /* set the solution path */
        PathGeometric *path = new PathGeometric(si_);
        for (int i = mpath.size() - 1 ; i >= 0 ; --i)
            path->append(mpath[i]->state_);
        // Add the solution path.
        base::PathPtr bpath(path);
        base::PlannerSolution psol(bpath);
        psol.setPlannerName(getName());
        if (approximate)
            psol.setApproximate(approxdif);
        pdef_->addSolutionPath(psol);
        solved = true;
    }

    si_->freeState(xstate);
    if (rmotion->state_)
        si_->freeState(rmotion->state_);
    delete rmotion;

    OMPL_INFORM("%s: Created %u states", getName().c_str(), statesGenerated);

    return base::PlannerStatus(solved, approximate);
}
コード例 #15
0
ファイル: RRTXstatic.cpp プロジェクト: ompl/ompl
ompl::base::PlannerStatus ompl::geometric::RRTXstatic::solve(const base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    base::Goal *goal = pdef_->getGoal().get();
    auto *goal_s = dynamic_cast<base::GoalSampleableRegion *>(goal);

    // Check if there are more starts
    if (pis_.haveMoreStartStates() == true)
    {
        // There are, add them
        while (const base::State *st = pis_.nextStart())
        {
            auto *motion = new Motion(si_);
            si_->copyState(motion->state, st);
            motion->cost = opt_->identityCost();
            nn_->add(motion);
        }

        // And assure that, if we're using an informed sampler, it's reset
        infSampler_.reset();
    }
    // No else

    if (nn_->size() == 0)
    {
        OMPL_ERROR("%s: There are no valid initial states!", getName().c_str());
        return base::PlannerStatus::INVALID_START;
    }

    // Allocate a sampler if necessary
    if (!sampler_ && !infSampler_)
    {
        allocSampler();
    }

    OMPL_INFORM("%s: Starting planning with %u states already in datastructure", getName().c_str(), nn_->size());

    if (!si_->getStateSpace()->isMetricSpace())
        OMPL_WARN("%s: The state space (%s) is not metric and as a result the optimization objective may not satisfy "
                  "the triangle inequality. "
                  "You may need to disable rejection.",
                  getName().c_str(), si_->getStateSpace()->getName().c_str());

    const base::ReportIntermediateSolutionFn intermediateSolutionCallback = pdef_->getIntermediateSolutionCallback();

    Motion *solution = lastGoalMotion_;

    Motion *approximation = nullptr;
    double approximatedist = std::numeric_limits<double>::infinity();
    bool sufficientlyShort = false;

    auto *rmotion = new Motion(si_);
    base::State *rstate = rmotion->state;
    base::State *xstate = si_->allocState();
    base::State *dstate;

    Motion *motion;
    Motion *nmotion;
    Motion *nb;
    Motion *min;
    Motion *c;
    bool feas;

    unsigned int rewireTest = 0;
    unsigned int statesGenerated = 0;

    base::Cost incCost, cost;

    if (solution)
        OMPL_INFORM("%s: Starting planning with existing solution of cost %.5f", getName().c_str(),
                    solution->cost.value());

    if (useKNearest_)
        OMPL_INFORM("%s: Initial k-nearest value of %u", getName().c_str(),
                    (unsigned int)std::ceil(k_rrt_ * log((double)(nn_->size() + 1u))));
    else
        OMPL_INFORM(
            "%s: Initial rewiring radius of %.2f", getName().c_str(),
            std::min(maxDistance_, r_rrt_ * std::pow(log((double)(nn_->size() + 1u)) / ((double)(nn_->size() + 1u)),
                                                     1 / (double)(si_->getStateDimension()))));

    while (ptc == false)
    {
        iterations_++;

        // Computes the RRG values for this iteration (number or radius of neighbors)
        calculateRRG();

        // sample random state (with goal biasing)
        // Goal samples are only sampled until maxSampleCount() goals are in the tree, to prohibit duplicate goal
        // states.
        if (goal_s && goalMotions_.size() < goal_s->maxSampleCount() && rng_.uniform01() < goalBias_ &&
            goal_s->canSample())
            goal_s->sampleGoal(rstate);
        else
        {
            // Attempt to generate a sample, if we fail (e.g., too many rejection attempts), skip the remainder of this
            // loop and return to try again
            if (!sampleUniform(rstate))
                continue;
        }

        // find closest state in the tree
        nmotion = nn_->nearest(rmotion);

        if (intermediateSolutionCallback && si_->equalStates(nmotion->state, rstate))
            continue;

        dstate = rstate;

        // find state to add to the tree
        double d = si_->distance(nmotion->state, rstate);
        if (d > maxDistance_)
        {
            si_->getStateSpace()->interpolate(nmotion->state, rstate, maxDistance_ / d, xstate);
            dstate = xstate;
        }

        // Check if the motion between the nearest state and the state to add is valid
        if (si_->checkMotion(nmotion->state, dstate))
        {
            // create a motion
            motion = new Motion(si_);
            si_->copyState(motion->state, dstate);
            motion->parent = nmotion;
            incCost = opt_->motionCost(nmotion->state, motion->state);
            motion->cost = opt_->combineCosts(nmotion->cost, incCost);

            // Find nearby neighbors of the new motion
            getNeighbors(motion);

            // find which one we connect the new state to
            for (auto it = motion->nbh.begin(); it != motion->nbh.end();)
            {
                nb = it->first;
                feas = it->second;

                // Compute cost using nb as a parent
                incCost = opt_->motionCost(nb->state, motion->state);
                cost = opt_->combineCosts(nb->cost, incCost);
                if (opt_->isCostBetterThan(cost, motion->cost))
                {
                    // Check range and feasibility
                    if ((!useKNearest_ || distanceFunction(motion, nb) < maxDistance_) &&
                        si_->checkMotion(nb->state, motion->state))
                    {
                        // mark than the motino has been checked as valid
                        it->second = true;

                        motion->cost = cost;
                        motion->parent = nb;
                        ++it;
                    }
                    else
                    {
                        // Remove unfeasible neighbor from the list of neighbors
                        it = motion->nbh.erase(it);
                    }
                }
                else
                {
                    ++it;
                }
            }

            // Check if the vertex should included
            if (!includeVertex(motion))
            {
                si_->freeState(motion->state);
                delete motion;
                continue;
            }

            // Update neighbor motions neighbor datastructure
            for (auto it = motion->nbh.begin(); it != motion->nbh.end(); ++it)
            {
                it->first->nbh.emplace_back(motion, it->second);
            }

            // add motion to the tree
            ++statesGenerated;
            nn_->add(motion);
            if (updateChildren_)
                motion->parent->children.push_back(motion);

            // add the new motion to the queue to propagate the changes
            updateQueue(motion);

            bool checkForSolution = false;

            // Add the new motion to the goalMotion_ list, if it satisfies the goal
            double distanceFromGoal;
            if (goal->isSatisfied(motion->state, &distanceFromGoal))
            {
                goalMotions_.push_back(motion);
                checkForSolution = true;
            }

            // Process the elements in the queue and rewire the tree until epsilon-optimality
            while (!q_.empty())
            {
                // Get element to update
                min = q_.top()->data;
                // Remove element from the queue and NULL the handle so that we know it's not in the queue anymore
                q_.pop();
                min->handle = nullptr;

                // Stop cost propagation if it is not in the relevant region
                if (opt_->isCostBetterThan(bestCost_, mc_.costPlusHeuristic(min)))
                    break;

                // Try min as a parent to optimize each neighbor
                for (auto it = min->nbh.begin(); it != min->nbh.end();)
                {
                    nb = it->first;
                    feas = it->second;

                    // Neighbor culling: removes neighbors farther than the neighbor radius
                    if ((!useKNearest_ || min->nbh.size() > rrg_k_) && distanceFunction(min, nb) > rrg_r_)
                    {
                        it = min->nbh.erase(it);
                        continue;
                    }

                    // Calculate cost of nb using min as a parent
                    incCost = opt_->motionCost(min->state, nb->state);
                    cost = opt_->combineCosts(min->cost, incCost);

                    // If cost improvement is better than epsilon
                    if (opt_->isCostBetterThan(opt_->combineCosts(cost, epsilonCost_), nb->cost))
                    {
                        if (nb->parent != min)
                        {
                            // changing parent, check feasibility
                            if (!feas)
                            {
                                feas = si_->checkMotion(nb->state, min->state);
                                if (!feas)
                                {
                                    // Remove unfeasible neighbor from the list of neighbors
                                    it = min->nbh.erase(it);
                                    continue;
                                }
                                else
                                {
                                    // mark than the motino has been checked as valid
                                    it->second = true;
                                }
                            }
                            if (updateChildren_)
                            {
                                // Remove this node from its parent list
                                removeFromParent(nb);
                                // add it as a children of min
                                min->children.push_back(nb);
                            }
                            // Add this node to the new parent
                            nb->parent = min;
                            ++rewireTest;
                        }
                        nb->cost = cost;

                        // Add to the queue for more improvements
                        updateQueue(nb);

                        checkForSolution = true;
                    }
                    ++it;
                }
                if (updateChildren_)
                {
                    // Propagatino of the cost to the children
                    for (auto it = min->children.begin(), end = min->children.end(); it != end; ++it)
                    {
                        c = *it;
                        incCost = opt_->motionCost(min->state, c->state);
                        cost = opt_->combineCosts(min->cost, incCost);
                        c->cost = cost;
                        // Add to the queue for more improvements
                        updateQueue(c);

                        checkForSolution = true;
                    }
                }
            }

            // empty q and reset handles
            while (!q_.empty())
            {
                q_.top()->data->handle = nullptr;
                q_.pop();
            }
            q_.clear();

            // Checking for solution or iterative improvement
            if (checkForSolution)
            {
                bool updatedSolution = false;
                for (auto &goalMotion : goalMotions_)
                {
                    if (opt_->isCostBetterThan(goalMotion->cost, bestCost_))
                    {
                        if (opt_->isFinite(bestCost_) == false)
                        {
                            OMPL_INFORM("%s: Found an initial solution with a cost of %.2f in %u iterations (%u "
                                        "vertices in the graph)",
                                        getName().c_str(), goalMotion->cost.value(), iterations_, nn_->size());
                        }
                        bestCost_ = goalMotion->cost;
                        updatedSolution = true;
                    }

                    sufficientlyShort = opt_->isSatisfied(goalMotion->cost);
                    if (sufficientlyShort)
                    {
                        solution = goalMotion;
                        break;
                    }
                    else if (!solution || opt_->isCostBetterThan(goalMotion->cost, solution->cost))
                    {
                        solution = goalMotion;
                        updatedSolution = true;
                    }
                }

                if (updatedSolution)
                {
                    if (intermediateSolutionCallback)
                    {
                        std::vector<const base::State *> spath;
                        Motion *intermediate_solution =
                            solution->parent;  // Do not include goal state to simplify code.

                        // Push back until we find the start, but not the start itself
                        while (intermediate_solution->parent != nullptr)
                        {
                            spath.push_back(intermediate_solution->state);
                            intermediate_solution = intermediate_solution->parent;
                        }

                        intermediateSolutionCallback(this, spath, bestCost_);
                    }
                }
            }

            // Checking for approximate solution (closest state found to the goal)
            if (goalMotions_.size() == 0 && distanceFromGoal < approximatedist)
            {
                approximation = motion;
                approximatedist = distanceFromGoal;
            }
        }

        // terminate if a sufficient solution is found
        if (solution && sufficientlyShort)
            break;
    }

    bool approximate = (solution == nullptr);
    bool addedSolution = false;
    if (approximate)
        solution = approximation;
    else
        lastGoalMotion_ = solution;

    if (solution != nullptr)
    {
        ptc.terminate();
        // construct the solution path
        std::vector<Motion *> mpath;
        while (solution != nullptr)
        {
            mpath.push_back(solution);
            solution = solution->parent;
        }

        // set the solution path
        auto path = std::make_shared<PathGeometric>(si_);
        for (int i = mpath.size() - 1; i >= 0; --i)
            path->append(mpath[i]->state);

        // Add the solution path.
        base::PlannerSolution psol(path);
        psol.setPlannerName(getName());
        if (approximate)
            psol.setApproximate(approximatedist);
        // Does the solution satisfy the optimization objective?
        psol.setOptimized(opt_, bestCost_, sufficientlyShort);
        pdef_->addSolutionPath(psol);

        addedSolution = true;
    }

    si_->freeState(xstate);
    if (rmotion->state)
        si_->freeState(rmotion->state);
    delete rmotion;

    OMPL_INFORM("%s: Created %u new states. Checked %u rewire options. %u goal states in tree. Final solution cost "
                "%.3f",
                getName().c_str(), statesGenerated, rewireTest, goalMotions_.size(), bestCost_.value());

    return {addedSolution, approximate};
}