我不太了解Compiler错误中的成员函数
C2436 '{ctor}': member function or nested class in constructor initializer list
使用Visual C ++
在我的SubNearestNeighbors.hpp中写:
template<typename _T>
class SubNearestNeighbors : public ompl::NearestNeighbors<_T>
{
public:
typedef std::function<double(const _T&, const _T&)> DistanceFunction;
SubNearestNeighbors(const ob::SpaceInformationPtr &si)
:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
{}
SubNearestNeighbors()// here is the member function cause the error <----
: // but it doesn't have any void in it? |
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect() |
{} // error get here, it say member func. or nested class in constructor|
// initialize list, while compiling class template member function |
//'SubNearestNeighbors<PathPlannerOMPLServer::kdRRTConnect::Motion*> |
//::SubNearestNeighbors(void) ---------------------------------------
~SubNearestNeighbors()
{
}
//...more other function
kdRRTConnect.cpp中的代码编写为:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
:
ompl::base::Planner((const base::SpaceInformationPtr &)*((base::SpaceInformationPtr*)(unsigned char*)0), "kdRRTConnect") {
typedef std::shared_ptr < ompl::NearestNeighbors<Motion*>> nn_ptr;
nn_ptr nn_;
nn_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}
Output Tipp tells me that the problem of member function is SubNearestNeighbors(void)
有人可以给我小费吗,这意味着初始化成员列表中的成员函数SubNearestNeighbors(void),但实际上在SubNearestNeighbors中不存在任何空白。
答案 0 :(得分:0)
感谢@ M.M和@Fei Xiang。
因为_T是在公共ompl :: nearestneighbors <_T>中定义的(这里是该类的链接:ompl.kavrakilab.org/NearestNeighbors_8h_source.html),所以仅模拟了另一个类NearestNeighborsLinear(ompl.kavrakilab.org /NearestNeighborsLinear_8h_source.html)、NearestNeighborsGNAT(ompl.kavrakilab.org/NearestNeighborsGNAT_8h_source.html)、NearestNeighborsAqrtApprox(ompl.kavrakilab.org/NearestNeighborsSqrtApprox_mpl.8):我写模板没有其他选择。
在这里,我给出了Ompl :: NearestNeighbors <_T>类的代码,我继承并覆盖了该类中的函数。
namespace ompl
{
template <typename _T>
class NearestNeighbors
{
public:
typedef std::function<double(const _T &, const _T &)> DistanceFunction;
NearestNeighbors() = default;
virtual ~NearestNeighbors() = default;
virtual void setDistanceFunction(const DistanceFunction &distFun)
{
distFun_ = distFun;
}
const DistanceFunction &getDistanceFunction() const
{
return distFun_;
}
virtual bool reportsSortedResults() const = 0;
virtual void clear() = 0;
virtual void add(const _T &data) = 0;
virtual void add(const std::vector<_T> &data)
{
for (const auto &elt : data)
add(elt);
}
virtual bool remove(const _T &data) = 0;
virtual _T nearest(const _T &data) const = 0;
virtual void nearestK(const _T &data, std::size_t k, std::vector<_T> &nbh) const = 0;
virtual void nearestR(const _T &data, double radius, std::vector<_T> &nbh) const = 0;
virtual std::size_t size() const = 0;
virtual void list(std::vector<_T> &data) const = 0;
protected:
DistanceFunction distFun_;
};
}
在这里,我很难举一个最小的例子。有关更多详细信息,请完成我的SubNearestNeighbors类:
template<typename _T>
class SubNearestNeighbors: public ompl::NearestNeighbors<_T>
{
public:
SubNearestNeighbors(const ob::SpaceInformationPtr &si)
:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(){}
SubNearestNeighbors()
:
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(){}
~SubNearestneighbors()
{
}
// All the functions below are just override all of the pure virtual function in ompl::NearestNeighbors<_T>
void clear()
{
motions.clear();
}
void list(std::vector<_T> &data) const
{
typename PathPlannerOMPLServer::kdRRTConnect::Motion;
data = motions;
}
std::size_t size() const
{
return motions.size();
}
void add(const _T &data)
{
typename PathPlannerOMPLServer::kdRRTConnect::Motion;
motions.push_back(data);
}
bool remove(const _T &data)
{
typename PathPlannerOMPLServer::kdRRTConnect::Motion;
if (!motions.empty())
for (int i = motions.size() - 1; i >= 0; --i)
if (motions[i] == data)
{
motions.erase(motions.begin() + i);
return true;
}
return false;
}
_T nearest(const _T &data) const
{
typename PathPlannerOMPLServer::kdRRTConnect::Motion;
// here is about 1000 lines code
// I am sure here works, because i have test it in main.cpp and that's really
// what i want. The logic are just get n random point, which are the around
// small room of state (rstate in RRTConnect )-> build the KD Tree -> give a
// searchPoint to find the nearestNeighbor point in KDTree -> convert the
// nearestNeighbor point in state -> make a new motion *nmotion -> save it i
//in motion->state
return motion;
}
protected:
std::vector<_T> motions;
};
现在我给我完整的kdRRTConnect,与RRTConnect Planner一样快 RRTConnect.h(http://ompl.kavrakilab.org/RRTConnect_8h_source.html) RRTConnect.cpp(http://ompl.kavrakilab.org/RRTConnect_8cpp_source.html)
在kdRRTConnect.h
namespace ob = ompl::base;
namespace og = ompl::geometric;
namespace PathPlannerOMPLServer
{
class kdRRTConnect :public ompl::base::Planner
{
public:
//brief constructor
kdRRTConnect(const ompl::base::SpaceInformationPtr &si);
kdRRTConnect();
virtual ~kdRRTConnect();
virtual void getPlannerData(ompl::base::PlannerData &data)const;
virtual ompl::base::PlannerStatus solve(const ompl::base::PlannerTerminationCondition &ptc);
virtual void clear();
void setRange(double distance)
{
maxDistance_ = distance;
}
double getRange() const
{
return maxDistance_;
}
template<template<typename T> class NN>
void setNearestNeighbors()
{
tStart_.reset(new NN<Motion*>());
tStart_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
tGoal_.reset(new NN<Motion*>());
tGoal_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}
virtual void setup();
//define Motion same as RRTConnect, but in public
class Motion
{
public:
Motion() : root(nullptr), state(nullptr), parent(nullptr)
{
parent = nullptr;
state = nullptr;
}
Motion(const ompl::base::SpaceInformationPtr &si) : root(nullptr), state(si->allocState()), parent(nullptr)
{
}
~Motion()
{
}
const ompl::base::State *root;
ompl::base::State *state;
Motion *parent;
};
protected:
// a Sub nearest-neighbor datastructure represents a tree of motions
typedef std::shared_ptr< ompl::NearestNeighbors<Motion*>> TreeData;
//brief Info. attached to gowing a tree motions(use internally)
struct TreeGrowingInfo
{
ompl::base::State *xstate;
Motion *xmotion;
bool start;
};
//brief The state of the tree after an attempt to extend it
enum GrowState
{
/// no progress has been made
TRAPPED,
/// progress has been made towards the randomly sampled state
ADVANCED,
/// the randomly sampled state was reached, d !> maxDistance
//double d = si_->distance(nmotion->state, rmotion->state); <- in growTree()
REACHED
};
//brief Free the memory allocated by this planner
void freeMemory();
double distance(const ob::State *p1, const ob::State *p2)
{
//define p1's and p2's StateType as SE3StateSpace
const ob::SE3StateSpace::StateType* state3Dp1 = p1->as<ob::SE3StateSpace::StateType>();
double x1 = state3Dp1->getX();
double y1 = state3Dp1->getY();
double z1 = state3Dp1->getZ();
const ob::SE3StateSpace::StateType* state3Dp2 = p2->as<ob::SE3StateSpace::StateType>();
double x2 = state3Dp2->getX();
double y2 = state3Dp2->getY();
double z2 = state3Dp2->getZ();
double dx = x1 - x2;
double dy = y1 - y2;
double dz = z1 - z2;
return sqrt(dx*dx + dy*dy + dz*dz);
}
double distanceFunction(const Motion *a, const Motion *b) const
{
ob::State *stateA = a->state;
ob::State *stateB = b->state;
ob::SE3StateSpace::StateType* stateTypeA = stateA->as<ob::SE3StateSpace::StateType>();
ob::SE3StateSpace::StateType* stateTypeB = stateB->as<ob::SE3StateSpace::StateType>();
double x1 = stateTypeA->getX();
double y1 = stateTypeA->getY();
double z1 = stateTypeA->getZ();
double x2 = stateTypeB->getX();
double y2 = stateTypeB->getY();
double z2 = stateTypeB->getZ();
double dx = x1 - x2;
double dy = y1 - y2;
double dz = z1 - z2;
return sqrt(dx * dx + dy * dy + dz * dz);
}
void interpolate(const ob::State *from, const ob::State *to, const double t, ob::State *state) const
{
const ob::SE3StateSpace::StateType* s1 = from->as<ob::SE3StateSpace::StateType>();
const ob::SE3StateSpace::StateType* s2 = to->as<ob::SE3StateSpace::StateType>();
ob::SE3StateSpace::StateType* lastValid = state->as<ob::SE3StateSpace::StateType>();
//Separate the path from s1 to s2 into nd Segment. nd = stateSpace_->validSegmentCount(s1, s2); in checkMotion and get the distance difference of X,Y,Z Value form s1 to s2
double distanceX = s2->getX() - s1->getX();
double distanceY = s2->getY() - s1->getY();
double distanceZ = s2->getZ() - s1->getZ();
lastValid->setXYZ(s1->getX() + distanceX*t, s1->getY() + distanceY*t, s1->getZ() + distanceZ*t);
}
//brief Grow a tree towards a random state
GrowState growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion);
//brief State sampler
ompl::base::StateSamplerPtr sampler_;
//brief The start tree
TreeData tStart_;
//brief The goal tree
TreeData tGoal_;
//brief The maximum length of a motion to be added to a tree
double maxDistance_;
//brief The random number generator
ompl::RNG rng_;
/** \brief The pair of states in each tree connected during planning. Used for PlannerData computation */
std::pair<ompl::base::State*, ompl::base::State*> connectionPoint_;
};
}
在kdRRTConnect.cpp
namespace ob = ompl::base;
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect(const ompl::base::SpaceInformationPtr &si) : ompl::base::Planner(si, "kdRRTConnect")
{
specs_.recognizedGoal = ompl::base::GOAL_SAMPLEABLE_REGION;
specs_.directed = true;
maxDistance_ = 0.0;
Planner::declareParam<double>("range", this, &kdRRTConnect::setRange, &kdRRTConnect::getRange, "0.:1.:10000.");
connectionPoint_ = std::make_pair<ompl::base::State*, ompl::base::State*>(nullptr, nullptr);
}
PathPlannerOMPLServer::kdRRTConnect::kdRRTConnect()
:
ompl::base::Planner((const ompl::base::SpaceInformationPtr &)*((ompl::base::SpaceInformationPtr*)(unsigned char*)0), "kdRRTConnect")
{
//typedef std::shared_ptr <Motion> motion_ptr;
typedef std::shared_ptr < ompl::NearestNeighbors<Motion*>> nn_ptr;
nn_ptr nn_;
nn_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}
PathPlannerOMPLServer::kdRRTConnect::~kdRRTConnect()
{
freeMemory();
}
void PathPlannerOMPLServer::kdRRTConnect::setup()
{
Planner::setup();
ompl::tools::SelfConfig sc(si_, getName());
sc.configurePlannerRange(maxDistance_);
if (!tStart_)
tStart_.reset(ompl::tools::SelfConfig::getDefaultNearestNeighbors<Motion*>(this));
if (!tGoal_)
tGoal_.reset(ompl::tools::SelfConfig::getDefaultNearestNeighbors<Motion*>(this));
tStart_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
tGoal_->setDistanceFunction(std::bind(&kdRRTConnect::distanceFunction, this, std::placeholders::_1, std::placeholders::_2));
}
void PathPlannerOMPLServer::kdRRTConnect::freeMemory()
{
std::vector<Motion*> motions;
if (tStart_)
{
tStart_->list(motions);
for (unsigned int i = 0; i < motions.size(); ++i)
{
if (motions[i]->state)
si_->freeState(motions[i]->state);
delete motions[i];
}
}
if (tGoal_)
{
tGoal_->list(motions);
for (unsigned int i = 0; i < motions.size(); ++i)
{
if (motions[i]->state)
si_->freeState(motions[i]->state);
delete motions[i];
}
}
}
void PathPlannerOMPLServer::kdRRTConnect::clear()
{
ompl::base::Planner::clear();
sampler_.reset();
freeMemory();
if (tStart_)
tStart_->clear();
if (tGoal_)
tGoal_->clear();
connectionPoint_ = std::make_pair<ompl::base::State*, ompl::base::State*>(nullptr, nullptr);
}
PathPlannerOMPLServer::kdRRTConnect::GrowState PathPlannerOMPLServer::kdRRTConnect::growTree(TreeData &tree, TreeGrowingInfo &tgi, Motion *rmotion)
{
/* find closest state in the tree */
Motion *nmotion = tree->nearest(rmotion);
/* assume we can reach the state we go towards */
bool reach = true;
/* find state to add */
ompl::base::State *dstate = rmotion->state;
double d = distance(nmotion->state, rmotion->state);
if (d > maxDistance_)
{
//si_->getStateSpace()->interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
interpolate(nmotion->state, rmotion->state, maxDistance_ / d, tgi.xstate);
dstate = tgi.xstate;
reach = false;
}
// if we are in the start tree, we just check the motion like we normally do;
// if we are in the goal tree, we need to check the motion in reverse, but checkMotion() assumes the first state it receives as argument is valid,
// so we check that one first
bool validMotion = tgi.start ? si_->checkMotion(nmotion->state, dstate) : si_->getStateValidityChecker()->isValid(dstate) && si_->checkMotion(dstate, nmotion->state);
if (validMotion)
{
/* create a motion */
Motion *motion = new Motion(si_);
si_->copyState(motion->state, dstate);
motion->parent = nmotion;
motion->root = nmotion->root;
tgi.xmotion = motion;
tree->add(motion);
if (reach)
return REACHED;
else
return ADVANCED;
}
else
return TRAPPED;
}
ompl::base::PlannerStatus PathPlannerOMPLServer::kdRRTConnect::solve(const ompl::base::PlannerTerminationCondition &ptc)
{
checkValidity();
ompl::base::GoalSampleableRegion *goal = dynamic_cast<ompl::base::GoalSampleableRegion*>(pdef_->getGoal().get());
if (!goal)
{
OMPL_ERROR("%s: Unknown type of goal", getName().c_str());
return ompl::base::PlannerStatus::UNRECOGNIZED_GOAL_TYPE;
}
while (const ompl::base::State *st = pis_.nextStart())
{
Motion *motion = new Motion(si_);
si_->copyState(motion->state, st);
motion->root = motion->state;
tStart_->add(motion);
}
if (tStart_->size() == 0)
{
OMPL_ERROR("%s: Motion planning start tree could not be initialized!", getName().c_str());
return ompl::base::PlannerStatus::INVALID_START;
}
if (!goal->couldSample())
{
OMPL_ERROR("%s: Insufficient states in sampleable goal region", getName().c_str());
return ompl::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()));
TreeGrowingInfo tgi;
tgi.xstate = si_->allocState();
Motion *rmotion = new Motion(si_);
ompl::base::State *rstate = rmotion->state;
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 ompl::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);
}
if (tGoal_->size() == 0)
{
OMPL_ERROR("%s: Unable to sample any valid states for goal tree", getName().c_str());
break;
}
}
/* sample random state */
sampler_->sampleUniform(rstate);
GrowState gs = growTree(tree, tgi, rmotion);
if (gs != TRAPPED)
{
/* remember which motion was just added */
Motion *addedMotion = tgi.xmotion;
/* attempt to connect trees */
/* if reached, it means we used rstate directly, no need top copy again */
if (gs != REACHED)
si_->copyState(rstate, tgi.xstate);
GrowState gsc = ADVANCED;
tgi.start = startTree;
while (gsc == ADVANCED)
gsc = growTree(otherTree, tgi, rmotion);
Motion *startMotion = startTree ? tgi.xmotion : addedMotion;
Motion *goalMotion = startTree ? addedMotion : tgi.xmotion;
/* if we connected the trees in a valid way (start and goal pair is valid)*/
if (gsc == REACHED && goal->isStartGoalPairValid(startMotion->root, goalMotion->root))
{
// it must be the case that either the start tree or the goal tree has made some progress
// so one of the parents is not nullptr. We go one step 'back' to avoid having a duplicate state
// on the solution path
if (startMotion->parent)
startMotion = startMotion->parent;
else
goalMotion = goalMotion->parent;
connectionPoint_ = std::make_pair(startMotion->state, goalMotion->state);
/* construct the solution path */
Motion *solution = startMotion;
std::vector<Motion*> mpath1;
while (solution != nullptr)
{
mpath1.push_back(solution);
solution = solution->parent;
}
solution = goalMotion;
std::vector<Motion*> mpath2;
while (solution != nullptr)
{
mpath2.push_back(solution);
solution = solution->parent;
}
ompl::geometric::PathGeometric *path = new ompl::geometric::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(ompl::base::PathPtr(path), false, 0.0, getName());
solved = true;
break;
}
}
}
si_->freeState(tgi.xstate);
si_->freeState(rstate);
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 ? ompl::base::PlannerStatus::EXACT_SOLUTION : ompl::base::PlannerStatus::TIMEOUT;
}
void PathPlannerOMPLServer::kdRRTConnect::getPlannerData(ompl::base::PlannerData &data) const
{
Planner::getPlannerData(data);
std::vector<Motion*> motions;
if (tStart_)
tStart_->list(motions);
for (unsigned int i = 0; i < motions.size(); ++i)
{
if (motions[i]->parent == nullptr)
data.addStartVertex(ompl::base::PlannerDataVertex(motions[i]->state, 1));
else
{
data.addEdge(ompl::base::PlannerDataVertex(motions[i]->parent->state, 1),
ompl::base::PlannerDataVertex(motions[i]->state, 1));
}
}
motions.clear();
if (tGoal_)
tGoal_->list(motions);
for (unsigned int i = 0; i < motions.size(); ++i)
{
if (motions[i]->parent == nullptr)
data.addGoalVertex(ompl::base::PlannerDataVertex(motions[i]->state, 2));
else
{
// The edges in the goal tree are reversed to be consistent with start tree
data.addEdge(ompl::base::PlannerDataVertex(motions[i]->state, 2),
ompl::base::PlannerDataVertex(motions[i]->parent->state, 2));
}
}
// Add the edge connecting the two trees
data.addEdge(data.vertexIndex(connectionPoint_.first), data.vertexIndex(connectionPoint_.second));
}
在这里,我清除了PathPathnerOMPLServer程序的结构,它有四个成员:SubNearestNeighbors,kdRRTConnect,这些函数是我自己编写的near(),isValid(),checkMotion(),interpolate()函数。这四个功能分别独立运行,但是现在我必须让它们与我的Planner kdRRTConnect一起使用。其他两个成员CollisionCheck和MotionValidator与该问题无关。 SubsNearestNeighbor继承OMPL源文件Ompl :: NearestNeighbors <_T>,而kdRRTConnect继承OMPL源文件Ompl :: base :: Planner。在Visual C ++中,所有源文件都构建了一个OMPL库,而我的程序PathPlannerOMPLServer则使用它。在这里我画一幅画来简化我之前所说的内容。Relation between my Program PathPlannerOMPLServer, OMPL Source File and Ompl lib
顺便说一句,我在ompl论坛中曾问过同样的问题,但管理员说这不是错误,请将我的问题设置为无效,不再回答。 这是我问的链接问题#436:https://bitbucket.org/ompl/ompl/issues/436/about-template-after-inheriting-ompl
抱歉,我无法简化示例。
非常感谢,我希望有人能给我更多的小费。
eoeo