コード例 #1
0
ファイル: SBL.cpp プロジェクト: ompl/ompl
bool ompl::geometric::SBL::isPathValid(TreeData &tree, Motion *motion)
{
    std::vector<Motion *> mpath;

    /* construct the solution path */
    while (motion != nullptr)
    {
        mpath.push_back(motion);
        motion = motion->parent;
    }

    /* check the path */
    for (int i = mpath.size() - 1; i >= 0; --i)
        if (!mpath[i]->valid)
        {
            if (si_->checkMotion(mpath[i]->parent->state, mpath[i]->state))
                mpath[i]->valid = true;
            else
            {
                removeMotion(tree, mpath[i]);
                return false;
            }
        }
    return true;
}
コード例 #2
0
ファイル: LBKPIECE1.cpp プロジェクト: giogadi/ompl
void ompl::geometric::LBKPIECE1::removeMotion(Discretization<Motion> &disc, Motion *motion)
{
    /* remove from grid */

    Discretization<Motion>::Coord coord;
    projectionEvaluator_->computeCoordinates(motion->state, coord);
    disc.removeMotion(motion, coord);

    /* remove self from parent list */

    if (motion->parent)
    {
        for (unsigned int i = 0 ; i < motion->parent->children.size() ; ++i)
            if (motion->parent->children[i] == motion)
            {
                motion->parent->children.erase(motion->parent->children.begin() + i);
                break;
            }
    }

    /* remove children */
    for (unsigned int i = 0 ; i < motion->children.size() ; ++i)
    {
        motion->children[i]->parent = NULL;
        removeMotion(disc, motion->children[i]);
    }

    freeMotion(motion);
}
コード例 #3
0
ファイル: LazyRRT.cpp プロジェクト: OspreyX/ompl-informed
void ompl::geometric::LazyRRT::removeMotion(Motion *motion)
{
    nn_->remove(motion);

    /* remove self from parent list */

    if (motion->parent)
    {
        for (unsigned int i = 0 ; i < motion->parent->children.size() ; ++i)
            if (motion->parent->children[i] == motion)
            {
                motion->parent->children.erase(motion->parent->children.begin() + i);
                break;
            }
    }

    /* remove children */
    for (unsigned int i = 0 ; i < motion->children.size() ; ++i)
    {
        motion->children[i]->parent = NULL;
        removeMotion(motion->children[i]);
    }

    if (motion->state)
        si_->freeState(motion->state);
    delete motion;
}
コード例 #4
0
//-----------------------------------------------------------------------------
// purgeExcessMotion()
//-----------------------------------------------------------------------------
void LLMotionController::purgeExcessMotions()
{
	if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
	{
		// clean up deprecated motions
		for (motion_set_t::iterator deprecated_motion_it = mDeprecatedMotions.begin(); 
			 deprecated_motion_it != mDeprecatedMotions.end(); )
		{
			motion_set_t::iterator cur_iter = deprecated_motion_it++;
			LLMotion* cur_motionp = *cur_iter;
			if (!isMotionActive(cur_motionp))
			{
				// Motion is deprecated so we know it's not cannonical,
				//  we can safely remove the instance
				removeMotionInstance(cur_motionp); // modifies mDeprecatedMotions
				mDeprecatedMotions.erase(cur_iter);
			}
		}
	}

	std::set<LLUUID> motions_to_kill;
	if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
	{
		// too many motions active this frame, kill all blenders
		mPoseBlender.clearBlenders();
		for (motion_set_t::iterator loaded_motion_it = mLoadedMotions.begin(); 
			 loaded_motion_it != mLoadedMotions.end(); 
			 ++loaded_motion_it)
		{
			LLMotion* cur_motionp = *loaded_motion_it;
			// motion isn't playing, delete it
			if (!isMotionActive(cur_motionp))
			{
				motions_to_kill.insert(cur_motionp->getID());
			}
		}
	}
	
	// clean up all inactive, loaded motions
	for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin();
		motion_it != motions_to_kill.end();
		++motion_it)
	{
		// look up the motion again by ID to get canonical instance
		// and kill it only if that one is inactive
		LLUUID motion_id = *motion_it;
		LLMotion* motionp = findMotion(motion_id);
		if (motionp && !isMotionActive(motionp))
		{
			removeMotion(motion_id);
		}
	}

	if (mLoadedMotions.size() > 2*MAX_MOTION_INSTANCES)
	{
		LL_WARNS_ONCE("Animation") << "> " << 2*MAX_MOTION_INSTANCES << " Loaded Motions" << llendl;
	}
}
コード例 #5
0
ファイル: SBL.cpp プロジェクト: ompl/ompl
void ompl::geometric::SBL::removeMotion(TreeData &tree, Motion *motion)
{
    /* remove from grid */

    Grid<MotionInfo>::Coord coord(projectionEvaluator_->getDimension());
    projectionEvaluator_->computeCoordinates(motion->state, coord);
    Grid<MotionInfo>::Cell *cell = tree.grid.getCell(coord);
    if (cell)
    {
        for (unsigned int i = 0; i < cell->data.size(); ++i)
        {
            if (cell->data[i] == motion)
            {
                cell->data.erase(cell->data.begin() + i);
                tree.size--;
                break;
            }
        }
        if (cell->data.empty())
        {
            tree.pdf.remove(cell->data.elem_);
            tree.grid.remove(cell);
            tree.grid.destroyCell(cell);
        }
        else
        {
            tree.pdf.update(cell->data.elem_, 1.0 / cell->data.size());
        }
    }

    /* remove self from parent list */

    if (motion->parent)
    {
        for (unsigned int i = 0; i < motion->parent->children.size(); ++i)
        {
            if (motion->parent->children[i] == motion)
            {
                motion->parent->children.erase(motion->parent->children.begin() + i);
                break;
            }
        }
    }

    /* remove children */
    for (auto &i : motion->children)
    {
        i->parent = nullptr;
        removeMotion(tree, i);
    }

    if (motion->state)
        si_->freeState(motion->state);
    delete motion;
}
コード例 #6
0
ファイル: pSBL.cpp プロジェクト: giogadi/ompl
void ompl::geometric::pSBL::removeMotion(TreeData &tree, Motion *motion, std::map<Motion*, bool> &seen)
{
    /* remove from grid */
    seen[motion] = true;

    Grid<MotionInfo>::Coord coord;
    projectionEvaluator_->computeCoordinates(motion->state, coord);
    Grid<MotionInfo>::Cell* cell = tree.grid.getCell(coord);
    if (cell)
    {
        for (unsigned int i = 0 ; i < cell->data.size(); ++i)
            if (cell->data[i] == motion)
            {
                cell->data.erase(cell->data.begin() + i);
                tree.size--;
                break;
            }
        if (cell->data.empty())
        {
            tree.pdf.remove(cell->data.elem_);
            tree.grid.remove(cell);
            tree.grid.destroyCell(cell);
        }
        else
        {
            tree.pdf.update(cell->data.elem_, 1.0/cell->data.size());
        }
    }

    /* remove self from parent list */

    if (motion->parent)
    {
        for (unsigned int i = 0 ; i < motion->parent->children.size() ; ++i)
            if (motion->parent->children[i] == motion)
            {
                motion->parent->children.erase(motion->parent->children.begin() + i);
                break;
            }
    }

    /* remove children */
    for (unsigned int i = 0 ; i < motion->children.size() ; ++i)
    {
        motion->children[i]->parent = NULL;
        removeMotion(tree, motion->children[i], seen);
    }

    if (motion->state)
        si_->freeState(motion->state);
    delete motion;
}
コード例 #7
0
//-----------------------------------------------------------------------------
// purgeExcessMotion()
//-----------------------------------------------------------------------------
void LLMotionController::purgeExcessMotions()
{
	//<singu>
	// The old code attempted to remove non-active motions from mDeprecatedMotions,
	// but that is nonsense: there are no motions in mDeprecatedMotions that are not active.
	if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
	{
		// Speed up, no need to create motions_to_kill.
		return;
	}
	//</singu>

	std::set<LLUUID> motions_to_kill;

	if (1)	// Singu: leave indentation alone...
	{
		// too many motions active this frame, kill all blenders
		mPoseBlender.clearBlenders();
		for (motion_set_t::iterator loaded_motion_it = mLoadedMotions.begin(); 
			 loaded_motion_it != mLoadedMotions.end(); 
			 ++loaded_motion_it)
		{
			LLMotion* cur_motionp = *loaded_motion_it;
			// motion isn't playing, delete it
			if (!isMotionActive(cur_motionp))
			{
				motions_to_kill.insert(cur_motionp->getID());
			}
		}
	}
	
	// clean up all inactive, loaded motions
	for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin();
		motion_it != motions_to_kill.end();
		++motion_it)
	{
		// look up the motion again by ID to get canonical instance
		// and kill it only if that one is inactive
		LLUUID motion_id = *motion_it;
		LLMotion* motionp = findMotion(motion_id);
		if (motionp && !isMotionActive(motionp))
		{
			removeMotion(motion_id);
		}
	}

	if (mLoadedMotions.size() > 2*MAX_MOTION_INSTANCES)
	{
		LL_WARNS_ONCE("Animation") << "> " << 2*MAX_MOTION_INSTANCES << " Loaded Motions" << llendl;
	}
}
コード例 #8
0
ファイル: LBKPIECE1.cpp プロジェクト: giogadi/ompl
bool ompl::geometric::LBKPIECE1::isPathValid(Discretization<Motion> &disc, Motion *motion, base::State *temp)
{
    std::vector<Motion*> mpath;

    /* construct the solution path */
    while (motion != NULL)
    {
        mpath.push_back(motion);
        motion = motion->parent;
    }

    std::pair<base::State*, double> lastValid;
    lastValid.first = temp;

    /* check the path */
    for (int i = mpath.size() - 1 ; i >= 0 ; --i)
        if (!mpath[i]->valid)
        {
            if (si_->checkMotion(mpath[i]->parent->state, mpath[i]->state, lastValid))
                mpath[i]->valid = true;
            else
            {
                Motion *parent = mpath[i]->parent;
                removeMotion(disc, mpath[i]);

                // add the valid part of the path, if sufficiently long
                if (lastValid.second > minValidPathFraction_)
                {
                    Motion* reAdd = new Motion(si_);
                    si_->copyState(reAdd->state, lastValid.first);
                    reAdd->parent = parent;
                    reAdd->root = parent->root;
                    parent->children.push_back(reAdd);
                    reAdd->valid = true;
                    Discretization<Motion>::Coord coord;
                    projectionEvaluator_->computeCoordinates(reAdd->state, coord);
                    disc.addMotion(reAdd, coord);
                }

                return false;
            }
        }
    return true;
}
コード例 #9
0
ファイル: LazyRRT.cpp プロジェクト: goretkin/kwc-ros-pkg
void ompl::LazyRRT::removeMotion(Motion_t motion)
{
    assert(m_nn.remove(motion));
    
    /* remove self from parent list */
    
    if (motion->parent)
    {
	for (unsigned int i = 0 ; i < motion->parent->children.size() ; ++i)
	    if (motion->parent->children[i] == motion)
	    {
		motion->parent->children.erase(motion->parent->children.begin() + i);
		break;
	    }
    }    

    /* remove children */
    for (unsigned int i = 0 ; i < motion->children.size() ; ++i)
    {
	motion->children[i]->parent = NULL;
	removeMotion(motion->children[i]);
    }
}
コード例 #10
0
ファイル: LazyRRT.cpp プロジェクト: OspreyX/ompl-informed
ompl::base::PlannerStatus ompl::geometric::LazyRRT::solve(const base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    base::Goal                 *goal   = pdef_->getGoal().get();
    base::GoalSampleableRegion *goal_s = dynamic_cast<base::GoalSampleableRegion*>(goal);

    while (const base::State *st = pis_.nextStart())
    {
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, st);
        motion->valid = true;
        nn_->add(motion);
    }

    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());

    Motion *solution = NULL;
    double  distsol  = -1.0;
    Motion *rmotion  = new Motion(si_);
    base::State *rstate = rmotion->state;
    base::State *xstate = si_->allocState();

    bool solutionFound = false;

    while (ptc == false && !solutionFound)
    {
        /* 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);
        assert(nmotion != rmotion);
        base::State *dstate = rstate;

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

        /* create a motion */
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, dstate);
        motion->parent = nmotion;
        nmotion->children.push_back(motion);
        nn_->add(motion);

        double dist = 0.0;
        if (goal->isSatisfied(motion->state, &dist))
        {
            distsol = dist;
            solution = motion;
            solutionFound = true;
            lastGoalMotion_ = solution;

            // Check that the solution is valid:
            // construct the solution path
            std::vector<Motion*> mpath;
            while (solution != NULL)
            {
                mpath.push_back(solution);
                solution = solution->parent;
            }

            // check each segment along the path for validity
            for (int i = mpath.size() - 1 ; i >= 0 && solutionFound; --i)
                if (!mpath[i]->valid)
                {
                    if (si_->checkMotion(mpath[i]->parent->state, mpath[i]->state))
                        mpath[i]->valid = true;
                    else
                    {
                        removeMotion(mpath[i]);
                        solutionFound = false;
                        lastGoalMotion_ = NULL;
                    }
                }

            if (solutionFound)
            {
                // set the solution path
                PathGeometric *path = new PathGeometric(si_);
                for (int i = mpath.size() - 1 ; i >= 0 ; --i)
                    path->append(mpath[i]->state);

                pdef_->addSolutionPath(base::PathPtr(path), false, distsol, getName());
            }
        }
    }

    si_->freeState(xstate);
    si_->freeState(rstate);
    delete rmotion;

    OMPL_INFORM("%s: Created %u states", getName().c_str(), nn_->size());

    return solutionFound ?  base::PlannerStatus::EXACT_SOLUTION : base::PlannerStatus::TIMEOUT;
}
コード例 #11
0
ファイル: pSBL.cpp プロジェクト: RickOne16/ompl
void ompl::geometric::pSBL::threadSolve(unsigned int tid, const base::PlannerTerminationCondition &ptc, SolutionInfo *sol)
{
    RNG rng;

    std::vector<Motion*> solution;
    base::State *xstate = si_->allocState();
    bool      startTree = rng.uniformBool();

    while (!sol->found && ptc == false)
    {
        bool retry = true;
        while (retry && !sol->found && ptc == false)
        {
            removeList_.lock.lock();
            if (!removeList_.motions.empty())
            {
                if (loopLock_.try_lock())
                {
                    retry = false;
                    std::map<Motion*, bool> seen;
                    for (unsigned int i = 0 ; i < removeList_.motions.size() ; ++i)
                        if (seen.find(removeList_.motions[i].motion) == seen.end())
                            removeMotion(*removeList_.motions[i].tree, removeList_.motions[i].motion, seen);
                    removeList_.motions.clear();
                    loopLock_.unlock();
                }
            }
            else
                retry = false;
            removeList_.lock.unlock();
        }

        if (sol->found || ptc)
            break;

        loopLockCounter_.lock();
        if (loopCounter_ == 0)
            loopLock_.lock();
        loopCounter_++;
        loopLockCounter_.unlock();


        TreeData &tree      = startTree ? tStart_ : tGoal_;
        startTree = !startTree;
        TreeData &otherTree = startTree ? tStart_ : tGoal_;

        Motion *existing = selectMotion(rng, tree);
        if (!samplerArray_[tid]->sampleNear(xstate, existing->state, maxDistance_))
            continue;

        /* create a motion */
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, xstate);
        motion->parent = existing;
        motion->root = existing->root;

        existing->lock.lock();
        existing->children.push_back(motion);
        existing->lock.unlock();

        addMotion(tree, motion);

        if (checkSolution(rng, !startTree, tree, otherTree, motion, solution))
        {
            sol->lock.lock();
            if (!sol->found)
            {
                sol->found = true;
                PathGeometric *path = new PathGeometric(si_);
                for (unsigned int i = 0 ; i < solution.size() ; ++i)
                    path->append(solution[i]->state);
                pdef_->addSolutionPath(base::PathPtr(path), false, 0.0, getName());
            }
            sol->lock.unlock();
        }


        loopLockCounter_.lock();
        loopCounter_--;
        if (loopCounter_ == 0)
            loopLock_.unlock();
        loopLockCounter_.unlock();
    }

    si_->freeState(xstate);
}
コード例 #12
0
ファイル: LazyRRT.cpp プロジェクト: goretkin/kwc-ros-pkg
bool ompl::LazyRRT::solve(double solveTime)
{
    SpaceInformationKinematic_t                          si = dynamic_cast<SpaceInformationKinematic_t>(m_si); 
    SpaceInformationKinematic::GoalRegionKinematic_t goal_r = dynamic_cast<SpaceInformationKinematic::GoalRegionKinematic_t>(si->getGoal());
    SpaceInformationKinematic::GoalStateKinematic_t  goal_s = dynamic_cast<SpaceInformationKinematic::GoalStateKinematic_t>(si->getGoal());
    unsigned int                                        dim = si->getStateDimension();

    if (!goal_s && !goal_r)
    {
	m_msg.error("Unknown type of goal (or goal undefined)");
	return false;
    }
    
    time_utils::Time endTime = time_utils::Time::now() + time_utils::Duration(solveTime);

    if (m_nn.size() == 0)
    {
	for (unsigned int i = 0 ; i < m_si->getStartStateCount() ; ++i)
	{
	    Motion_t motion = new Motion(dim);
	    si->copyState(motion->state, dynamic_cast<SpaceInformationKinematic::StateKinematic_t>(si->getStartState(i)));
	    if (si->isValid(motion->state))
	    { 
		motion->valid = true;
		m_nn.add(motion);
	    }	
	    else
	    {
		m_msg.error("Initial state is in collision!");
		delete motion;
	    }	
	}
    }
    
    if (m_nn.size() == 0)
    {
	m_msg.error("There are no valid initial states!");
	return false;	
    }    

    m_msg.inform("Starting with %u states", m_nn.size());

    std::vector<double> range(dim);
    for (unsigned int i = 0 ; i < dim ; ++i)
	range[i] = m_rho * (si->getStateComponent(i).maxValue - si->getStateComponent(i).minValue);
    
    Motion_t                                    solution = NULL;
    double                                      distsol  = -1.0;
    Motion_t                                    rmotion  = new Motion(dim);
    SpaceInformationKinematic::StateKinematic_t rstate   = rmotion->state;
    SpaceInformationKinematic::StateKinematic_t xstate   = new SpaceInformationKinematic::StateKinematic(dim);
    
 RETRY:

    while (time_utils::Time::now() < endTime)
    {
	/* sample random state (with goal biasing) */
	if (goal_s && random_utils::uniform(&m_rngState, 0.0, 1.0) < m_goalBias)
	    si->copyState(rstate, goal_s->state);
	else
	    si->sample(rstate);

	/* find closest state in the tree */
	Motion_t nmotion = m_nn.nearest(rmotion);
	assert(nmotion != rmotion);
	
	/* find state to add */
	for (unsigned int i = 0 ; i < dim ; ++i)
	{
	    double diff = rmotion->state->values[i] - nmotion->state->values[i];
	    xstate->values[i] = fabs(diff) < range[i] ? rmotion->state->values[i] : nmotion->state->values[i] + diff * m_rho;
	}
	
	/* create a motion */
	Motion_t motion = new Motion(dim);
	si->copyState(motion->state, xstate);
	motion->parent = nmotion;
	nmotion->children.push_back(motion);
	m_nn.add(motion);
	
	double dist = 0.0;
	if (goal_r->isSatisfied(motion->state, &dist))
	{
	    distsol = dist;
	    solution = motion;
	    break;
	}
    }    


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

	/* check the path */
	for (int i = mpath.size() - 1 ; i >= 0 ; --i)
	    if (!mpath[i]->valid)
	    {
		if (si->checkMotionSubdivision(mpath[i]->parent->state, mpath[i]->state))
		    mpath[i]->valid = true;
		else
		{
		    removeMotion(mpath[i]);
		    goto RETRY;
		}
	    }
	
	/*set the solution path */
	SpaceInformationKinematic::PathKinematic_t path = new SpaceInformationKinematic::PathKinematic(m_si);
   	for (int i = mpath.size() - 1 ; i >= 0 ; --i)
	{
	    SpaceInformationKinematic::StateKinematic_t st = new SpaceInformationKinematic::StateKinematic(dim);
	    si->copyState(st, mpath[i]->state);
	    path->states.push_back(st);
	}

	goal_r->setDifference(distsol);
	goal_r->setSolutionPath(path);	
    }

    delete xstate;
    delete rmotion;

    m_msg.inform("Created %u states", m_nn.size());

    return goal_r->isAchieved();
}
コード例 #13
0
ファイル: LazyRRT.cpp プロジェクト: megan-starr9/UAV_Aiolos
bool ompl::geometric::LazyRRT::solve(const base::PlannerTerminationCondition &ptc)
{
    checkValidity();
    base::Goal                 *goal   = pdef_->getGoal().get();
    base::GoalSampleableRegion *goal_s = dynamic_cast<base::GoalSampleableRegion*>(goal);

    while (const base::State *st = pis_.nextStart())
    {
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, st);
        motion->valid = true;
        nn_->add(motion);
    }

    if (nn_->size() == 0)
    {
        msg_.error("There are no valid initial states!");
        return false;
    }

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

    msg_.inform("Starting with %u states", nn_->size());

    Motion *solution = NULL;
    double  distsol  = -1.0;
    Motion *rmotion  = new Motion(si_);
    base::State *rstate = rmotion->state;
    base::State *xstate = si_->allocState();

 RETRY:

    while (ptc() == false)
    {
        /* 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);
        assert(nmotion != rmotion);
        base::State *dstate = rstate;

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

        /* create a motion */
        Motion *motion = new Motion(si_);
        si_->copyState(motion->state, dstate);
        motion->parent = nmotion;
        nmotion->children.push_back(motion);
        nn_->add(motion);

        double dist = 0.0;
        if (goal->isSatisfied(motion->state, &dist))
        {
            distsol = dist;
            solution = motion;
            break;
        }
    }

    bool solved = false;
    if (solution != NULL)
    {
        /* construct the solution path */
        std::vector<Motion*> mpath;
        while (solution != NULL)
        {
            mpath.push_back(solution);
            solution = solution->parent;
        }

        /* check the path */
        for (int i = mpath.size() - 1 ; i >= 0 ; --i)
            if (!mpath[i]->valid)
            {
                if (si_->checkMotion(mpath[i]->parent->state, mpath[i]->state))
                    mpath[i]->valid = true;
                else
                {
                    removeMotion(mpath[i]);
                    goto RETRY;
                }
            }

        /* set the solution path */
        PathGeometric *path = new PathGeometric(si_);
        for (int i = mpath.size() - 1 ; i >= 0 ; --i)
            path->append(mpath[i]->state);

        goal->addSolutionPath(base::PathPtr(path), false, distsol);
        solved = true;
    }

    si_->freeState(xstate);
    si_->freeState(rstate);
    delete rmotion;

    msg_.inform("Created %u states", nn_->size());

    return solved;
}