-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmainwindow.h
More file actions
214 lines (167 loc) · 6.52 KB
/
Copy pathmainwindow.h
File metadata and controls
214 lines (167 loc) · 6.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/******************************************************************************
* @file mainwindow.h
* @brief Declaration of MainWindow — primary controller for the Open Motion
* 6-DOF platform application (UI, IK, telemetry, serial, rendering).
*
* Responsibilities:
* - Wire UI controls and slider callbacks (manual drive mode).
* - Handle sim drive via X-Plane UDP (XPlaneUdpReceiver).
* - Maintain platform state (X,Y,Z, φ,θ,ψ) and geometry (Eigen 3×6).
* - Provide IK intermediates and computed servo angles for 6 servos.
* - Manage Arduino serial I/O (QtSerialPort) with auto-detect/retry.
* - Bridge geometry to ImGuiGLWidget for 3D visualization.
* - Expose a live telemetry dock (Euler, body rates, accelerations).
*
* Conventions:
* - Geometry uses millimeters and radians unless noted; slider angles are
* in degrees (converted in the implementation).
* - Eigen matrices are column-major 3×6 sets: rows = {x,y,z}, cols = joints.
*
* Part of the Open Motion project (6DOF Motion Simulator).
******************************************************************************/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSlider>
#include <cstring> // for memset
#include <Eigen/Dense>
#include "xplaneudpreceiver.h"
#include <QTimer>
#include <QLabel>
#include <QDockWidget>
#include <QSerialPort>
#include <QSerialPortInfo>
// forward declare
class ImGuiGLWidget;
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setX(double value);
void setY(double value);
void setZ(double value);
void setPHI(double value);
void setTHETA(double value);
void setPSI(double value);
private slots:
void on_startButton_clicked();
void on_abortButton_clicked();
void on_homeButton_clicked();
void on_Slider_X_valueChanged(int value);
void on_Slider_Y_valueChanged(int value);
void on_Slider_Z_valueChanged(int value);
void on_Slider_PHI_valueChanged(int value);
void on_Slider_THETA_valueChanged(int value);
void on_Slider_PSI_valueChanged(int value);
void on_chkDriveFromSim_toggled(bool checked);
double clamp(double value, double min, double max);
private:
Ui::MainWindow *ui;
double X;//= 1.0*(ui->Slider_X->value());
double Y;//= 1.0*(ui ->Slider_Y ->value());
double Z;//= 1.0*(ui ->Slider_Z -> value());
double phi;//= deg2rad*(ui->Slider_PHI ->value()) ;//-0.087266462599717;
double theta;//= deg2rad*(ui ->Slider_THETA ->value());//0.226892802759263;
double psi;// = deg2rad*(ui ->Slider_PSI -> value());//0.2;//0.191986217719376;
std::array<double, 6> angles;
double servo_arm;
double servo_leg;
double beta[6];
double height;
//============== Platform geometry ===================
Eigen::Matrix<double, 3, 6> Platform_pos_zero;
Eigen::Matrix<double, 3, 6> Servo_pos;
Eigen::Matrix<double,3,3> R_PB; //rotation matrix
Eigen::Matrix<double, 3, 1> t_home;
Eigen::Matrix<double, 3, 1> t_input;
Eigen::Matrix<double, 3, 1> T;
double h_0;
Eigen::Matrix<double, 3, 6> Rotated_platform;
Eigen::Matrix<double, 3, 6> New_pos;
Eigen::Matrix<double, 3, 6> lin_leg_lengths;
Eigen::Matrix<double, 1, 6> virtual_leg_lengths;
double L_home;
double M_home;
double N_home;
Eigen::Matrix<double,1,6> L;
Eigen::Matrix<double,1,6> M;
double x_diff; // intermediate calc
double y_diff;
Eigen::Matrix<double,1,6> N;
Eigen::Matrix<double,1,6>alpha;
Eigen::Matrix<double,1,6>servo_deg;
Eigen::Matrix<double,3,6> Knee_pos_new;
double alpha_home;
double alpha_home_deg;
Eigen::Matrix<double,3,6> Knee_pos_home;
void initGeometryFromAngles_();
//=========== GUI ===============================
QSlider *Slider_X; // declare Slider_X as a member of the class
QSlider *Slider_Y;
QSlider *Slider_Z;
QSlider *Slider_PHI;
QSlider *Slider_THETA;
QSlider *Slider_PSI;
void pushGeometryToGL();
ImGuiGLWidget* glw_ = nullptr;
XPlaneUdpReceiver* udpRx_ = nullptr; // from the previous fix
QTimer* tick_ = nullptr; // for periodic updates
void stepPlatformAndSerial();
//=================== Telemetry labels ==============
QLabel *lblRoll_ = nullptr, *lblPitch_ = nullptr, *lblYaw_ = nullptr;
QLabel *lblP_ = nullptr, *lblQ_ = nullptr, *lblR_ = nullptr;
QLabel *lblAx_ = nullptr, *lblAy_ = nullptr, *lblAz_ = nullptr;
void createTelemetryDock_();
// ============== Qt SerialPort ===============
void setupSerialQt(); // open (auto-detect) & configure
void closeSerialQt(); // close safely
void sendAnglesQt(const QString&); // write line to serial
void retryOpenSerialQt(); // periodic retry if unplugged
QSerialPort* sp_ = nullptr;
QTimer* serialRetry_ = nullptr; // retry timer if device missing
QString serialPortName_; // for UI/status
// ============= Mode Settings ==================
// Drive mode
enum class DriveMode { Manual, FromSim };
DriveMode driveMode_ = DriveMode::Manual;
// Sim-origin capture (deg) and flag
bool haveSimZero_ = false;
double roll0_deg = 0.0, pitch0_deg = 0.0, yaw0_deg = 0.0;
// Last sample + timestamp for watchdog
bool lastHaveSample_ = false;
MotionSample lastSample_{};
qint64 lastSimMs_ = 0;
// Simple gains/limits for platform angles [NEEDS TUNING and actually using brains]
struct
{
// attitude
double kRoll = 1.0; // deg->deg gain (used against sim deltas)
double kPitch = 1.0;
double kYaw = 1.0;
double maxRoll = 15.0 * M_PI/180;
double maxPitch= 15.0 * M_PI/180;
double maxYaw = 15.0 * M_PI/180;
// NEW: translations (mm-per-slider-tick or mm-per-sim-unit)
double kX = 2.0; // try 2–5 mm per tick to start
double kY = 2.0;
double kZ = 2.0;
// Safety clamps (mm)
double maxX = 80.0;
double maxY = 80.0;
double maxZ = 90.0; // be mindful of horn limits below-horizontal
} cue_;
bool viewFlipY_ = true; // flip Y in 3D view to fix roll sense
struct AxisSign
{
double roll = -1.0; // <- invert roll (fixes for “bank left/right”)
double pitch = +1.0; // adjust if you find pitch is reversed
double yaw = +1.0; // adjust if yaw is reversed
} axis_;
};
#endif // MAINWINDOW_H