速度规划:s形曲线应用(变速 停车)opencv c++显示(3)

理论篇

先看该篇,这里沿用了里面的变量。

应用推导篇

分为变速和停车两部分(字迹潦草,可结合代码看)
请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述

代码篇

变速函数入口:

velocityPlanner vp;
vp.SetParameters(0, 1);

停车函数入口:

ParkingVelocityPlanner vp;
vp.SetDistance(1, 0.4);

头文件:SpeedPlan.h

#ifndef SPEEDPLAN_H
#define SPEEDPLAN_H#include <opencv2/opencv.hpp> // 包含OpenCV头文件
#include <chrono>
#include <thread>#define _CRT_SECURE_NO_WARNINGS
#define a_max  1.0
#define J_s  0.5
#define v_max  4.0class VelocityPlanner
{
public:VelocityPlanner();~VelocityPlanner();virtual double GetSpeed(double t);virtual void SetParameters(double robot, double target);//private:double time0;double lasttime;double T0, T1, T2;double t0, t1, t2, t3;double v0, v1, v2, v3;double targetspeed0;double robotspeed0;double j, J;
};VelocityPlanner::VelocityPlanner() {J = J_s;
}
VelocityPlanner::~VelocityPlanner() {
}class ParkingVelocityPlanner :public VelocityPlanner
{
public:ParkingVelocityPlanner();~ParkingVelocityPlanner(); double GetSpeed(double t) override ;void SetDistance(double robot, double distance);void SetJ(double j);double S0, S1, S2, S3;double s_min, s_s;double distance0;private:double CalculateFitJ(double robot, double distance);};ParkingVelocityPlanner::ParkingVelocityPlanner()
{
}ParkingVelocityPlanner::~ParkingVelocityPlanner()
{
}#endif

主文件SpeedPlan.cpp

#include <iostream>
#include "SpeedPlan.h"using namespace std;void VelocityPlanner::SetParameters(double robot, double target) {robotspeed0 = robot;targetspeed0 = target;double errorspeed = target - robot;double T1_max = abs(a_max / J);bool trilogy = abs(errorspeed) > J * T1_max * T1_max ? true : false;//三段式if (trilogy) {//计算时间T1 T2T1 = T1_max;T2 = abs(errorspeed) / a_max - T1;}//两段式else {T1 = pow(abs(errorspeed) / J, 0.5);T2 = 0;}T0 = 0;t0 = T0;t1 = t0 + T1;t2 = t1 + T2;t3 = t2 + T1;if (errorspeed < 0) {j = -J;}else {j = J;}auto currentTime = std::chrono::system_clock::now();auto currentTime_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime);//毫秒auto valueMS = currentTime_ms.time_since_epoch().count();time0 = valueMS * 0.001;lasttime = time0;//std::cout << "Milliseconds: " << "    " << typeid(valueMS).name() << "  " << valueMS << std::endl;//std::cout << "errortime: " << "    " << typeid(time0).name() << "  " << time0 << std::endl;v0 = robot;v1 = v0 + j * T1 * T1 * 0.5;v2 = v1 + j * T1 * T2;//v3 = target;v3 = v2 + j * T1 * T1 * 0.5;
}double VelocityPlanner::GetSpeed(double t) {double period = t - time0;double temp = 0.0;if (period < t0) {return v0;}else if (period < t1) {temp = period - t0;return v0 + j * temp * temp * 0.5;}else if (period < t2) {temp = period - t1;return v1 + j * T1 * temp;}else if (period < t3) {temp = period - t2;return v2 + j * T1 * temp - j * temp * temp * 0.5;}else {return v3;}}void ParkingVelocityPlanner::SetDistance(double robot,double distance)
{distance0 = distance;//急刹段内T2 = robot / a_max;s_min = 0.5 * a_max * T2 * T2;if (distance < s_min) {cout << "急刹,速度规划失效!" << endl;return;}//s形规划SetParameters(robot, 0);S1 = v0 * T1 + j * pow(T1, 3)/6;S2 = v1 * T2 + 0.5 * j * T1 * T2 * T2;S3 = v2 * T1 + j * pow(T1, 3) / 3;s_s = S1 + S2 + S3;T0 = (distance - s_s) / robot;t0 = T0;t1 = t0 + T1;t2 = t1 + T2;t3 = t2 + T1;if (distance >= s_s) {cout << "s形速度规划!" << endl;cout << "j: " << j << endl;cout << "a_max  a: " << a_max << " " << j * T1 << endl;cout << "s_s: " <<s_s<<" "<<distance << endl;cout << "t0-3: " <<t3<<" "<<t0<<" " << t3 - t0 << endl;return;}//拟合规划double j_adaptive = CalculateFitJ(robot, distance);SetJ(j_adaptive);SetParameters(robot, 0);cout << "拟合速度规划!" << endl;cout << "j: " << j << endl;cout << "s_s: " << distance << endl;cout << "T0-3: " << t3-t0<< endl;cout << "a_max  a: " << a_max << " " << j * T1 << endl;}double ParkingVelocityPlanner::CalculateFitJ(double robot, double distance) {//两段式T2 = 0;T1 = distance / robot;double j_temp = robot / T1 / T1;if (j_temp * T1 <= a_max) {return j_temp;}//三段式T1 = 2 * distance / robot - robot / a_max;T2 = robot / a_max - T1;j_temp = a_max / T2;return j_temp;
}void ParkingVelocityPlanner::SetJ(double j) {J = j;
}double ParkingVelocityPlanner::GetSpeed(double t) {//急刹if (distance0 < s_min) {return 0;}//拟合规划else{double period = t - time0;double temp = 0.0;if (period < t0) {return v0;}else if (period < t1) {temp = period - t0;return v0 + j * temp * temp * 0.5;}else if (period < t2) {temp = period - t1;return v1 + j * T1 * temp;}else if (period < t3) {temp = period - t2;return v2 + j * T1 * temp - j * temp * temp * 0.5;}else {return v3;}}
}int main() {//VelocityPlanner vp;//vp.SetParameters(0, 1);//cout << "时间:" << vp.t3 - vp.t0 << endl;ParkingVelocityPlanner vp;vp.SetDistance(1, 0.4);auto currentTime = std::chrono::system_clock::now();auto currentTime_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(currentTime);//毫秒auto valueMS = currentTime_ms.time_since_epoch().count();double time = valueMS * 0.001;bool flag = false;double last_vt = 0, last_t = 0;cv::Mat canvas(600, 600, CV_8UC3, cv::Scalar(255, 255, 255)); // 创建一个300x300像素的画布cv::line(canvas, cv::Point(0, 0), cv::Point(0, 600), cv::Scalar(255, 0, 0), 4);//y周  (x,y)cv::line(canvas, cv::Point(0, 0), cv::Point(600, 0), cv::Scalar(255, 0, 0), 4);//x周  (x,y)double tf = vp.t3 * 1.25;// 总时间double kx = 500 / tf, ky = 300 / max(vp.v3, vp.v0);double period;double cyclicality = tf / 100;for (double t = time; t <= time + tf; t += cyclicality) {//double s_t = PathCurve(t);period = t - time;double v_t = vp.GetSpeed(t);if (!flag) {cv::circle(canvas, cv::Point(period * kx, v_t * ky), 2, cv::Scalar(0, 0, 255), -1);}else {cv::circle(canvas, cv::Point(period * kx, v_t * ky), 2, cv::Scalar(0, 0, 255), -1);cv::line(canvas, cv::Point(last_t * kx, last_vt * ky), cv::Point(period * kx, v_t * ky), cv::Scalar(255, 0, 0), 1);//y周  (x,y)}last_vt = v_t;last_t = period;std::cout << period << "时刻速度:" << "    " << v_t << std::endl;}cv::line(canvas, cv::Point(vp.t0 * kx, vp.v0 * ky), cv::Point(vp.t0 * kx, 0), cv::Scalar(100, 0, 0), 1);//y周  (x,y)cv::circle(canvas, cv::Point(vp.t0 * kx, vp.v0 * ky), 5, cv::Scalar(0, 0, 255), -1);cv::line(canvas, cv::Point(vp.t1 * kx, vp.v1 * ky), cv::Point(vp.t1 * kx, 0), cv::Scalar(100, 0, 0), 1);//y周  (x,y)cv::circle(canvas, cv::Point(vp.t1 * kx, vp.v1 * ky), 5, cv::Scalar(0, 0, 255), -1);//cv::putText(canvas, "(" + std::to_string(vp.t1) + "," + std::to_string(vp.v1) + ")", cv::Point(vp.t1 * kx, vp.v1 * ky), cv::FONT_HERSHEY_SIMPLEX, 1.5, cv::Scalar(0, 255, 0), 2);cv::line(canvas, cv::Point(vp.t2 * kx, vp.v2 * ky), cv::Point(vp.t2 * kx, 0), cv::Scalar(100, 0, 0), 1);//y周  (x,y)cv::circle(canvas, cv::Point(vp.t2 * kx, vp.v2 * ky), 5, cv::Scalar(0, 0, 255), -1);//cv::putText(canvas, "(" + std::to_string(vp.t2) + "," + std::to_string(vp.v2) + ")", cv::Point(vp.t2 * kx, vp.v2 * ky), cv::FONT_HERSHEY_SIMPLEX, 1.5, cv::Scalar(0, 255, 0), 2);cv::line(canvas, cv::Point(vp.t3 * kx, vp.v3 * ky), cv::Point(vp.t3 * kx, 0), cv::Scalar(100, 0, 0), 1);//y周  (x,y)cv::circle(canvas, cv::Point(vp.t3 * kx, vp.v3 * ky), 5, cv::Scalar(0, 0, 255), -1);//cv::putText(canvas, "(" + std::to_string(vp.t3) + "," + std::to_string(vp.v3) + ")", cv::Point(vp.t3 * kx, vp.v3 * ky), cv::FONT_HERSHEY_SIMPLEX, 1.5, cv::Scalar(0, 255, 0), 2);// 创建镜像图像矩阵  cv::Mat mirror_img;cv::flip(canvas, mirror_img, 0);  // 水平镜像,flipCode=1  cv::imshow("Image", mirror_img);cv::waitKey(); // 等待10秒return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/457811.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新版MQL语言程序设计:键盘快捷键交易的设计与实现

文章目录 一、什么是快捷键交易二、使用快捷键交易的好处三、键盘快捷键交易程序设计思路四、键盘快捷键交易程序具体实现1.界面设计2.键盘交易事件机制的代码实现 一、什么是快捷键交易 操盘中按快捷键交易是指在股票或期货交易中&#xff0c;通过使用快捷键来进行交易操作的…

linux centos安装neofetch

简介 neofetch是一个命令行工具&#xff0c;可以用来显示系统的基本信息和硬件配置。它支持多种操作系统&#xff0c;包括Linux、macOS和Windows等。 安装 增加yum源 curl -o /etc/yum.repos.d/konimex-neofetch-epel-7.repo https://copr.fedorainfracloud.org/coprs/konime…

代码随想录 Leetcode46. 全排列

题目&#xff1a; 代码&#xff08;首刷自解 2024年2月6日&#xff09;&#xff1a; class Solution { private:vector<vector<int>> res;vector<int> path; public:void backtracking(vector<int>& nums, int depth, vector<bool>& us…

网络基础(三)

网络层与数据链路层 1.网络层2.IP2.1 基本概念2.2 协议头格式2.3 网段划分2.4 特殊的IP地址2.5IP地址的数量限制2.6 私有IP地址和公网IP地址2.7 路由 3.数据链路层4.以太网&#xff08;MAC帧协议&#xff09;4.1 认识以太网4.2 以太网帧格式4.3 认识MAC地址4.4 对比理解MAC地址…

node cool-admin 后端宝塔面板看代码日志

1.需求 我在处理回调问题的时候 就是找不到问题&#xff0c;因为不像本地的代码 控制台能够直接打印出来问题&#xff0c;你是放在线上了 所以那个日志不好打印 我看网上都说是 直接用一个loger.js 打印 日志 放到代码文件里 这种方法也许有用 但是对我这框架cool来说 试了没有…

【排序】插入排序、冒泡排序、选择排序

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&a…

【华为云】容灾方案两地三中心实践理论

应用上云之后&#xff0c;如何进行数据可靠性以及业务连续性的保障是非常关键的&#xff0c;通过华为云云上两地三中心方案了解相关方案认证地址&#xff1a;https://connect.huaweicloud.com/courses/learn/course-v1:HuaweiXCBUCNXI057Self-paced/about当前内容为灾备常见理论…

2024-02-06 TCP/UDP work

1. 画出TCP三次握手和四次挥手的示意图&#xff0c;并且总结TCP和UDP的区别 三次握手&#xff1a; 4次挥手&#xff1a; tcp/udp区别 TCP 1. 稳定&#xff0c;提供面向连接的&#xff0c;可靠的数据传输服务 2. 传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、…

LabVIEW高精度微小电容测量

LabVIEW高精度微小电容测量 在电子工程和科研领域&#xff0c;精确测量微小电容值是一项有一定要求的任务&#xff0c;尤其在涉及到高精度和低成本时。设计了一种基于LabVIEW高精度微小电容测量系统&#xff0c;旨在提供一个既经济又高效的解决方案。 该系统的核心在于使用FD…

Django框架开发学习实录

本文将记录一下我在Django框架开发学习过程中的一些步骤&#xff08;坑&#xff09;&#xff0c;方便查阅。 安装与框架介绍 Django安装与项目创建 安装Django 首先需要安装Django的包&#xff0c;直接pip install即可&#xff0c;如果出现超时&#xff0c;可以换源。 pip…

记录 | linux下切换python版本

查看系统中存在的 python 版本 ls /usr/bin/python* 查看系统默认的 python 版本 python --version

【Linux系统学习】2.Linux基础命令

Linux基础命令 Linux的目录结构 Linux命令入门 目录切换相关命令(cd/pwd) 相对路径、绝对路径和特殊路径符 创建目录命令(mkdir) 文件操作命令part1(touch、cat、more&#xff09; 文件操作命令part2(cp、mv、rm&#xff09; 查找命令(which、find&#xff09; grep、wc和管道符…