[linux]申请设备号

1.静态申请
cat /proc/devices //查看已有设别号

2.动态申请

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
dev:保存申请到的设备号。
baseminor: 次设备号起始地址, alloc_chrdev_region 可以申请一段连续的多个设备号,这些设备号的主设备号一样,但是次设备号不同,次设备号以 baseminor 为起始地址地址开始递增。一般 baseminor 为 0,也就是说次设备号从 0 开始。
count: 要申请的设备号数量。
name:设备名字。

注销字符设备之后要释放掉设备号,设备号释放函数如下:
void unregister_chrdev_region(dev_t from, unsigned count)
此函数有两个参数:
from:要释放的设备号。
count: 表示从 from 开始,要释放的设备号数量。

[linux]驱动模块的加载与卸载,字符串设备的注册与注销

/* 驱动入口函数 */
static int __init xxx_init(void)
{
/* 入口函数具体内容 */
return 0;
}

static void __exit xxx_exit(void)
{
/* 出口函数具体内容 */
}

module_init(xxx_init);

module_exit(xxx_exit);

加载
modprobe *.ko
卸载
rmmod *.ko

注册

static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)

注销
static inline void unregister_chrdev(unsigned int major, const char *name)

[linux]根文件系统挂载

服务器地址为 192.168.0.105 目录为/home/yue/rootfs
开发板地址为 192.168.0.200

setenv bootargs ‘console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.105:/home/yue/rootfs,proto=tcp rw ip=192.168.0.200:192.168.0.105:192.168.0.1:255.255.255.0::eth0:off’
saveenv

[linux]服务器可执行,vscode不行

arm-linux-gnueabihf-gcc -v
例如以上命令,在服务器上可以显示版本,但在vscode上显示未安装,检查服务器上profile也对
1.打开powershell,用管理员权限打开
2.输入get-executionpolicy,显示Restricted
3.输入set-executionpolicy -executionpolicy unrestricted 提示后输入a
4.再次输入get-executionpolicy 显示Unrestricted
5.重启vscode

[Linux]烧录文件组成

I.MX6U 的最终可烧写文件组成如下:
①、 Image vector table,简称 IVT, IVT 里面包含了一系列的地址信息,这些地址信息在
ROM 中按照固定的地址存放着。
②、 Boot data,启动数据,包含了镜像要拷贝到哪个地址,拷贝的大小是多少等等。
③、 Device configuration data,简称 DCD,设备配置信息,重点是 DDR3 的初始化配置。
④、用户代码可执行文件,比如 led.bin。
可以看出最终烧写到 I.MX6U 中的程序其组成为: IVT+Boot data+DCD+.bin。所以第八章
中的 imxdownload 所生成的 load.imx 就是在 led.bin 前面加上 IVT+Boot data+DCD。内部 Boot
ROM 会将 load.imx 拷贝到 DDR 中,用户代码是要一定要从 0X87800000 这个地方开始的,因
为链接地址为 0X87800000, load.imx 在用户代码前面又有 3KByte 的 IVT+Boot Data+DCD 数
据,下面会讲为什么是 3KByte,因此 load.imx 在 DDR 中的起始地址就是 0X87800000-
3072=0X877FF400

[FK]穿越机翻滚

————————–以下方式没实际使用上———————-

pitch的范围是-90°-0-90°
roll的范围是-180°-180°
yaw的范围是-180°-180°

1.首先确定坐标系,是ENU坐标系还是NED坐标系,
方法是看x,y,z的正方向,x指向正东,y指向正北,z指向天则为ENU坐标系。x指向正北,y指向正东,z指向地则为NED坐标系
已经确认我用的是ENU坐标系,z对应yaw , y对应pitch ,x对应roll

2.确定旋转方向
方法用右手定则,大拇指先指向Z,绕Z的正方向(其余手指)旋转,yaw变化,其余pitch和roll不变。第二步 大拇指指向Y,pitch变化,其余yaw和roll不变化,第三步,大拇指指向X的正方向,roll变化,其余两轴不变化。
则确认欧拉角的旋转方向是Z-Y-X,确认旋转方向至关重要。

3.理解欧拉角、姿态角、四元数、旋转矩阵

端午节期间在疑似新冠头晕后遗症、娃的爱的奥特曼铁拳以及老婆的鼓励下,终于发现点眉目

发现roll偏转一定角度后,pitch怎么旋转,角度都不能到90°,在pitch由0°-90°-0°旋转时,得出的角度都是0°-30°-0°这样,于是查阅资料,发现有旋转矩阵这个东西,找个各个版本的,重新确认旋转方向,将角度带进去,不对,求转置矩阵,还是不对,最后把三个向量[1 0 0 ][0 1 0] [0 0 1]带进去,好像是对了 – -,以下是代码

—————————————————————————————————————
#include #include
#include
#include

#define MI 0.017453292519943295
#define M_PI 3.14159265358979323846

struct _Quat{
double w;
double x;
double y;
double z;
};

struct _Quat Quat;

void ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
{
// Abbreviations for the various angular function

yaw = yaw*MI;
pitch = pitch*MI;
roll = roll*MI;

double w,x,y,z;
double cy = cos(yaw * 0.5);
double sy = sin(yaw * 0.5);
double cp = cos(pitch * 0.5);
double sp = sin(pitch * 0.5);
double cr = cos(roll * 0.5);
double sr = sin(roll * 0.5);

Quat.w = cy * cp * cr + sy * sp * sr;
Quat.x = cy * cp * sr – sy * sp * cr;
Quat.y = sy * cp * sr + cy * sp * cr;
Quat.z = sy * cp * cr – cy * sp * sr;
// printf(“四元数:\r\n”);
// printf(“w = %f\r\nx = %f\r\ny = %f\r\nz = %f\r\n”,Quat.w,Quat.x,Quat.y,Quat.z);
}

int Att_Convert(float y,float p,float r)
{
float cx ,cy ,cz;
float yx ,yy ,yz;

r = r*MI;
p = p*MI;
y = y*MI;

float yc11 = cos(y);
float yc12 = -sin(y);
float yc13 = 0;

float yc21 = sin(y);
float yc22 = cos(y);
float yc23 = 0;

float yc31 = 0;
float yc32 = 0;
float yc33 = 1;

float rc11 = 1;
float rc12 = 0;
float rc13 = 0;

float rc21 = 0;
float rc22 = cos(r);
float rc23 = -sin(r);

float rc31 = 0;
float rc32 = sin(r);
float rc33 = cos(r);

float c11 = cos(y)*cos(p);
float c21 = cos(p)*sin(y);
float c31 = -sin(p);

float c12 = cos(y)*sin(r)*sin(p)-cos(r)*sin(y);
float c22 = cos(y)*cos(r)+sin(y)*sin(r)*sin(p);
float c32 = cos(p)*sin(r);

float c13 = sin(y)*sin(r)+cos(y)*cos(r)*sin(p);
float c23 = cos(y)*sin(r)+cos(r)*sin(y)*sin(p);;
float c33 = cos(r)*cos(p);
/*
cx = y*c11+ p*c12 + r*c13;
cy = y*c21+ p*c22 + r*c23;
cz = y*c31+ p*c32 + r*c33;
*/

cx = r*c11+ p*c21 + y*c31;
cy = r*c12+ p*c22 + y*c32;
cz = r*c13+ p*c23 + y*c33;

yx = r * yc11 + p * yc12 + y * yc13;
yy = r * yc21 + p * yc22 + y * yc23;
yz = r * yc31 + p * yc32 + y * yc33;

cx = cx / MI;
cy = cy / MI;
cz = yz / MI;

yx = yx / MI;
yy = yy / MI;
yz = yz / MI;

printf(“yx’=%f\r\nyy’=%f\r\nyz’=%f\r\n”,cx,cy,cz);
}
int main(int argc,char * argv[])
{
float yaw = atof(argv[1]);
float pitch = atof(argv[2]);
float roll = atof(argv[3]);

// float q3 = atof(argv[4]);

float q0,q1,q2,q3;

double c11,c12,c13,c21,c22,c23,c31,c32,c33;

double g1;
double g2;
double g3;
double g4;
double g5;

float ax=0;
float ay=0;
float az=0;

float px,py,pz;

float cx1,cx2,cx3,cy1,cy2,cy3,cz1,cz2,cz3;

ToQuaternion(yaw,pitch,roll);

q0 = Quat.w;
q1 = Quat.x;
q2 = Quat.y;
q3 = Quat.z;

// printf (“四元数:\r\nq0=%f\r\nq1=%f\r\nq2=%f\r\nq3=%f\r\n”,q0,q1,q2,q3);

g1 = 2*(q1*q3-q0*q2);
g2 = 2*(q2*q3+q0*q1);
g3 = q0*q0-q1*q1-q2*q2+q3*q3;
g4 = 2*(q1*q2+q0*q3);
g5 = q0*q0+q1*q1-q2*q2-q3*q3;

c11 = q0*q0+q1*q1-q2*q2-q3*q3;
c21 = 2*(q1*q2+q0*q3);
c31 = 2*(q1*q3-q0*q2);

c12 = 2*(q1*q2 -q0*q3);
c22 = q0*q0-q1*q1+q2*q2-q3*q3;
c32 = 2*(q2*q3+q0*q1);

c13 = 2*(q1*q3 +q0*q2);
c23 = 2*(q2*q3-q0*q1);
c33 = q0*q0-q1*q1-q2*q2+q3*q3;
/*
cx1 = c11*0.6+c12 * 0 + c13 * 0;
cx2 = c21*0.6+c22 * 0 +c23 * 0;
cx3 = c31*0.6+c32 * 0 + c33 * 0;

cy1 = c11*0+c12 * -0.6 + c13 * 0;
cy2 = c21*0+c22 * -0.6 +c23 * 0;
cy3 = c31*0+c32 * -0.6 + c33 * 0;

cz1 = c11*0+c12 * 0 + c13 * -0.6;
cz2 = c21*0+c22 * 0 +c23 * -0.6;
cz3 = c31*0+c32 * 0 + c33 * -0.6;
*/

cx1 = c11*1+c12 * 0 + c13 * 0;
cx2 = c21*1+c22 * 0 + c23 * 0;
cx3 = c31*1+c32 * 0 + c33 * 0;

cy1 = c11*0+c12 * 1 + c13 * 0;
cy2 = c21*0+c22 * 1 + c23 * 0;
cy3 = c31*0+c32 * 1 + c33 * 0;

cz1 = c11*0+c12 * 0 + c13 * 1;
cz2 = c21*0+c22 * 0 + c23 * 1;
cz3 = c31*0+c32 * 0 + c33 * 1;

//printf(“旋转矩阵\r\n”);
// printf(“c11=%f c12=%f c13=%f\r\nc21=%f c22=%f c23=%f\r\nc31=%f c32=%f c33=%f\r\n”,c11,c12,c13,c21,c22,c23,c31,c32,c33);
printf(“向量\r\n”);
printf(“cx1=%f cx2=%f cx3=%f\r\n”,cx1,cx2,cx3);
printf(“cy1=%f cy2=%f cy3=%f\r\n”,cy1,cy2,cy3);
printf(“cz1=%f cz2=%f cz3=%f\r\n”,cz1,cz2,cz3);

ax = atan2(cx2,sqrt(cx1*cx1 + cx3*cx3))/MI; //pitch ,绕y轴旋转,取y-xoz平面的角度
ay = atan2(cz1,sqrt(cz2*cz2 + cz3*cz3))/MI; //yaw ,绕z轴旋转,取z-xoy平面的角度
az = atan2(cy3,sqrt(cy1*cy1 + cy2*cy2))/MI; //roll ,绕X轴旋转,取x-yoz平面的角度
/*
if(cx1 >=0)
{
ax = atan2(cx2,sqrt(cx1*cx1 + cx3*cx3))/MI;
}
else
{
ax = 180 – atan2(cx2,sqrt(cx1*cx1 + cx3*cx3))/MI;
}

if(ax > 180)
{
ax = ax-360;
}

if (cx1 >=0 )
{
ay = -atan2(cx3,sqrt(cx1*cx1 + cx2*cx2))/MI; //PITCH 绕
}
else
{
ay = 180+atan2(cx3,sqrt(cx1*cx1 + cx2*cx2))/MI; //PITCH 绕
}
if (ay>180)
{
ay = ay-360;
}

if (cy2>=0)
{
az = atan2(cy3,sqrt(cy1*cy1 + cy2*cy2))/MI; //PITCH 绕
}
else
{
az = 180 – atan2(cy3,sqrt(cy1*cy1 + cy2*cy2))/MI; //PITCH 绕
}
if (az > 180)
{
az = az-360;
}
*/
/*
ax = atan2(cz1,sqrt(cz2*cz2 + cz3*cz3))/MI;
ay = atan2(cz2,sqrt(cz1*cz1 + cz3*cz3))/MI;
az = atan2(cz3,sqrt(cz1*cz1 + cz2*cz2))/MI;
*/
// ay = atan2(cy2,sqrt(cy1*cy1 + cy3*cy3)); //
// az = atan2(cx3,sqrt(cx1*cx1 + cx2*cx2)); //
/*
ay = atan2(cy2,sqrt(cy1*cy1 + cy3*cy3));

ay = atan2(cy2,sqrt(cy1*cy1 + cy3*cy3));
az = atan2(cz3,sqrt(cz1*cz1 + cz2*cz2));

*/
printf(“角度\r\n”);
printf(“ax =%f \r\n”,ax);
printf(“ay=%f \r\n”,ay);
printf(“az =%f \r\n”,az);

// Att_Convert(y,p,r);
}

—————————————————————————————
求完后还是感觉不对,压根就没解决pitch到不了90°的问题,于是还是从欧拉角下手,根据pitch-roll的旋转方向,打算推出roll对pitch的影响,即当pitch是30°时,roll从0-90°变化的时候,让pitch由30-90°变化,继续冥思苦想,说实话年纪大了空间想象能力是真的差,最后想到了切西瓜的模型,假设在半径为1的西瓜上来回切,最终通过三角函数解决了,以下是代码
————————————————————————————————————————————–
#include #include
#include
#include
#define MI 0.017453292519943295
#define M_PI 3.14159265358979323846

int main(int argc,char * argv[])
{
float a1,a2,a3;

float a = atof(argv[1]);
float b = atof(argv[2]);

float x1,x2,x3,x4;

float c = 0;

float theta = a*MI;

float A = 2*sin(theta/2);

float B = sqrt(2);
float C = sqrt(2);

float D = acos(A/2/C)/MI; //

float E = sin(45*MI);
float F = 0;
float H = 0;

float G = 0;
b = 45+b;

F = E / tan(b*MI);
F = E -F;

//A F D
G = sqrt(A*A+F*F-2*A*F*cos(D*MI));
//1 F 45
H = sqrt(1*1+F*F-2*1*F*cos(45*MI));

printf(“A = %f\r\n”,A);
printf(“b = %f\r\n”,b);
printf(“E = %f\r\n”,E);
printf(“F = %f\r\n”,F);
printf(“D = %f\r\n”,D);
printf(“G = %f\r\n”,G);
printf(“H = %f\r\n”,H);

// 1 G H

a = 1;
b = G;
c = H;

printf(“\r\n”);
printf(“D1 = %f\r\n”,a);
printf(“D2 = %f\r\n”,b);
printf(“D3 = %f\r\n”,c);

/*
cosA=(b²+c²-a²)/2bc;
cosB=(a²+c²-b²)/2ac;
cosC=(a²+b²-c²)/2ab。
*/

x1 = acos((b*b+b*b-a*a)/(2*b*c));
x2 = acos((a*a+c*c-b*b)/(2*a*c));
x3 = acos((a*a+b*b-c*c)/(2*a*b));

x1= x1/MI;
x2= x2/MI;
x3= x3/MI;

printf(“x1 = %f\r\n”,x1);
printf(“x2 = %f\r\n”,x2);
printf(“x3 = %f\r\n”,x3);
}

x2是最终求的数据
———————————————————————————————
求出来了带进飞控里看下呗,还真不行,如果roll转动的话直接导致pitch变化,当有roll的时候,pitch会基本等于roll,但是遥控器给出的pitch还是0,肯定会导致飞机转圈,以后再解决把,最后还是用的原始欧拉角- –

陆陆续续四轴搞了一年了,手搓的机架、飞控、遥控器、姿态调节、上位机程序、无线LoRa数传,也飞起来的,那就暂时告一段落吧,先搞搞linux,搞定图传后再研究四轴FPV

[linux]strerror perror

int main(void)
{
int fd;
fd = open(“./test_file”,O_RDONLY);
if (-1==fd)
{
printf(“Error:%s\n”,strerror(errno));
//perror(“open error”);
return -1;
}
close(fd);
return 0;
}

Error:No such file or directory
open error:NO such file or directory

[linux]man 命令

示例man 2 open
man 命令后面跟着两个参数,数字 2 表示系统调用, man 命令除了可以查看系统调用的帮助信息
外,还可以查看 Linux 命令(对应数字 1)以及标准 C 库函数(对应数字 3)所对应的帮助信息;最后一个
参数 open 表示需要查看的系统调用函数名

[linux]压缩、解压缩

tar -vxf test.tar //解包
tar -vcf test.tar test //将test打包为test.tar

tar -jxvf test.tar.bz2 //解压缩
tar -jcvf test.tar.bz2 test //将test压缩为test.tar.bz2

tar -zxvf test.tar.gz //解压缩
tar -zcvf test.tar.gz test //将test压缩为test.tar.gz

[FK]matlab 椭圆拟合

–注意matlab版本选择18版本以上,否则不支持部分函数

[cc lang=”matlab” tab_size=”4″]

function [ellipse] = ellipsefit(x,y)

x=[3
1
-2
2
0
-5
-15
-18
-21
-29
-38
-44
-55
-59
-67
-74
-80
-89
-103
-105
-108
-119
-120
-130
-132
-136
-138
-141
-154
-161
-175
-185
-186
-192
-198
-200
-203
-211
-217
-221
-222
-222
-226
-224
-230
-228
-227
-225
-221
-221
-218
-209
-210
-203
-196
-190
-186
-178
-172
-162
-153
-145
-136
-125
-114
-106
-98
-84
-83
-73
-64
-61
-54
-41
-33
-28
-17
-6
-3
10
26
31
44
50
57
65
71
84
90
98
108
117
115
124
142
153
158
162
168
171
183
187
196
197
205
212
218
218
215
223
224
225
229
224
227
227
220
225
219
218
218
213
209
207
200
197
189
179
167
162
157
149
143
128
121
115
108
99
96
92
88
87
74
70
63
56
47
41
23
20
14
15
13
19
15
8
1
-7
-15
-28
-36
-40
-46
-53
-58
-58
-68
-77
-85
-94
-103
-118
-127
-130

];

y=[-234
-233
-235
-231
-234
-233
-237
-233
-229
-226
-226
-225
-219
-222
-218
-215
-215
-208
-209
-211
-210
-206
-195
-192
-195
-189
-184
-184
-172
-156
-146
-140
-117
-114
-94
-88
-74
-71
-62
-47
-37
-20
-8
5
29
39
44
66
66
82
86
87
99
107
116
129
138
148
155
160
174
179
188
187
197
203
197
208
206
207
210
212
220
226
225
226
235
239
237
227
227
226
223
220
219
221
216
210
203
201
196
194
188
190
182
178
165
165
157
156
149
131
127
119
101
93
89
81
68
50
38
33
29
17
2
-10
-17
-26
-30
-43
-49
-63
-72
-88
-94
-100
-109
-119
-138
-139
-142
-151
-151
-161
-164
-167
-168
-169
-162
-163
-160
-159
-158
-158
-164
-164
-158
-152
-154
-162
-168
-170
-185
-185
-190
-180
-180
-174
-171
-172
-173
-163
-163
-165
-161
-160
-157
-161
-156
-154
-155
-152
-145
-147

];

%x=x+9.9831;
%y=y+26.9348;
%y = y*1.054;
%y = y*1.00134;
grid on;
hold on;
plot(x,y,’*’)

% 采用最小二乘法进行椭圆拟合
% 采用椭圆一般式子:x^2 + A*x*y + B*y^2 + C*x + D*y + E = 0;

xlength = length(x);
xmax = max(x);
ymax = max(y);
if(xlength ~= length(y) | xlength < 5) warning('椭圆拟合至少需要四个点数据'); else M1 = [ sum(x.^2.*y.^2), sum(x.*y.^3), sum(x.^2.*y), sum(x.*y.^2), sum(x.*y) sum(x.*y.^3), sum(y.^4), sum(x.*y.^2), sum(y.^3), sum(y.^2) sum(x.^2.*y), sum(x.*y.^2), sum(x.^2), sum(x.*y), sum(x) sum(x.*y.^2), sum(y.^3), sum(x.*y), sum(y.^2), sum(y) sum(x.*y), sum(y.^2), sum(x), sum(y), xlength] ; %M1满秩才可逆 if rank(M1) == 5 M2 = -[ sum(x.^3.*y); sum(x.^2.*y.^2); sum(x.^3); sum(x.^2.*y); sum(x.^2)]; G = inv(M1)*M2; [A,B,C,D,E] = deal(G(1),G(2),G(3),G(4),G(5)); ellipse = [A,B,C,D,E]; Xp = (A*D-2*B*C)/(A*A-4*B); Yp = (A*C-2*D)/(A*A-4*B); Xc = -Xp; Yc = -Yp; theta_r = 0.5*atan(A/(B-1)); theta_offset = - theta_r; a = sqrt((Xp^2+A*Xp*Yp+B*Yp^2-E)/(cos(theta_r)^2-A*sin(theta_r)*cos(theta_r)+B*sin(theta_r)^2)); b = sqrt((Xp^2+A*Xp*Yp+B*Yp^2-E)/(sin(theta_r)^2+A*sin(theta_r)*cos(theta_r)+B*cos(theta_r)^2)); %绘图 plot(x,y,'bo') fimplicit(@(x,y)x.^2 + A.*x.*y + B.*y.^2 + C.*x + D.*y + E ,'-r','LineWidth', 3) plot(Xc,Yc,'ro','LineWidth', 3); plot([Xc Xc+a*cos(theta_offset)],[Yc Yc+a*sin(theta_offset)],'--p','LineWidth', 3); title(['圆心坐标为(' num2str(Xc) ',' num2str(Yc) '),偏移角为' num2str(theta_offset*180/pi) '°,长轴为' num2str(a) ',短轴为' num2str(b) ... newline 'x^2 + ' num2str(A) 'xy + ' num2str(B) 'y^2 + ' num2str(C) 'x + ' num2str(D) 'y + ' num2str(E) '= 0']); axis equal end end end [/cc]