├── LICENSE
├── README.md
└── motionPlan
├── MotionPlan.pro
├── MotionPlan.pro.user
├── autorun.cpp
├── autorun.h
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
├── motionplan.cpp
├── motionplan.h
├── mychart.cpp
├── mychart.h
├── mychart.ui
└── pic.png
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 WangZhangMing
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 | 编写了一种静态前瞻式7段S型速度规划,实现边计算边运动,并在运动过程中可平稳减速暂停以及启动。
3 | 目前算法在运动过程中不支持修改位移、速度、加速度等条件,只是是在这些条件确定下实现的前瞻速度规划。
4 | ## 有暂停情况
5 | 
6 |
7 | ## 无暂停情况
8 | 
9 |
--------------------------------------------------------------------------------
/motionPlan/MotionPlan.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2021-09-15T17:02:59
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += core gui charts
8 |
9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10 |
11 | TARGET = motionPlan
12 | TEMPLATE = app
13 |
14 | # The following define makes your compiler emit warnings if you use
15 | # any feature of Qt which as been marked as deprecated (the exact warnings
16 | # depend on your compiler). Please consult the documentation of the
17 | # deprecated API in order to know how to port your code away from it.
18 |
19 | DEFINES += QT_DEPRECATED_WARNINGS motionDebug
20 |
21 | # You can also make your code fail to compile if you use deprecated APIs.
22 | # In order to do so, uncomment the following line.
23 | # You can also select to disable deprecated APIs only up to a certain version of Qt.
24 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
25 |
26 |
27 | SOURCES += main.cpp\
28 | mainwindow.cpp \
29 | autorun.cpp \
30 | motionplan.cpp \
31 | mychart.cpp
32 |
33 | HEADERS += mainwindow.h \
34 | autorun.h \
35 | motionplan.h \
36 | mychart.h
37 |
38 | FORMS += mainwindow.ui \
39 | mychart.ui
40 |
41 |
--------------------------------------------------------------------------------
/motionPlan/MotionPlan.pro.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | EnvironmentId
7 | {68c40faf-792f-418f-91e3-8199f7a41a75}
8 |
9 |
10 | ProjectExplorer.Project.ActiveTarget
11 | 0
12 |
13 |
14 | ProjectExplorer.Project.EditorSettings
15 |
16 | true
17 | false
18 | true
19 |
20 | Cpp
21 |
22 | CppGlobal
23 |
24 |
25 |
26 | QmlJS
27 |
28 | QmlJSGlobal
29 |
30 |
31 | 2
32 | UTF-8
33 | false
34 | 4
35 | false
36 | 80
37 | true
38 | true
39 | 1
40 | true
41 | false
42 | 0
43 | true
44 | true
45 | 0
46 | 8
47 | true
48 | 1
49 | true
50 | true
51 | true
52 | false
53 |
54 |
55 |
56 | ProjectExplorer.Project.PluginSettings
57 |
58 |
59 | true
60 |
61 |
62 |
63 | ProjectExplorer.Project.Target.0
64 |
65 | Desktop Qt 5.12.2 GCC 64bit
66 | Desktop Qt 5.12.2 GCC 64bit
67 | qt.qt5.5122.gcc_64_kit
68 | 0
69 | 0
70 | 0
71 |
72 | /home/linux/work/personal/motionPlan/bin
73 |
74 |
75 | true
76 | qmake
77 |
78 | QtProjectManager.QMakeBuildStep
79 | true
80 |
81 | false
82 | false
83 | false
84 |
85 |
86 | true
87 | Make
88 |
89 | Qt4ProjectManager.MakeStep
90 |
91 | false
92 |
93 |
94 | false
95 |
96 | 2
97 | Build
98 |
99 | ProjectExplorer.BuildSteps.Build
100 |
101 |
102 |
103 | true
104 | Make
105 |
106 | Qt4ProjectManager.MakeStep
107 |
108 | true
109 | clean
110 |
111 | false
112 |
113 | 1
114 | Clean
115 |
116 | ProjectExplorer.BuildSteps.Clean
117 |
118 | 2
119 | false
120 |
121 | Debug
122 | Debug
123 | Qt4ProjectManager.Qt4BuildConfiguration
124 | 2
125 | true
126 |
127 |
128 | /home/linux/work/personal/motionPlan/bin
129 |
130 |
131 | true
132 | qmake
133 |
134 | QtProjectManager.QMakeBuildStep
135 | false
136 |
137 | false
138 | false
139 | true
140 |
141 |
142 | true
143 | Make
144 |
145 | Qt4ProjectManager.MakeStep
146 |
147 | false
148 |
149 |
150 | false
151 |
152 | 2
153 | Build
154 |
155 | ProjectExplorer.BuildSteps.Build
156 |
157 |
158 |
159 | true
160 | Make
161 |
162 | Qt4ProjectManager.MakeStep
163 |
164 | true
165 | clean
166 |
167 | false
168 |
169 | 1
170 | Clean
171 |
172 | ProjectExplorer.BuildSteps.Clean
173 |
174 | 2
175 | false
176 |
177 | Release
178 | Release
179 | Qt4ProjectManager.Qt4BuildConfiguration
180 | 0
181 | true
182 |
183 |
184 | /home/linux/work/personal/motionPlan/bin
185 |
186 |
187 | true
188 | qmake
189 |
190 | QtProjectManager.QMakeBuildStep
191 | true
192 |
193 | false
194 | true
195 | true
196 |
197 |
198 | true
199 | Make
200 |
201 | Qt4ProjectManager.MakeStep
202 |
203 | false
204 |
205 |
206 | false
207 |
208 | 2
209 | Build
210 |
211 | ProjectExplorer.BuildSteps.Build
212 |
213 |
214 |
215 | true
216 | Make
217 |
218 | Qt4ProjectManager.MakeStep
219 |
220 | true
221 | clean
222 |
223 | false
224 |
225 | 1
226 | Clean
227 |
228 | ProjectExplorer.BuildSteps.Clean
229 |
230 | 2
231 | false
232 |
233 | Profile
234 | Profile
235 | Qt4ProjectManager.Qt4BuildConfiguration
236 | 0
237 | true
238 |
239 | 3
240 |
241 |
242 | 0
243 | 部署
244 |
245 | ProjectExplorer.BuildSteps.Deploy
246 |
247 | 1
248 | Deploy Configuration
249 |
250 | ProjectExplorer.DefaultDeployConfiguration
251 |
252 | 1
253 |
254 |
255 | false
256 | false
257 | 1000
258 |
259 | true
260 |
261 | false
262 | false
263 | false
264 | false
265 | true
266 | 0.01
267 | 10
268 | true
269 | 1
270 | 25
271 |
272 | 1
273 | true
274 | false
275 | true
276 | valgrind
277 |
278 | 0
279 | 1
280 | 2
281 | 3
282 | 4
283 | 5
284 | 6
285 | 7
286 | 8
287 | 9
288 | 10
289 | 11
290 | 12
291 | 13
292 | 14
293 |
294 | 2
295 |
296 | MotionPlan
297 |
298 | Qt4ProjectManager.Qt4RunConfiguration:/home/linux/work/personal/motionPlan/MotionPlan.pro
299 | MotionPlan.pro
300 |
301 | 3768
302 | false
303 | true
304 | true
305 | false
306 | false
307 | true
308 |
309 | /home/linux/work/personal/motionPlan/bin
310 |
311 | 1
312 |
313 |
314 |
315 | ProjectExplorer.Project.TargetCount
316 | 1
317 |
318 |
319 | ProjectExplorer.Project.Updater.FileVersion
320 | 20
321 |
322 |
323 | Version
324 | 20
325 |
326 |
327 |
--------------------------------------------------------------------------------
/motionPlan/autorun.cpp:
--------------------------------------------------------------------------------
1 | #include "autorun.h"
2 |
3 | autoRun::autoRun():motion(new motionPlan)
4 | {
5 | #ifdef motionDebug
6 | connect(motion,&motionPlan::sendMsg,this,&autoRun::sendMotionPlanMsg);
7 | #endif
8 | }
9 |
10 | autoRun::~autoRun()
11 | {
12 | delete motion;
13 | }
14 |
15 | void autoRun::run(){
16 | static double path_moved=0;
17 | static double proportion=0,dis=0,vs=0,acc=0,time=0;
18 | static bool pause=false;
19 | path_moved=0;
20 | motion->ini_path_data(pathInit);
21 | while(motion->pathBusy()){
22 | if(forceQuit) break;
23 | pause=path_pause;
24 | if(motion->performPath(pause)){
25 | motion->get_move_msg(proportion,dis,vs,acc,time);
26 | emit send_data(dis-path_moved,dis,vs,acc,time);
27 | path_moved=dis;
28 | }
29 | }
30 | forceQuit=false;
31 | path_pause=false;
32 | emit send_cal_done_sig();
33 | }
34 |
--------------------------------------------------------------------------------
/motionPlan/autorun.h:
--------------------------------------------------------------------------------
1 | #ifndef AUTORUN_H
2 | #define AUTORUN_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include //使用了QTime函数
13 | #include //qsrand和qrand这两个函数在这里面
14 | #include
15 | #include"motionplan.h"
16 |
17 | class autoRun : public QThread
18 | {
19 | Q_OBJECT
20 | public:
21 | autoRun();
22 | ~autoRun();
23 | pathInitData pathInit;
24 | bool path_pause=false;
25 | QString pathMode;
26 |
27 | bool forceQuit=false;
28 |
29 | protected:
30 | void run();
31 |
32 | private:
33 | motionPlan *motion=nullptr;
34 |
35 | signals:
36 | void sendMotionPlanMsg(const QString &);
37 | void send_data(double,double,double,double,double);
38 | void send_cal_done_sig();
39 |
40 | };
41 | #endif // AUTORUN_H
42 |
--------------------------------------------------------------------------------
/motionPlan/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.showMaximized();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/motionPlan/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "ui_mainwindow.h"
3 |
4 | MainWindow::MainWindow(QWidget *parent) :
5 | QMainWindow(parent),
6 | ui(new Ui::MainWindow),
7 | disChart(new myChart(0,this)),
8 | spdChart(new myChart(1,this)),
9 | accChart(new myChart(2,this)),
10 | dataTableWidget(new QTableWidget(this)),
11 | autorun(new autoRun())
12 | {
13 | ui->setupUi(this);
14 | setWindowTitle("静态前瞻式7段S型速度规划");
15 | #ifdef motionDebug
16 | connect(autorun,&autoRun::sendMotionPlanMsg,this,&MainWindow::recMotionPlanMsg);
17 | #endif
18 | connect(autorun,&autoRun::send_data,this,&MainWindow::rec_data,Qt::BlockingQueuedConnection);
19 | connect(this,&MainWindow::send_data,disChart,&myChart::rec_data);//,Qt::BlockingQueuedConnection
20 | connect(this,&MainWindow::send_data,spdChart,&myChart::rec_data);
21 | connect(this,&MainWindow::send_data,accChart,&myChart::rec_data);
22 | connect(autorun,&autoRun::send_cal_done_sig,this,&MainWindow::rec_cal_done_sig);
23 |
24 | ui->lineEdit_V0->setValidator(new QDoubleValidator(this));
25 | ui->lineEdit_Ve->setValidator(new QDoubleValidator(this));
26 | ui->lineEdit_Jerk->setValidator(new QDoubleValidator(this));
27 | ui->lineEdit_VMax->setValidator(new QDoubleValidator(this));
28 | ui->lineEdit_distance->setValidator(new QDoubleValidator(this));
29 | ui->lineEdit_acc->setValidator(new QDoubleValidator(this));
30 | ui->lineEdit_planSingleTime->setValidator(new QDoubleValidator(this));
31 |
32 | ui->mdiArea->setMouseTracking(true);
33 | ui->mdiArea->setContextMenuPolicy(Qt::CustomContextMenu);
34 | ui->mdiArea->addSubWindow(dataTableWidget,Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
35 | ui->mdiArea->addSubWindow(accChart,Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
36 | ui->mdiArea->addSubWindow(spdChart,Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
37 | ui->mdiArea->addSubWindow(disChart,Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
38 | ui->mdiArea->tileSubWindows();
39 | ui->mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation,true);
40 |
41 | ui->dockWidget->setWindowTitle(tr("参数设置"));
42 | dataTableWidget->setWindowTitle("规划数据");
43 | initTableWidget();
44 | }
45 |
46 | MainWindow::~MainWindow()
47 | {
48 | delete ui;
49 | if(autorun!=nullptr){
50 | if(autorun->isRunning()){
51 | autorun->forceQuit=true;
52 | autorun->quit();
53 | autorun->wait();
54 | }
55 | delete autorun;
56 | }
57 | delete disChart;
58 | delete spdChart;
59 | delete accChart;
60 | delete dataTableWidget;
61 | }
62 |
63 | void MainWindow::initTableWidget()
64 | {
65 | dataTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
66 | dataTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
67 | QTableWidgetItem *headerItem;
68 | QStringList widgethead;
69 | widgethead<<"总时间"<<"总位移"<<"当前时刻位移"<<"当前时刻速度"<<"当前时刻加速度";
70 | dataTableWidget->setHorizontalHeaderLabels(widgethead);
71 | dataTableWidget->setColumnCount(widgethead.size());
72 | for(int i=0;icolumnCount();i++)
73 | {
74 | headerItem=new QTableWidgetItem(widgethead.at(i));
75 | dataTableWidget->setHorizontalHeaderItem(i,headerItem);
76 | }
77 | }
78 |
79 | void MainWindow::rec_data(double realData, double allData, double vs, double acc,double time)
80 | {
81 | static int row=0;
82 | dataTableWidget->setRowCount(dataTableWidget->rowCount()+1);
83 | row=dataTableWidget->rowCount()-1;
84 | dataTableWidget->setItem(row,0,new QTableWidgetItem(QString::number(time)));
85 | dataTableWidget->item (row,0)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
86 | dataTableWidget->setItem(row,1,new QTableWidgetItem(QString::number(allData,'f',6)));
87 | dataTableWidget->item (row,1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
88 | dataTableWidget->setItem(row,2,new QTableWidgetItem(QString::number(realData)));
89 | dataTableWidget->item (row,2)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
90 | dataTableWidget->setItem(row,3,new QTableWidgetItem(QString::number(vs)));
91 | dataTableWidget->item (row,3)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
92 | dataTableWidget->setItem(row,4,new QTableWidgetItem(QString::number(acc)));
93 | dataTableWidget->item (row,4)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
94 | dataTableWidget->scrollToBottom();
95 |
96 | emit send_data(realData,allData,vs,acc,time);
97 | }
98 |
99 | void MainWindow::recMotionPlanMsg(const QString &arg)
100 | {
101 | ui->textEdit->append(arg);
102 | }
103 |
104 | void MainWindow::rec_cal_done_sig()
105 | {
106 | autorun->quit();
107 | autorun->wait();
108 | ui->btn_start->setText("启动");
109 | }
110 |
111 | void MainWindow::on_btn_start_clicked()
112 | {
113 | if(!autorun->isRunning()){
114 | autorun->pathInit.v0=ui->lineEdit_V0->text().toDouble();
115 | autorun->pathInit.ve=ui->lineEdit_Ve->text().toDouble();
116 | autorun->pathInit.Jerk=ui->lineEdit_Jerk->text().toDouble();
117 | autorun->pathInit.VMax=ui->lineEdit_VMax->text().toDouble();
118 | autorun->pathInit.cmd_pos=ui->lineEdit_distance->text().toDouble();
119 | autorun->pathInit.max_acc=ui->lineEdit_acc->text().toDouble();
120 | //autorun->pathInit.dec_jerk_muti=ui->doubleSpinBox_decMuti->value();
121 | autorun->pathInit.deltaT=ui->lineEdit_planSingleTime->text().toDouble();
122 | disChart->clearData();
123 | spdChart->clearData();
124 | accChart->clearData();
125 | while(dataTableWidget->rowCount()>0)
126 | dataTableWidget->removeRow(0);
127 | ui->textEdit->clear();
128 | autorun->start();
129 | }
130 | else{
131 | autorun->path_pause=false;
132 | ui->btn_start->setText("启动");
133 | }
134 | }
135 |
136 | void MainWindow::on_btn_pause_clicked()
137 | {
138 | autorun->path_pause=true;
139 | ui->btn_start->setText("继续");
140 | }
141 |
142 | void MainWindow::on_btn_cancelPlan_clicked()
143 | {
144 | if(autorun->isRunning()){
145 | autorun->forceQuit=true;
146 | ui->btn_start->setText("启动");
147 | }
148 | }
149 |
150 | void MainWindow::on_btn_showPoints_clicked()
151 | {
152 | static bool showPoint=false;
153 | if(showPoint)
154 | ui->btn_showPoints->setText("显示数据");
155 | else
156 | ui->btn_showPoints->setText("隐藏数据");
157 | disChart->showData(showPoint);
158 | spdChart->showData(showPoint);
159 | accChart->showData(showPoint);
160 | if(showPoint) showPoint=false;
161 | else showPoint=true;
162 | }
163 |
164 | void MainWindow::on_mdiArea_customContextMenuRequested(const QPoint &pos)
165 | {
166 | QAction act_menu("参数菜单显示", this);
167 | QAction act_cascadeShow("级联模式",this);
168 | QAction act_tileShow("平铺模式",this);
169 | connect(&act_menu, &QAction::triggered, this, &MainWindow::showMenu);
170 | connect(&act_cascadeShow, &QAction::triggered, this, &MainWindow::cascadeShow);
171 | connect(&act_tileShow, &QAction::triggered, this, &MainWindow::tileShow);
172 | QMenu menu,mdiShow("图表显示模式");
173 | menu.addAction(&act_menu);
174 | menu.addMenu(&mdiShow);
175 | mdiShow.addAction(&act_cascadeShow);
176 | mdiShow.addAction(&act_tileShow);
177 | menu.exec(QCursor::pos());
178 | }
179 |
180 | void MainWindow::cascadeShow()
181 | {
182 | ui->mdiArea->cascadeSubWindows();
183 | }
184 |
185 | void MainWindow::tileShow()
186 | {
187 | ui->mdiArea->tileSubWindows();
188 | }
189 |
190 | void MainWindow::showMenu()
191 | {
192 | if(ui->dockWidget->isHidden())
193 | ui->dockWidget->show();
194 | }
195 |
--------------------------------------------------------------------------------
/motionPlan/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include"autorun.h"
12 | #include "mychart.h"
13 |
14 | using namespace QtCharts;
15 |
16 | namespace Ui {
17 | class MainWindow;
18 | }
19 |
20 | class MainWindow : public QMainWindow
21 | {
22 | Q_OBJECT
23 |
24 | public:
25 | explicit MainWindow(QWidget *parent = nullptr);
26 | ~MainWindow();
27 |
28 | signals:
29 | void send_data(double, double, double,double,double);
30 |
31 | private slots:
32 | void recMotionPlanMsg(const QString &arg);
33 |
34 | void rec_data(double, double, double , double , double);
35 |
36 | void showMenu();
37 |
38 | void cascadeShow();
39 |
40 | void tileShow();
41 |
42 | void rec_cal_done_sig();
43 |
44 | void on_btn_start_clicked();
45 |
46 | void on_btn_pause_clicked();
47 |
48 | void on_btn_showPoints_clicked();
49 |
50 | void on_btn_cancelPlan_clicked();
51 |
52 | void on_mdiArea_customContextMenuRequested(const QPoint &pos);
53 |
54 | private:
55 | void initTableWidget();
56 |
57 | Ui::MainWindow *ui;
58 | QPointerdisChart,spdChart,accChart;
59 | QPointerdataTableWidget;
60 | //myChart *disChart=nullptr;
61 | //myChart* spdChart=nullptr;
62 | //myChart* accChart=nullptr;
63 | //QTabWidget* dataTabWidget=nullptr;
64 | autoRun *autorun=nullptr;
65 | };
66 |
67 | #endif // MAINWINDOW_H
68 |
--------------------------------------------------------------------------------
/motionPlan/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 958
10 | 755
11 |
12 |
13 |
14 |
15 | Noto Serif CJK SC
16 | 12
17 |
18 |
19 |
20 | MainWindow
21 |
22 |
23 |
24 |
25 | 0
26 |
27 |
28 | 0
29 |
30 |
31 | 0
32 |
33 |
34 | 0
35 |
36 |
37 | 0
38 |
39 | -
40 |
41 |
42 | Qt::ScrollBarAsNeeded
43 |
44 |
45 | Qt::ScrollBarAsNeeded
46 |
47 |
48 | QMdiArea::SubWindowView
49 |
50 |
51 | false
52 |
53 |
54 | false
55 |
56 |
57 | false
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | false
66 |
67 |
68 | 2
69 |
70 |
71 |
72 |
73 | 0
74 |
75 |
76 | 0
77 |
78 |
79 | 0
80 |
81 |
82 | 3
83 |
84 |
85 | 0
86 |
87 | -
88 |
89 |
-
90 |
91 |
-
92 |
93 |
-
94 |
95 |
96 |
97 | Noto Serif CJK SC
98 | 12
99 |
100 |
101 |
102 | 位移:
103 |
104 |
105 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
106 |
107 |
108 |
109 | -
110 |
111 |
112 |
113 | Noto Serif CJK SC
114 | 12
115 |
116 |
117 |
118 | 初速度:
119 |
120 |
121 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
122 |
123 |
124 |
125 | -
126 |
127 |
128 |
129 | Noto Serif CJK SC
130 | 12
131 |
132 |
133 |
134 | 最大速度:
135 |
136 |
137 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
138 |
139 |
140 |
141 | -
142 |
143 |
144 |
145 | Noto Serif CJK SC
146 | 12
147 |
148 |
149 |
150 | 末速度:
151 |
152 |
153 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
154 |
155 |
156 |
157 | -
158 |
159 |
160 |
161 | Noto Serif CJK SC
162 | 12
163 |
164 |
165 |
166 | 加速度:
167 |
168 |
169 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
170 |
171 |
172 |
173 | -
174 |
175 |
176 |
177 | Noto Serif CJK SC
178 | 12
179 |
180 |
181 |
182 | 加加速度:
183 |
184 |
185 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
186 |
187 |
188 |
189 | -
190 |
191 |
192 | 时间单位:
193 |
194 |
195 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
196 |
197 |
198 |
199 |
200 |
201 | -
202 |
203 |
-
204 |
205 |
206 |
207 | 0
208 | 0
209 |
210 |
211 |
212 |
213 | Noto Serif CJK SC
214 | 12
215 |
216 |
217 |
218 | 123.456
219 |
220 |
221 |
222 | -
223 |
224 |
225 |
226 | 0
227 | 0
228 |
229 |
230 |
231 | 0
232 |
233 |
234 |
235 | -
236 |
237 |
238 |
239 | 0
240 | 0
241 |
242 |
243 |
244 |
245 | Noto Serif CJK SC
246 | 12
247 |
248 |
249 |
250 | 1000
251 |
252 |
253 |
254 | -
255 |
256 |
257 |
258 | 0
259 | 0
260 |
261 |
262 |
263 | 1
264 |
265 |
266 |
267 | -
268 |
269 |
270 |
271 | 0
272 | 0
273 |
274 |
275 |
276 |
277 | Noto Serif CJK SC
278 | 12
279 |
280 |
281 |
282 | 5000
283 |
284 |
285 |
286 | -
287 |
288 |
289 |
290 | 0
291 | 0
292 |
293 |
294 |
295 |
296 | Noto Serif CJK SC
297 | 12
298 |
299 |
300 |
301 | 50000
302 |
303 |
304 |
305 | -
306 |
307 |
308 |
309 | 0
310 | 0
311 |
312 |
313 |
314 | 0.001
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 | -
323 |
324 |
-
325 |
326 |
327 | QFrame::StyledPanel
328 |
329 |
330 | QFrame::Raised
331 |
332 |
333 |
334 | 0
335 |
336 |
337 | 0
338 |
339 |
340 | 0
341 |
342 |
343 | 0
344 |
345 |
-
346 |
347 |
348 |
349 | 0
350 | 0
351 |
352 |
353 |
354 | 启动
355 |
356 |
357 |
358 | -
359 |
360 |
361 |
362 | 0
363 | 0
364 |
365 |
366 |
367 | 暂停
368 |
369 |
370 |
371 |
372 |
373 |
374 | -
375 |
376 |
377 | QFrame::StyledPanel
378 |
379 |
380 | QFrame::Raised
381 |
382 |
383 |
384 | 0
385 |
386 |
387 | 0
388 |
389 |
390 | 0
391 |
392 |
393 | 0
394 |
395 |
-
396 |
397 |
398 |
399 | 0
400 | 0
401 |
402 |
403 |
404 | 取消规划
405 |
406 |
407 |
408 | -
409 |
410 |
411 |
412 | 0
413 | 0
414 |
415 |
416 |
417 | 显示数据
418 |
419 |
420 |
421 |
422 |
423 |
424 | -
425 |
426 |
427 |
428 | 0
429 | 0
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
--------------------------------------------------------------------------------
/motionPlan/motionplan.cpp:
--------------------------------------------------------------------------------
1 | #include "motionplan.h"
2 |
3 | motionPlan::motionPlan()
4 | {
5 |
6 | }
7 |
8 | motionPlan::~motionPlan()
9 | {
10 |
11 | }
12 |
13 | void motionPlan::ini_path_data(const pathInitData &pathInit)
14 | {
15 | cmd_pos=pathInit.cmd_pos; remaining_pos=pathInit.cmd_pos;;
16 | v0=fabs(pathInit.v0); Vmax=fabs(pathInit.VMax); ve=fabs(pathInit.ve);
17 | maxAcc=fabs(pathInit.max_acc); Jerk=fabs(pathInit.Jerk);
18 | deltaT=fabs(pathInit.deltaT);
19 |
20 | path_busy=true; can_do_path=false;
21 | decInit=false; dec_finished=false; path_pause_cmd=false;
22 |
23 | vs=v0; val_Auv=0;
24 | preView_phase=0; preViewDone=false;
25 |
26 | dec_move_pos=0; cur_move_pos=0; recordTime=0;
27 |
28 | ficureTime[0]=0; acc_t=0;
29 | moveDir = (cmd_pos >= 0) ? 1 : -1;
30 | judge_path_condition();
31 | #ifdef motionDebug
32 | motionStatusMsg.clear();
33 | #endif
34 | }
35 |
36 | bool motionPlan::pathBusy()//判断是否在规划中
37 | {
38 | if(path_busy) return true;
39 | else return false;
40 | }
41 |
42 | void motionPlan::judge_path_condition()//规划前进行初始条件判断
43 | {
44 | if(fabs(Vmax*deltaT/cmd_pos)>maxProportion)
45 | Vmax=fabs(maxProportion*cmd_pos/deltaT);
46 | if(VmaxcoverAccuracy){//初速度和末速度不相等的情况下
49 | double cal_ve=0,minDis=0,vmin=0;
50 | if(vs>ve)
51 | cal_ve=vs-Jerk*pow(deltaT,2);
52 | else
53 | cal_ve=vs+Jerk*pow(deltaT,2);
54 | minDis=(vs+cal_ve)*deltaT;
55 | vmin=qMax(vs,cal_ve);
56 | if(fabs(cmd_pos)fabs(cmd_pos)){//需要修正末速度
63 | double veTmp=ve,vsTmp=vs,vCenter=ve,minus_dis=0;
64 | bool fixFinished=false;
65 | while(!fixFinished){
66 | vCenter=(veTmp+vsTmp)/2;
67 | get_time_point(vCenter,cal_vmax,cal_maxAcc,t1_tmp,t2_tmp,moveDis);
68 | if(fabs(minus_dis-(moveDis-fabs(cmd_pos)))fabs(cmd_pos)) veTmp=vCenter;
79 | else vsTmp=vCenter;
80 | }
81 | }
82 | }
83 | can_do_path=true;//末速度已满足要求,可以S型速度规划
84 | }
85 | }
86 | else{//初速度和末速度相等的情况下
87 | double cal_minDis=(vs+0.5*Jerk*pow(deltaT,2))*4.0*deltaT;
88 | double cal_vmin=vs+Jerk*pow(deltaT,2);
89 | if(cal_minDis>fabs(cmd_pos) || cal_vmin>Vmax || Jerk*deltaT>maxAcc){//距离太短或最大加速度太小或最大速度太小,退出S型速度规划
90 | can_do_path=false;
91 | }
92 | else can_do_path=true;//可以S型速度规划
93 | }
94 | if(can_do_path) emit sendMsg(tr("开始速度规划...\n参数满足7段S型速度规划条件!"));
95 | else emit sendMsg(tr("开始速度规划...\n参数无法满足7段S型速度规划条件!\n被迫进行匀速运动!"));
96 | }
97 |
98 | bool motionPlan::performPath(bool path_pause)//执行规划
99 | {
100 | if(!path_busy){
101 | emit sendMsg(tr("没初始化参数,无法进行计算,请先初始化参数!"));
102 | return false;
103 | }
104 | if(can_do_path){//S型规划模式
105 | if(!path_pause_cmd || dec_finished)
106 | path_pause_cmd=path_pause;
107 | if(dec_finished){
108 | if(path_pause_cmd)
109 | return false;
110 | else
111 | dec_finished=false;
112 | }
113 | else{
114 | if(path_pause_cmd & !decInit){
115 | if(val_Auv>0){//减速初始化
116 | double cal_vmax,cal_maxAcc,t1_tmp,t2_tmp,moveDis;
117 | get_time_point(dec_ve,cal_vmax,cal_maxAcc,t1_tmp,t2_tmp,moveDis);
118 | get_ficure_point(cal_vmax,dec_ve,t1_tmp,t2_tmp);
119 | preViewDone=false;
120 | preView_phase=2;
121 | }
122 | decInit=true;
123 | }
124 | }
125 | }
126 | else{//匀速模式
127 | path_pause_cmd=path_pause;
128 | if(path_pause_cmd) return false;
129 | }
130 | doMotionPlan(can_do_path);
131 | return true;
132 | }
133 |
134 | void motionPlan::doMotionPlan(bool doPath)//进入运动模式
135 | {
136 | #ifdef motionDebug
137 | static QString motionMsg;
138 | static bool canSendMsg=false;
139 | canSendMsg=false;
140 | #endif
141 | static bool haveMove=false;
142 | if(doPath){
143 | if(!preViewDone){
144 | haveMove=false;
145 | switch(preView_phase){
146 | case 0:{//加加速运动
147 | if(preView(positiveAcceleration)){
148 | #ifdef motionDebug
149 | if(motionStatusMsg!=tr("开始加加速运动阶段:\n")){
150 | motionMsg=tr("开始加加速运动阶段:\n");
151 | canSendMsg=true;
152 | }
153 | #endif
154 | movePreViewPos(positiveAcceleration);
155 | }
156 | else{
157 | if(preView(steadyAcceleration)){
158 | #ifdef motionDebug
159 | if(motionStatusMsg!=tr("开始匀速运动阶段:\n")){
160 | motionMsg=tr("开始匀速运动阶段:\n");
161 | canSendMsg=true;
162 | }
163 | #endif
164 | movePreViewPos(steadyAcceleration);
165 | preView_phase=1;
166 | }
167 | else{
168 | preFicure();
169 | if(acc_t!=0){
170 | #ifdef motionDebug
171 | if(motionStatusMsg!=tr("开始减加速运动阶段:\n")){
172 | motionMsg=tr("开始减加速运动阶段:\n");
173 | canSendMsg=true;
174 | }
175 | #endif
176 | haveMove=true;
177 | movePreViewPos(negetiveAcceleration);
178 | acc_t--;
179 | }
180 | if(acc_t==0) preViewDone=true;
181 | else preView_phase=2;
182 | if(!haveMove){
183 | if(acc_t==0) goto lastMove;
184 | else goto decAcc;
185 | }
186 | }
187 | }
188 | }break;
189 | case 1:{//匀加速运动
190 | if(preView(steadyAcceleration)){
191 | #ifdef motionDebug
192 | if(fabs(val_Auv)ficureTime[3])
252 | haveData=false;
253 | else
254 | haveData=true;
255 | if(!haveData)
256 | recordTime=ficureTime[3]+ficureTimeRecord;
257 |
258 | if(recordTime-ficureTimeRecord>ficureTime[2]){
259 | #ifdef motionDebug
260 | if(ficureMoveDir>0){
261 | if(motionStatusMsg!=tr("开始减减运动阶段:\n")){
262 | motionMsg=tr("开始减减运动阶段:\n");
263 | canSendMsg=true;
264 | }
265 | }
266 | else{
267 | if(motionStatusMsg!=tr("开始减加运动阶段:\n")){
268 | motionMsg=tr("开始减加运动阶段:\n");
269 | canSendMsg=true;
270 | }
271 | }
272 | #endif
273 | timeTmp=recordTime-ficureTimeRecord-ficureTime[2];
274 | moveFicurePos(positiveAcceleration,timeTmp);
275 | }
276 | else if(recordTime-ficureTimeRecord>ficureTime[1]){
277 | #ifdef motionDebug
278 | if(val_Auv>0){
279 | if(motionStatusMsg!=tr("开始匀加运动阶段:\n")){
280 | motionMsg=tr("开始匀加运动阶段:\n");
281 | canSendMsg=true;
282 | }
283 | }
284 | else{
285 | if(motionStatusMsg!=tr("开始匀减运动阶段:\n")){
286 | motionMsg=tr("开始匀减运动阶段:\n");
287 | canSendMsg=true;
288 | }
289 | }
290 | #endif
291 | timeTmp=recordTime-ficureTimeRecord-ficureTime[1];
292 | moveFicurePos(steadyAcceleration,timeTmp);
293 | }
294 | else if(recordTime-ficureTimeRecord>ficureTime[0]){
295 | #ifdef motionDebug
296 | if(ficureMoveDir>0){
297 | if(motionStatusMsg!=tr("开始加减运动阶段:\n")){
298 | motionMsg=tr("开始加减运动阶段:\n");
299 | canSendMsg=true;
300 | }
301 | }
302 | else{
303 | if(motionStatusMsg!=tr("开始加加运动阶段:\n")){
304 | motionMsg=tr("开始加加运动阶段:\n");
305 | canSendMsg=true;
306 | }
307 | }
308 | #endif
309 | timeTmp=recordTime-ficureTimeRecord-ficureTime[0];
310 | moveFicurePos(negetiveAcceleration,timeTmp);
311 | }
312 | else{
313 | #ifdef motionDebug
314 | if(motionStatusMsg!=tr("开始匀速运动阶段:\n")){
315 | motionMsg=tr("开始匀速运动阶段:\n");
316 | canSendMsg=true;
317 | }
318 | #endif
319 | timeTmp=recordTime-ficureTimeRecord;
320 | cur_move_pos=moveDir *vs*timeTmp;
321 | }
322 | cur_move_pos-=recordDis;
323 | recordDis+=cur_move_pos;
324 | if(!haveData){
325 | if(path_pause_cmd && fabs(remaining_pos-cur_move_pos)>coverAccuracy){
326 | dec_finished=true;
327 | decInit=false;
328 | dec_move_pos+=(cmd_pos-remaining_pos+cur_move_pos);
329 | cmd_pos=remaining_pos-cur_move_pos;
330 | v0=vs;
331 | val_Auv=0;
332 | preView_phase=0;
333 | preViewDone=false;
334 | acc_t=0;
335 | ficureTime[0]=0;
336 | judge_path_condition();
337 | }
338 | else
339 | path_busy=false;
340 | }
341 | }
342 | }
343 | else{
344 | if((moveDir*Vmax*deltaT)/(cmd_pos+dec_move_pos)>maxProportion)
345 | cur_move_pos=maxProportion*(cmd_pos+dec_move_pos);
346 | else
347 | cur_move_pos=moveDir*Vmax*deltaT;
348 | recordTime+=deltaT;
349 | if(fabs(remaining_pos)Vmax || current_acc>maxAcc) return false;
390 | else if(((moveDir*cal_vmax*deltaT)/(cmd_pos+dec_move_pos))>maxProportion) return false;
391 | else{
392 | move_dis+=moveDir*(current_vs*current_acc/Jerk+0.5*current_acc*pow(current_acc/Jerk,2)-Jerk*pow(current_acc/Jerk,3)*1.0/6.0);
393 | double cur_remaining_pos=remaining_pos-move_dis;
394 | double cal_maxAcc=sqrt(fabs(cal_vmax-ve)*Jerk);
395 | if(cal_maxAcc>maxAcc)
396 | cal_maxAcc=maxAcc;
397 | cal_maxAcc=(static_cast((cal_maxAcc+coverAccuracy)/(Jerk*deltaT)))*Jerk*deltaT;
398 | double t1_tmp=cal_maxAcc/Jerk;
399 | double t2_tmp=0;
400 | if(fabs(cal_maxAcc)>coverAccuracy)
401 | t2_tmp=(fabs(cal_vmax-ve)-pow(cal_maxAcc,2)/Jerk)/cal_maxAcc;
402 | double moveDis=(ve+cal_vmax)*t1_tmp+(cal_vmax+ve)*t2_tmp/2;
403 | if(fabs(moveDis)<=fabs(cur_remaining_pos)) return true;
404 | else return false;
405 | }
406 | }
407 |
408 | void motionPlan::preFicure()//全部前瞻完,结束前瞻
409 | {
410 | double cal_acc_dis=moveDir*(vs*val_Auv/Jerk+0.5*val_Auv*pow(val_Auv/Jerk,2)-Jerk*pow(val_Auv/Jerk,3)*1.0/6.0);
411 | double moveDis,cal_vmax,cal_maxAcc,t1_tmp,t2_tmp;
412 | get_time_point(ve,cal_vmax,cal_maxAcc,t1_tmp,t2_tmp,moveDis);
413 | ficureTime[0]=fabs(moveDis-fabs(remaining_pos-cal_acc_dis))/cal_vmax;
414 | get_ficure_point(cal_vmax,ve,t1_tmp,t2_tmp);
415 | }
416 |
417 | void motionPlan::get_time_point(const double vEnd,double &cal_vmax,double &cal_maxAcc,double &t1_tmp,double &t2_tmp,double &moveDis)//获取到达最大速度的时间,最大加速度,以及后半程各阶段时间
418 | {
419 | acc_t=static_cast((val_Auv+coverAccuracy)/Jerk/deltaT);
420 | cal_vmax=vs+val_Auv*val_Auv/Jerk-0.5*Jerk*pow(val_Auv/Jerk,2);
421 | cal_maxAcc=sqrt(fabs(cal_vmax-vEnd)*Jerk);
422 | if(cal_maxAcc>maxAcc)
423 | cal_maxAcc=maxAcc;
424 | cal_maxAcc=(static_cast((cal_maxAcc+coverAccuracy)/(Jerk*deltaT)))*Jerk*deltaT;
425 | t1_tmp=cal_maxAcc/Jerk;
426 | t2_tmp=0;
427 | if(fabs(cal_maxAcc)>coverAccuracy)
428 | t2_tmp=(fabs(cal_vmax-vEnd)-pow(cal_maxAcc,2)/Jerk)/cal_maxAcc;
429 | moveDis=(cal_vmax+vEnd)*t1_tmp+(cal_vmax+vEnd)*t2_tmp/2;
430 | }
431 |
432 | void motionPlan::get_ficure_point(const double vBegin,const double vEnd,const double t1_tmp,const double t2_tmp)//获取后半程时间,位移,速度,加速度节点信息
433 | {
434 | if(vBegin>vEnd) ficureMoveDir=1;
435 | else ficureMoveDir=-1;
436 |
437 | recordDis=0;
438 |
439 | ficureTimeRecord=recordTime+acc_t*deltaT;
440 | ficureTime[1]=t1_tmp+ficureTime[0];
441 | ficureTime[2]=ficureTime[1]+t2_tmp;
442 | ficureTime[3]=ficureTime[2]+t1_tmp;
443 |
444 | ficureV[0]=vBegin;
445 | ficureAcc[0]=0;
446 | ficureDis[0]=moveDir*ficureV[0]*ficureTime[0];
447 |
448 | ficureV[1]=ficureV[0]+0.5*(ficureAcc[0] + ficureAcc[0]-ficureMoveDir*Jerk * t1_tmp) * t1_tmp;
449 | ficureAcc[1]=ficureAcc[0]-ficureMoveDir*Jerk*t1_tmp;
450 | ficureDis[1]=ficureDis[0]+moveDir *(ficureV[0]*t1_tmp+0.5*ficureAcc[0]*pow(t1_tmp,2)-ficureMoveDir*1.0/6.0*Jerk*pow(t1_tmp,3));
451 |
452 | ficureV[2]=ficureV[1]+ficureAcc[1]*t2_tmp;
453 | ficureAcc[2]=ficureAcc[1];
454 | ficureDis[2]=ficureDis[1]+moveDir *(ficureV[0]+ve)*t2_tmp/2;
455 | }
456 |
457 | void motionPlan::moveFicurePos(enumType motionType,const double timeTmp)
458 | {
459 | switch (motionType){
460 | case positiveAcceleration:{
461 | cur_move_pos=ficureDis[2]+moveDir *(ficureV[2]*timeTmp+0.5*ficureAcc[2]*pow(timeTmp,2)+ficureMoveDir*1.0/6.0*Jerk*pow(timeTmp,3));
462 | vs=ficureV[2]+0.5*(ficureAcc[2] + ficureAcc[2]+ficureMoveDir*Jerk * timeTmp) * timeTmp;
463 | val_Auv =ficureAcc[2]+ ficureMoveDir*Jerk * timeTmp;
464 | }break;
465 |
466 | case steadyAcceleration:{
467 | cur_move_pos=ficureDis[1]+moveDir *(ficureV[1]*timeTmp+0.5*ficureAcc[1]*pow(timeTmp,2));
468 | vs=ficureV[1]+ficureAcc[1] * timeTmp;
469 | }break;
470 | case negetiveAcceleration:{
471 | cur_move_pos=ficureDis[0]+moveDir *(ficureV[0]*timeTmp+0.5*ficureAcc[0]*pow(timeTmp,2)-ficureMoveDir*1.0/6.0*Jerk*pow(timeTmp,3));
472 | vs=ficureV[0]+0.5*(ficureAcc[0] + ficureAcc[0]-ficureMoveDir*Jerk * timeTmp) * timeTmp;
473 | val_Auv =ficureAcc[0]- ficureMoveDir*Jerk * timeTmp;
474 | }break;}
475 | }
476 |
477 | void motionPlan::movePreViewPos(enumType motionType)//下一时刻运动计算
478 | {
479 | switch (motionType){
480 | case positiveAcceleration:{//加速度绝对值增大
481 | cur_move_pos=moveDir *(vs*deltaT+0.5*val_Auv*pow(deltaT,2)+1.0/6.0*Jerk*pow(deltaT,3));
482 | vs+=0.5*(val_Auv + val_Auv+Jerk * deltaT) * deltaT;
483 | val_Auv += Jerk * deltaT;
484 | }break;
485 | case steadyAcceleration:{//加速度不变
486 | cur_move_pos=moveDir *(vs*deltaT+0.5*val_Auv*pow(deltaT,2));
487 | vs+=val_Auv * deltaT;
488 | //val_Auv = val_Auv;
489 | }break;
490 | case negetiveAcceleration:{//加速度绝对值减小
491 | cur_move_pos=moveDir *(vs*deltaT+0.5*val_Auv*pow(deltaT,2)-1.0/6.0*Jerk*pow(deltaT,3));
492 | vs+=0.5*(val_Auv + val_Auv-Jerk * deltaT) * deltaT;
493 | val_Auv -= Jerk * deltaT;
494 | }break;}
495 | recordTime+=deltaT;
496 | }
497 |
498 | void motionPlan::get_move_msg(double &curProportion,double &curPos_m,double &curVs_m, double &curAcc_m,double &curTime_m)//获得当前所走位移占比、总位移、速度、加速度、时间
499 | {
500 | if(fabs(cmd_pos+dec_move_pos)<=coverAccuracy)
501 | curProportion=0;
502 | else
503 | curProportion=(cmd_pos-remaining_pos+dec_move_pos)/(cmd_pos+dec_move_pos);
504 | curPos_m=cmd_pos-remaining_pos+dec_move_pos;
505 | curVs_m=vs;
506 | curAcc_m=val_Auv;
507 | curTime_m=recordTime;
508 | }
509 |
510 | #ifdef motionDebug
511 | void motionPlan::get_move_msg(QString &motionMsg)
512 | {
513 | motionMsg+=tr("当前位移:")+QString::number(cmd_pos-remaining_pos+dec_move_pos,'f',6)+"\n";
514 | motionMsg+=tr("当前速度:")+QString::number(vs)+"\n";
515 | motionMsg+=tr("当前加速度:")+QString::number(val_Auv)+"\n";
516 | motionMsg+=tr("当前时间:")+QString::number(recordTime)+"\n";
517 | }
518 | #endif
519 |
--------------------------------------------------------------------------------
/motionPlan/motionplan.h:
--------------------------------------------------------------------------------
1 | #ifndef S_MOTIONPLAN_H
2 | #define S_MOTIONPLAN_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | struct pathInitData{
10 | double max_acc=0;//最大加速度
11 | double Jerk=0 ;//加加速度
12 | double cmd_pos=0 ;//位移
13 | double v0=0;//初速度
14 | double VMax=0;//最大速度
15 | double ve=0;//末速度
16 | double deltaT=0.001;//规划时最小时间单位(默认0.001s)
17 | };
18 |
19 | class motionPlan : public QObject
20 | {
21 | Q_OBJECT
22 | public:
23 | motionPlan();
24 | ~motionPlan();
25 | bool performPath(bool path_pause=false);//执行规划
26 | #ifdef motionDebug
27 | void get_move_msg(QString &motionMsg);
28 | #endif
29 | void get_move_msg(double &curProportion,double &curPos_m,double &curVs_m, double &curAcc_m,double &curTime_m);//获得当前所走总位移、速度、加速度、时间
30 | void ini_path_data(const pathInitData &pathInit);//初始化参数
31 | bool pathBusy();//判断是否在规划中
32 |
33 | signals:
34 | void sendMsg(const QString &);//发送调试信息
35 |
36 | private:
37 | double deltaT=0.001;
38 |
39 | const double coverAccuracy=pow(10,-12);//弥补double精度
40 | const double maxProportion=1;
41 |
42 | #ifdef motionDebug
43 | QString motionStatusMsg;
44 | #endif
45 |
46 | double cmd_pos=0,remaining_pos=0,dec_move_pos=0,cur_move_pos=0;
47 | double v0=0,Vmax=0,ve=0,vs=0,dec_ve=0;
48 | double maxAcc=0,Jerk=0,val_Auv=0;
49 | double recordTime=0,ficureTimeRecord=0,recordDis=0;
50 |
51 | bool decInit=false, dec_finished=false,path_pause_cmd=false;
52 | bool path_busy=false,can_do_path=false;
53 |
54 | uint preView_phase=0;
55 | bool preViewDone=false;
56 |
57 | int moveDir=0;
58 | int ficureMoveDir=0;
59 |
60 | int acc_t=0;
61 | double ficureTime[4]={0,0,0,0};
62 | double ficureV[3]={0,0,0};
63 | double ficureAcc[3]={0,0,0};
64 | double ficureDis[3]={0,0,0};
65 |
66 | enum enumType{positiveAcceleration,steadyAcceleration,negetiveAcceleration};
67 | void judge_path_condition();//进行规划条件判断
68 | void doMotionPlan(bool doPath);//运行单位时间计算
69 | bool preView(enumType motionType);//前瞻下一个单位时间,并做出判断
70 | void preFicure();//前瞻完成,将后半程各个阶段的信息计算出来
71 | void movePreViewPos(enumType motionType);//前瞻后运动一个单位时间的计算
72 | void moveFicurePos(enumType motionType, const double time);//后半程运动一个单位时间的计算
73 | void get_time_point(const double vEnd,double &cal_vmax,double &cal_maxAcc,double &t1_tmp,double &t2_tmp,double &moveDis);//获取到达最大速度的时间,最大加速度,以及后半程各阶段时间
74 | void get_ficure_point(const double vBegin,const double vEnd,const double t1_tmp,const double t2_tmp);//获取后半程时间,位移,速度,加速度节点信息
75 | };
76 |
77 |
78 | #endif // S_MOTIONPLAN_H
79 |
--------------------------------------------------------------------------------
/motionPlan/mychart.cpp:
--------------------------------------------------------------------------------
1 | #include "mychart.h"
2 | #include "ui_mychart.h"
3 |
4 | myChart::myChart(uchar type, QWidget *parent) :
5 | QWidget(parent),
6 | chartType(static_cast(type)),
7 | ui(new Ui::myChart)
8 | {
9 | ui->setupUi(this);
10 | setMouseTracking(true);
11 | ui->chartView->setAttribute(Qt::WA_TransparentForMouseEvents, true);
12 | switch (chartType) {
13 | case disChartType:setWindowTitle("位移时间曲线");break;
14 | case spdChartType:setWindowTitle("速度时间曲线");break;
15 | case accChartType:setWindowTitle("加速度时间曲线");break;
16 | }
17 | init_chart();
18 | }
19 |
20 | myChart::~myChart()
21 | {
22 | delete ui;
23 | }
24 |
25 | void myChart::rec_data(double realData, double allData, double vs, double acc,double time)
26 | {
27 | QLineSeries *series=qobject_cast(ui->chartView->chart()->series().at(0));
28 | static double chartData=0;
29 | static bool outRange=false;
30 |
31 | switch (chartType) {
32 | case disChartType:{
33 | chartData=allData;
34 | series->setName("耗时:"+QString::number(time)+"秒 总位移:"+QString::number(allData));
35 | }break;
36 | case spdChartType:{
37 | chartData=vs;
38 | series->setName("耗时:"+QString::number(time)+"秒 当前速度:"+QString::number(vs));
39 | }break;
40 | case accChartType:{
41 | chartData=acc;
42 | series->setName("耗时:"+QString::number(time)+"秒 当前加速度:"+QString::number(acc));
43 | }break;}
44 |
45 | series->append(time,chartData);
46 | if(time<=rangeX0){
47 | rangeX0=time;
48 | outRange=true;
49 | }
50 | else if(time>=rangeX1){
51 | rangeX1=time;
52 | outRange=true;
53 | }
54 | if(chartData<=rangeY0){
55 | rangeY0=chartData;
56 | outRange=true;
57 | }
58 | else if(chartData>=rangeY1){
59 | rangeY1=chartData;
60 | outRange=true;
61 | }
62 | if(outRange){
63 | ui->chartView->chart()->axisX()->setRange(rangeX0,rangeX1);
64 | ui->chartView->chart()->axisY()->setRange(rangeY0,rangeY1);
65 | outRange=false;
66 | }
67 | }
68 |
69 | void myChart::init_chart()
70 | {
71 | QChart *chart=new QChart();
72 | ui->chartView->setChart(chart);
73 | ui->chartView->setRenderHint(QPainter::Antialiasing);
74 | QPen pen;
75 | pen.setStyle(Qt::SolidLine);
76 | pen.setWidth(2);
77 | QValueAxis *axisX=new QValueAxis;
78 | axisX->setLabelFormat("%0.3f");
79 | axisX->setTickCount(0);
80 | axisX->setTitleText("时间(秒)");
81 | QValueAxis *axisY=new QValueAxis;
82 | axisY->setLabelFormat("%0.3f");
83 | axisY->setTickCount(0);
84 | switch (chartType) {
85 | case disChartType:{
86 | axisY->setTitleText("位移");
87 | pen.setColor(Qt::red);
88 | }break;
89 | case spdChartType:{
90 | axisY->setTitleText("速度");
91 | pen.setColor(Qt::green);
92 | }break;
93 | case accChartType:{
94 | axisY->setTitleText("加速度");
95 | pen.setColor(Qt::blue);
96 | }break;}
97 | QLineSeries *series=new QLineSeries;
98 | series->setName("耗时");
99 | series->setPen(pen);
100 | chart->addSeries(series);
101 | chart->setAxisX(axisX,series);
102 | chart->setAxisY(axisY,series);
103 | axisX->setRange(rangeX0,rangeX1);
104 | axisY->setRange(rangeY0,rangeY1);
105 | }
106 |
107 | void myChart::mousePressEvent(QMouseEvent *event)
108 | {
109 | if (event->button() == Qt::LeftButton){
110 | drag_flag = true;
111 | m_lastPointF=event->pos();
112 | setCursor(Qt::OpenHandCursor);
113 | }
114 | }
115 |
116 | void myChart::mouseReleaseEvent(QMouseEvent *event)
117 | {
118 | drag_flag = false;
119 | setCursor(Qt::ArrowCursor);
120 | }
121 |
122 | void myChart::mouseMoveEvent(QMouseEvent *event)
123 | {
124 | if (drag_flag){
125 | QPoint curPos = event->pos();
126 | QPoint offset = curPos - m_lastPointF;
127 | m_lastPointF = curPos;
128 | ui->chartView->chart()->scroll(-offset.x(), offset.y());
129 | ui->chartView->chart()->update();
130 | }
131 | }
132 |
133 | void myChart::wheelEvent(QWheelEvent *event)
134 | {
135 | const QPoint curPos = event->pos();
136 | QPointF curVal = ui->chartView->chart()->mapToValue(QPointF(curPos));
137 | const double factor = 1.1;//缩放比例
138 | QValueAxis *axisX=(QValueAxis *)ui->chartView->chart()->axisX();
139 | QValueAxis *axisY=(QValueAxis *)ui->chartView->chart()->axisY();
140 | const double xMin = axisX->min();
141 | const double xMax = axisX->max();
142 | const double yMin = axisY->min();
143 | const double yMax = axisY->max();
144 | const double xCentral = curVal.x();
145 | const double yCentral = curVal.y();
146 | double leftOffset=0,rightOffset=0,bottomOffset=0,topOffset=0;
147 | if (event->delta() > 0){//放大
148 | bottomOffset = 1.0 / factor * (yCentral - yMin);
149 | topOffset = 1.0 / factor * (yMax - yCentral);
150 | leftOffset = 1.0 / factor * (xCentral - xMin);
151 | rightOffset = 1.0 / factor * (xMax - xCentral);
152 | }
153 | else{//缩小
154 | bottomOffset = 1.0 * factor * (yCentral - yMin);
155 | topOffset = 1.0 * factor * (yMax - yCentral);
156 | leftOffset = 1.0 * factor * (xCentral - xMin);
157 | rightOffset = 1.0 * factor * (xMax - xCentral);
158 | }
159 | rangeX0=xCentral - leftOffset;
160 | rangeX1=xCentral + rightOffset;
161 | rangeY0=yCentral - bottomOffset;
162 | rangeY1=yCentral + topOffset;
163 |
164 | ui->chartView->chart()->axisX()->setRange(rangeX0,rangeX1);
165 | ui->chartView->chart()->axisY()->setRange(rangeY0,rangeY1);
166 | ui->chartView->chart()->update();
167 | }
168 |
169 | void myChart::clearData()
170 | {
171 | QLineSeries *series=qobject_cast(ui->chartView->chart()->series().at(0));
172 | series->clear();
173 | }
174 |
175 | void myChart::showData(bool showPoint)
176 | {
177 | QLineSeries *series=qobject_cast(ui->chartView->chart()->series().at(0));
178 | if(showPoint){
179 | series->setPointsVisible(false);
180 | series->setPointLabelsVisible(false);
181 | }
182 | else{
183 | series->setPointsVisible(true);
184 | series->setPointLabelsVisible(true);
185 | }
186 | }
187 |
188 |
189 |
--------------------------------------------------------------------------------
/motionPlan/mychart.h:
--------------------------------------------------------------------------------
1 | #ifndef MYCHART_H
2 | #define MYCHART_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace QtCharts;
10 |
11 | namespace Ui {
12 | class myChart;
13 | }
14 |
15 | class myChart : public QWidget
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit myChart(uchar type,QWidget *parent = nullptr);
21 | ~myChart();
22 | void clearData();
23 | void showData(bool showPoint);
24 | enum chartShowType{disChartType=0,spdChartType,accChartType};
25 |
26 | protected:
27 | void wheelEvent(QWheelEvent* event);
28 |
29 | void mousePressEvent(QMouseEvent *event);
30 |
31 | void mouseMoveEvent(QMouseEvent *event);
32 |
33 | void mouseReleaseEvent(QMouseEvent *event);
34 |
35 | public slots:
36 | void rec_data(double, double, double , double , double);
37 |
38 | private:
39 | void init_chart();
40 |
41 | chartShowType chartType;
42 | bool drag_flag=false;
43 | QPoint m_lastPointF;
44 | double rangeX0=0,rangeX1=1,rangeY0=0,rangeY1=1;
45 |
46 | Ui::myChart *ui;
47 | };
48 |
49 | #endif // MYCHART_H
50 |
--------------------------------------------------------------------------------
/motionPlan/mychart.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | myChart
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 | 0
19 |
20 |
21 | 0
22 |
23 |
24 | 0
25 |
26 |
27 | 0
28 |
29 |
30 | 0
31 |
32 | -
33 |
34 |
35 |
36 |
37 |
38 |
39 | QChartView
40 | QGraphicsView
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/motionPlan/pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhangming-wang/motionPlan/15146bad7fbaac76512e9e99ca02bafdc6b03520/motionPlan/pic.png
--------------------------------------------------------------------------------