【OMPL.demo.1】二维点到点

改写代码地址

基于开学初用Windows下的vs2019的框架改了改,基本工程搭建过程见:vs2019+VREP 基本工程框架

借用vrep界面展示规划的路径,vrep主要是记录robot的轨迹,robot的位置由c++程序直接设置,vrep类的定义如下:

vrep.h

#pragma once
#include"extApi.h"
#include"simConst.h"
#include"extApiPlatform.h"
#include 
#include 
#include 


namespace vrepspace
{
	class vrep
	{
	public:
		void vrep_connect(const char* ip);
		void vrep_start();
		void vrep_stop();
		void vrep_setpose2d(int handle, float x, float y);
		void getobjectpos(int handle, float* pos);
		int client_id;
		int robot_handle;
		int goal_handle;
	};



}



vrep.c


#include "vrep.h"

namespace vrepspace
{
    
    using namespace std;
	void vrep::vrep_connect(const char* ip)
	{
        

        int Port = 19997;

        client_id = simxStart((simxChar*)ip, Port, 1, 1, 1000, 5);
        vrep_stop();
        extApi_sleepMs(100);
        if (client_id != -1)
        {
            cout << "V-rep connected.";
            simxGetObjectHandle(client_id, "robot", &robot_handle, simx_opmode_blocking);
            simxGetObjectHandle(client_id, "goal", &goal_handle, simx_opmode_blocking);

        }
        else
        {
            cout << "V-rep can't be connected.";
        }
	}
    void vrep::vrep_start()
    {
        simxStartSimulation(client_id, simx_opmode_oneshot);
        cout << "simulation started ...... " << endl;
        extApi_sleepMs(100);
    }
    void vrep::vrep_stop()
    {
        simxStopSimulation(client_id, simx_opmode_oneshot);
    }
    void vrep::vrep_setpose2d(int handle, float x, float y)
    {
        float position[3] = { x, y, 0 };
        simxSetObjectPosition(client_id, (simxInt)handle, -1, position,simx_opmode_oneshot);
        
    }
    void vrep::getobjectpos(int handle, float* pos)
    {
        simxGetObjectPosition(client_id, handle, -1, pos, simx_opmode_blocking);
        extApi_sleepMs(50);
    }
}

路径规划部分直接copy的ompl官网的 这个demo

里面的main函数当然要挪到自己的main.c里面去,另外Plane2DEnvironment类里面新增一个drawPath函数,在main.h里面定义,作用是在vrep里面移动位置
Plane2DEnvironment.h如下,路径规划只有一个头文件就够了

#pragma once
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include 
#include 




namespace ob = ompl::base;
namespace og = ompl::geometric;

class Plane2DEnvironment
{
public:
    Plane2DEnvironment(const char* ppm_file, bool use_deterministic_sampling = false)
    {
        bool ok = false;
        useDeterministicSampling_ = use_deterministic_sampling;
        try
        {
            ppm_.loadFile(ppm_file);
            ok = true;
        }
        catch (ompl::Exception& ex)
        {
            OMPL_ERROR("Unable to load %s.\n%s", ppm_file, ex.what());
        }
        if (ok)
        {
            auto space(std::make_shared<ob::RealVectorStateSpace>());
            space->addDimension(0.0, ppm_.getWidth());//x轴长度即图片宽像素数
            space->addDimension(0.0, ppm_.getHeight());//y轴长度即图片高像素数
            maxWidth_ = ppm_.getWidth() - 1;//可行路径不能在边界上?
            maxHeight_ = ppm_.getHeight() - 1;
            ss_ = std::make_shared<og::SimpleSetup>(space);//初始化采样空间即构型空间?状态空间

            // set state validity checking for this space
            ss_->setStateValidityChecker([this](const ob::State* state) { return isStateValid(state); });
            space->setup();
            ss_->getSpaceInformation()->setStateValidityCheckingResolution(1.0 / space->getMaximumExtent());

            // set the deterministic sampler
            // 2D space, no need to specify bases specifically
            if (useDeterministicSampling_)
            {
                // PRMstar can use the deterministic sampling
                ss_->setPlanner(std::make_shared<og::PRMstar>(ss_->getSpaceInformation()));//渐进最优的概率路线图*算法
                space->setStateSamplerAllocator(std::bind(&Plane2DEnvironment::allocateHaltonStateSamplerRealVector,
                    this, std::placeholders::_1, 2,
                    std::vector<unsigned int>{2, 3}));
            }
        }
    }

    bool plan(unsigned int start_row, unsigned int start_col, unsigned int goal_row, unsigned int goal_col)
    {
        if (!ss_)
            return false;
        ob::ScopedState<> start(ss_->getStateSpace());
        start[0] = start_row;
        start[1] = start_col;
        ob::ScopedState<> goal(ss_->getStateSpace());
        goal[0] = goal_row;
        goal[1] = goal_col;
        ss_->setStartAndGoalStates(start, goal);
        // generate a few solutions; all will be added to the goal;
        for (int i = 0; i < 10; ++i)
        {
            if (ss_->getPlanner())
                ss_->getPlanner()->clear();
            ss_->solve();
        }
        const std::size_t ns = ss_->getProblemDefinition()->getSolutionCount();
        OMPL_INFORM("Found %d solutions", (int)ns);
        if (ss_->haveSolutionPath())
        {
            if (!useDeterministicSampling_)
                ss_->simplifySolution();

            og::PathGeometric& p = ss_->getSolutionPath();
            if (!useDeterministicSampling_)
            {
                ss_->getPathSimplifier()->simplifyMax(p);
                ss_->getPathSimplifier()->smoothBSpline(p);
            }

            return true;
        }

        return false;
    }

    void drawPath();

    void recordSolution()
    {
        if (!ss_ || !ss_->haveSolutionPath())
            return;
        og::PathGeometric& p = ss_->getSolutionPath();
        p.interpolate();
        for (std::size_t i = 0; i < p.getStateCount(); ++i)
        {
            const int w = std::min(maxWidth_, (int)p.getState(i)->as<ob::RealVectorStateSpace::StateType>()->values[0]);
            const int h =
                std::min(maxHeight_, (int)p.getState(i)->as<ob::RealVectorStateSpace::StateType>()->values[1]);
                //得到路径上的点的坐标
            ompl::PPM::Color& c = ppm_.getPixel(h, w);
            c.red = 255;
            c.green = 0;
            c.blue = 0;
            //在该坐标处画红点,设置vrep里面的robot位置原理与此一致
        }
    }

    void save(const char* filename)
    {
        if (!ss_)
            return;
        ppm_.saveFile(filename);
    }

private:
    bool isStateValid(const ob::State* state) const
    {
        const int w = std::min((int)state->as<ob::RealVectorStateSpace::StateType>()->values[0], maxWidth_);
        const int h = std::min((int)state->as<ob::RealVectorStateSpace::StateType>()->values[1], maxHeight_);

        const ompl::PPM::Color& c = ppm_.getPixel(h, w);
        return c.red > 127 && c.green > 127 && c.blue > 127;
    }

    ob::StateSamplerPtr allocateHaltonStateSamplerRealVector(const ompl::base::StateSpace* space, unsigned int dim,
        std::vector<unsigned int> bases = {})
    {
        // specify which deterministic sequence to use, here: HaltonSequence
        // optionally we can specify the bases used for generation (otherwise first dim prime numbers are used)
        if (bases.size() != 0)
            return std::make_shared<ompl::base::RealVectorDeterministicStateSampler>(
                space, std::make_shared<ompl::base::HaltonSequence>(bases.size(), bases));
        else
            return std::make_shared<ompl::base::RealVectorDeterministicStateSampler>(
                space, std::make_shared<ompl::base::HaltonSequence>(dim));
    }

    og::SimpleSetupPtr ss_;
    int maxWidth_;
    int maxHeight_;
    ompl::PPM ppm_;
    bool useDeterministicSampling_;
};

main.h 里面定义vrep里面robot移动的过程

#pragma once
#include "vrep.h"
#include "2dpointplanningdemo.h"

using namespace std;
namespace vp = vrepspace;
vp::vrep m_vrep;

void Plane2DEnvironment::drawPath()
{
	float x, y;
	if (ss_->haveSolutionPath())
	{
		if (!useDeterministicSampling_)
			ss_->simplifySolution();

		og::PathGeometric& p = ss_->getSolutionPath();
		if (!useDeterministicSampling_)
		{
			ss_->getPathSimplifier()->simplifyMax(p);
			ss_->getPathSimplifier()->smoothBSpline(p);
		}

		size_t length = p.getStateCount();//得到路径节点数
		//p.interpolate(20); // 已经样条曲线平滑过了就不插补了
		cout << "path length is : " << endl << length << endl;
	
		for (int i = 0; i < length; i++)
		{
			x = (p.getState(i)->as<ob::RealVectorStateSpace::StateType>()->values[0])/100; //注意像素距离转换到vrep里面的实际距离,差100倍
			y = (p.getState(i)->as<ob::RealVectorStateSpace::StateType>()->values[1])/100;
			cout << "path point : " << i << ".  x : " << x << ".y : " << y << endl;
			m_vrep.vrep_setpose2d(m_vrep.robot_handle, x, y);
			extApi_sleepMs(10);
		}

	}

}

main.c 主函数

/*********************************************************************
 * @ Harbin Institute of Technology
 *
 * @author : HI_FORREST
 * 
 * @date : 2021.12.27
 * 
 *
 *********************************************************************/

#include "main.h"



int main()
{
    m_vrep.vrep_connect("127.0.0.1"); // 连接到本机的vrep程序
    m_vrep.vrep_start(); //开始仿真
    
    std::cout << "OMPL version: " << OMPL_VERSION << std::endl;

    boost::filesystem::path path("E:/c++program/ompl/resources/resources/"); // ompl安装文件夹里复制出来的,D:\vcpkg-master\buildtrees\ompl\src\1.5.1-f5b2356dec.clean\tests\resources 。用vcpkg安装的ompl,该文件夹在这里。
    bool useDeterministicSampling = true;
    Plane2DEnvironment env((path/"ppm/floor.ppm").string().c_str(), useDeterministicSampling);

    float pos[3] = { 0,0,0 };
    float target[3] = { 0,0,0 };

    m_vrep.getobjectpos(m_vrep.robot_handle, pos);
    m_vrep.getobjectpos(m_vrep.goal_handle, target);//根据vrep里面的当做起点终点的dummy初始化路径规划的起终点。
    int x = (int)(pos[0] * 100);
    int y = (int)(pos[1] * 100);
    int tx = (int)(target[0] * 100);
    int ty = (int)(target[1] * 100);// 该demo以图像像素数为距离进行规划,图片尺寸1895×1568,vrep里面的实际尺寸设为18.95米×15.68米。ppm图片可以用WPS打开!之前专门下了一个xnview mp 软件也可以,但是不如WPS方便。
    cout << "start position : x : " << x << " . y : " << y << endl;
    cout << "goal position : tx : " << tx << " . ty : " << ty << endl;

    if (env.plan(x, y, tx, ty)) //如果路径规划成功执行以下内容
    {
        env.recordSolution();
        
        cout << "saving path as pictur ... " << endl;
        env.save("result_demo.ppm");
        cout << "showing path in vrep ... " << endl;
        env.drawPath(); // 看main.h的定义
    }

    return 0;
}

ppm地图以左上角为原点,向下为y轴正方形,向右为x轴正方形,因此vrep里面的地图绕x轴转了180°,同时向右上方移动半张图,使原点位于地图左下角。
实际路径在ppm和vrep中如图:
【OMPL.demo.1】二维点到点_第1张图片
【OMPL.demo.1】二维点到点_第2张图片

十次规划均有解
【OMPL.demo.1】二维点到点_第3张图片

你可能感兴趣的:(学习笔记,VREP,motion,planning,c++,动态规划)