OMPL官方教程学习State Validity Checking
State Validity Checking(状态有效性检测?)
State Validity Checking 的功能:描述对于状态空间所给定的某个状态是否有效
OMPL本身不包含State Validity Checking, 因为这个检测过程或者说检测的方法是和实际的问题紧密联系的,从下面的这段话中可以看出,State Validity Checking 这个过程很像是碰撞检测
OMPL itself does not include code for state validity checking. This is intentional, since defining this notion depends on the type of problems to be solved. For instance, OMPL.app defines state validity checking in terms of collision checking between loaded CAD models. The ROS interface to OMPL in MoveIt defines state validity checking to be collision checking between the robot model and sensed objects in the environment. If planning for protein folding, the state validity check has to do with the evaluation of energy functions.
OPML中提供了两个抽象类,来帮助用户定义状态有效性检测
In order to allow the user to specify the notion of state validity, OMPL defines two abstract classes:
1.ompl::base::StateValidityChecker
2.ompl::base::MotionValidator
这些抽象类提供了许多属性,用户可以根据需要去配置ompl::base::SpaceInformation 从而实现State Validity Checking类对象。
These classes abstract away properties specific to the systems we are planning for. For instance, OMPL does not need to represent robot or obstacle geometry. The user can specify which implementations to use when configuring ompl::base::SpaceInformation. The instances of ompl::base::StateValidityChecker and ompl::base::MotionValidator need to be thread safe.
规划器可以通过StateValidityChecker::isValid() 来评价状态的有效性,如果用户没有去定义State Validity Checking 系统会默认一个 AllValidStateValidityChecker ,表示所有状态都是可用的,这也是一个类对象。
The ompl::base::StateValidityChecker class defines the ompl::base::StateValidityChecker::isValid() function, which allows planners to evaluate the validity of a state. If the user does not specify this class, an instance of ompl::base::AllValidStateValidityChecker is assumed. This will consider all states to be valid.
官方提供的一个代码片段
从这段代码中可以看出:StateValidityChecker 是为 SpaceInformation 服务的,也就是状态有效检测是用来检测状态空间的。用户要需要自己定义 检测的规则 ,这可以通过两种方式实现:
- 通过实现 继承自StateValidityChecker的类对象 。
- 通过直接实现 检测函数
自定义类对象依然要实现 检测函数
// define this class:
// 用户定义的有效性检测类继承自base::StateValidityChecker
class myStateValidityCheckerClass : public base::StateValidityChecker
{
public:
// 构造函数的实现需要 base::SpaceInformation 类对象
myStateValidityCheckerClass(const base::SpaceInformationPtr &si) :
base::StateValidityChecker(si)
{
}
// 用户还需要实现一个 isValid 函数
virtual bool isValid(const base::State *state) const
{
return ...;
}
};
// or this function:
// 或者定义一个 bool类型的状态检测函数,输入是 base::State
bool myStateValidityCheckerFunction(const base::State *state)
{
return ...;
}
// 不管那种情况,都需要 base::SpaceInformation 对象
base::SpaceInformationPtr si(space);
// either this call:
// 为 SpaceInformation 设置状态检测,要么设置类对象
si->setStateValidityChecker(std::make_shared<myStateValidityCheckerClass>(si));
// or this call:
// 要么设置 检测函数
si->setStateValidityChecker(myStateValidityCheckerFunction);
// 下面应该是公用部分
si->setStateValidityCheckingResolution(0.03); // 3%
si->setup();
另一个检测类对象是MotionValidator (运动有效性检测?),通过实现其内部的MotionValidator::checkMotion() 函数来 衡量两个状态之间的运动是否有效 ,默认情况下MotionValidator 是被 DiscreteMotionValidator 代替
The ompl::base::MotionValidator class defines ompl::base::MotionValidator::checkMotion() routines that evaluate the validity of motions between two specified states. By default, the implementation of this class is assumed to be ompl::base::DiscreteMotionValidator.
使用DiscreteMotionValidator 有什么好处呢?
- 可以使用StateValidityChecker 的函数而不用再次定义么?目前不理解
The advantage of ompl::base::DiscreteMotionValidator is that it can be implemented solely using functionality from ompl::base::StateValidityChecker.
使用DiscreteMotionValidator 有什么坏处呢?
- 缺点是运动被离散化为 resolution(分辨率?离散的程度?),状态的检测将基于 resolution 进行, resolution 太大,无效的状态点被跳过去了,没检测到;太低了,计算量大,效率低。
The disadvantage is that the motion is discretized to some resolution and states are checked for validity at that resolution. If the resolution at which the motions are checked for validity is too large, there may be invalid states along the motion that escape undetected. If the resolution is too small, there can be too many states to be checked along each motion, slowing down the planner significantly.
resolution 的计算是通过StateSpace::validSegmentCount() 进行的(由StateSpace提供),表明:一个运动应该被分成多少段(segments),才能满足状态有效性检测。(resolution的计算与状态检测有关,决定状态检测的有效程度么?根据前面的看好像是这样的)
The resolution at which motions are discretized is computed using ompl::base::StateSpace::validSegmentCount() : each state space provides the ability to compute how many segments the motion should be split into so that the number of states checked for validity is satisfactory.
用户如何定义 resolution 呢?或者说如何改变呢?
- 用户可以用 space’s maximum extent(空间的最大范围)的百分比来表示 resolution
- 百分比的设置可以通过SpaceInformation::setStateValidityCheckingResolution() 实现
- 也可以通过StateSpace::setLongestValidSegmentFraction() 实现
- 当然也可以为不同的子空间设置 resolution , 不过此时的状态空间对象为CompoundStateSpace ,并且MotionValidator 也要单独设置。(先知道有这么回事就可以了)
The user can define this resolution in terms of percentages of the space’s maximum extent (ompl::base::StateSpace::getMaximumExtent()) by calling ompl::base::SpaceInformation::setStateValidityCheckingResolution() or by calling ompl::base::StateSpace::setLongestValidSegmentFraction() for individual state spaces. Different resolutions can be used in subspaces, if using ompl::base::CompoundStateSpace. If continuous collision checking is available, it is recommended that a different implementation of ompl::base::MotionValidator is provided, one that does not rely on discretizing the motion at a specific resolution.
现在再回过头去看上面代码的resolution部分可以看出:状态有效性检测的的尺度是空间最大尺寸的3%,设置的太大的话很多状态就检测不到了,感觉resolution很像是检测有效性时,空间离散的程度
官方提供的第二片代码
MotionValidator 的实现与之前的类似,只不过此处不能用使用直接实现函数的方法进行了,当然这是教程,不一定全面。
// define this class:
// 定义 继承自base::MotionValidator的运动有效性检测类对象
class myMotionValidator : public base::MotionValidator
{
public:
// implement checkMotion()
// 同理需要用户实现 checkMotion() 方法
};
// 调用方法只能通过类对象的形式调用么?
base::SpaceInformationPtr si(space);
si->setMotionValidator(std::make_shared<myMotionValidator>(si));
si->setup();
