关于熊老师那边的项目的总结
作为一个小总结吧…
学习是从上个寒假开始的, 熊老师让我帮他弄那个轮椅控制的事情= =当时每个星期天都跑了过去帮忙, 连续弄了好几个星期吧, 最后快到期末基本弄成了.
然后这两天帮他们把他们后续的东西大致给弄完了, 然后晚上感觉在那边睡着不是很踏实, 就今天跑回来了, 毕竟后面的任务我在家也可以完成了, 在那边确实呆着不是很舒服, 洗澡什么的也不方便.
帮那个同学弄了一下震荡检测的, 虽然这个算法我觉得还是需要在考虑下或者参数需要调好点, 不过最后结果看起来还是可以的.
在那边主要帮忙了三个东西, 一个摇晃检测, 一个移动动态控制, 还有一个GPRS数据传输的东西.
不多说代码如下
摇晃检测
#include
#include
Madgwick filter; // initialise Madgwick object
int ax, ay, az;
int gx, gy, gz;
float yaw[30];
float pitch[30];
float roll[30];
int factor = 800; // variable by which to divide gyroscope values, used to control sensitivity
// note that an increased baud rate requires an increase in value of factor
int calibrateOffsets = 1; // int to determine whether calibration takes place or not
void setup() {
// initialize Serial communication
Serial.begin(9600);
// initialize device
CurieIMU.begin();
if (calibrateOffsets == 1) {
// use the code below to calibrate accel/gyro offset values
Serial.println("Internal sensor offsets BEFORE calibration...");
Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getGyroOffset(X_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getGyroOffset(Y_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getGyroOffset(Z_AXIS)); Serial.print("\t");
Serial.println("");
// To manually configure offset compensation values, use the following methods instead of the autoCalibrate...() methods below
// CurieIMU.setGyroOffset(X_AXIS, 220);
// CurieIMU.setGyroOffset(Y_AXIS, 76);
// CurieIMU.setGyroOffset(Z_AXIS, -85);
// CurieIMU.setAccelerometerOffset(X_AXIS, -76);
// CurieIMU.setAccelerometerOffset(Y_AXIS, -235);
// CurieIMU.setAccelerometerOffset(Z_AXIS, 168);
//IMU device must be resting in a horizontal position for the following calibration procedure to work correctly!
Serial.print("Starting Gyroscope calibration...");
CurieIMU.autoCalibrateGyroOffset();
Serial.println(" Done");
Serial.print("Starting Acceleration calibration...");
CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0);
CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);
Serial.println(" Done");
Serial.println("Internal sensor offsets AFTER calibration...");
Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
Serial.println("");
}
}
int k = 0;
int flag = 0;
float roll3[3];
float pitch3[3];
int sign = 0;
void readFirstMotion(){
for(int i = 0;i<30;i++){
CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);
filter.updateIMU(gx / factor, gy / factor, gz / factor, ax, ay, az);
roll[i] = filter.getRoll();
pitch[i] = filter.getPitch();
}
}
void refreshMotion(){
for(int i = 0;i<29;i++){
roll[i] = roll[i+1];
pitch[i] = pitch[i+1];
}
CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);
filter.updateIMU(gx / factor, gy / factor, gz / factor, ax, ay, az);
roll[29] = filter.getRoll();
pitch[29] = filter.getPitch();
}
int var(){
refreshMotion();
for(int i = 0;i<29;i++){
if(i % 10 == 0 && i <= 20){
float roll_mean = 0;
float pitch_mean = 0;
for(int k = i;k= 0.5) || (abs(roll3[2] - roll[3]) >= 0.5) || abs((pitch3[1] - pitch3[2]) >= 0.5) || (abs(pitch3[2] - pitch[3]) >= 0.5))
return 1;
else
return 0;
}
int judge(){
int count = 0;
for(int i = 0; i<5000; i++){
int sign = var();
if(sign == 1){
count++;
}
}
if(count >= 4000){
return 1;
}else
return 0;
}
void loop() {
if(flag == 0){
readFirstMotion();
flag++;
}
sign = judge();
if (sign == 0){
Serial.println("situation is OK");
}else{
Serial.println("bad situation");
}
}
测试结果我这里没有板子, 最后在串口检测的数据
行驶控制的代码有点多…600多行, 因为还有安卓端的程序接口还有一堆数据传输的东西, 不过这些都是与控制无关的, 只上传核心部分了.
行驶控制
double angle[100];//用来存储每一个阶段运行时所应该保持的角度
double old_val = 0;//用来标记是否目的地发生了更新, 以便同步更新angle数组
int count = 0;//用来计数表示目前正在行进的哪一个直线阶段
int flag = 0;//用来标记原地调整方向动作,调整完之后就不在进行原地调整.
double eps_angle = 0.1;//对方向角的误差允许值eps, 小于这个eps可以认为当前角度与目标角度一致
double eps_geo = 0.00001; //对地理位置的误差允许值eps, 小于这个eps可以认为当前位置与目标位置一致
double eps_run = 0.0000001;//对运行状态的误差允许值eps, 小于这个eps可以认为当前小车没有发生运动
//更新角度数组
void freshAngle(){
for (int i = 0;i < num-1;i++) {
angle[i] = anglesolve(z_lon[i],z_lat[i], z_lon[i+1], z_lat[i+1]);
}
}
////运动调整函数.用来判断目前位置所应该做出的动作
void moveAdjust(){
//下面这段用来原地姿态调整
mm1 = directZ - angle[count];
if(abs(mm1) > eps_angle && flag ==0){
if(mm1 > 0){
spin_right();//这里角度还没有对上传感器的量纲, 了解其含义后对应更改
}
else{
spin_left();//这里角度还没有对上传感器的量纲, 了解其含义后对应更改
}
}
else{//下面用来进行直线行驶, 并且调整角度, 和上面一样角度没有对应传感器的量纲, 这个eps的值需要自行更改
if(flag == 0){
flag++;
}
if(calD() > eps_geo){
if( abs(longitude[3] - longitude[0]) + abs(latitude[3]- latitude[0]) < eps_run){
run();
}
mm2 = directZ - angle[count];
if( abs(mm2) > eps_angle){//用来判断是否偏离了角度, 偏离则进行修正, 这里的修正幅度可以根据自己需要进行更改
if(mm2 < 0){//比如如果角度比较大, 想要转向更快一些, 可以把right函数修改一下, 带入参数目前角度与目标角度的差, 进行即时更新.
right();
}else{
left();
}
}
else{
keep_run();//添加的keep_run函数, 保持最大速度进行, 因为你们之前写的run是调整进行的不能满足要求.
}
}
else{//这里用来对到达当前目的地进行技术, 更新flag和count, 以便下一步更新时状态进行改变
flag = 0;
count++;
brake();
}
}
}
//计算与当前目的地的相对地理位置偏差
double calD(){
diff_lon = longitude[3] - z_lon[count+1];
diff_lat = latitude[3] - z_lat[count+1];
return sqrt(pow(diff_lon,2)+pow(diff_lat,2));
}
//给定两坐标求角度
double anglesolve(double x1, double y1, double x2, double y2){
double a =(y2-y1)*laDis;
double b =(x2-x1)*longDis*cos(y1);
return atan2(a,b);
}
//总调整函数
void adjust(){
//下面语句用来判断是否需要更新angle这个目标角度数组
if(old_val != z_lon[0] && num != 0){
freshAngle();
count = 0;
}
//下面语句用来对当前的坐标及方向角进行调整
if(num != 0){
old_val = z_lon[0];
moveAdjust();
}
}
void loop()
{
//yaogan();
//byte msg[10];
if (acc.isConnected())
{
int len = acc.read(message, sizeof(message), 200);
if(message[0]=='*'){
int i=0;
while(message[i]!='#'){
Serial.print(message[i]);
i++;
}
Serial.println("~~~~~~~~~~~~~~~~~");
judeg();
Serial.println("~~~~~~~~~~~~~~~~~");
}
Serial.println(directX);
sprintf(dir,"%d",(int)directX);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+34]=dir[dd];
}
sprintf(dir,"%d",(int)directY);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+38]=dir[dd];
}
sprintf(dir,"%d",(int)directZ);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+42]=dir[dd];
}
sprintf(dir,"%d",(int)angleX);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+46]=dir[dd];
}
sprintf(dir,"%d",(int)angleY);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+50]=dir[dd];
}
sprintf(dir,"%d",(int)angleZ);//将int转换成char数组
for(int dd=0;dd<3;dd++)
{
control[dd+54]=dir[dd];
}
message[0]='0';
message[5]='0';
Serial.println("=================");
for(int i=0;i<60;i++){
Serial.print(control[i]);
}
Serial.println("===========");
acc.write(control, 60);
}
adjust();
GPSworking();
yaogan();
//control[5]='0';
}
然后是一些细节的地方给他们去修改了, 然后今天8月10号到学校来参加数模比赛了, 看了一下cs189发现prerequisite
有cs188 artificial intelligence…毕竟cs189的名字是introduction to machine learning, 一个intro还以为是个本科课, 结果在quora上看到别人说有1/3的人都是graduate, = =我就跟着这个课一起上吧, 顺便把esl给看了, 主要这个cs189的一些lecture和video都挺全的, 目前的打算大致过一遍然后继续看cs188.
然后是prml和mlapp感觉国外大学基本不用这两本书当教材, 一般还是用esl, 所以我还是主要看esl这本书吧, 然后是cracking the code interview这本书最好一起看了, 大三也好找实习, 有几个目标项目如果申请上了感觉还是很不错哒.
对了最后今天修改了一下代码的背景, 不知道怎么每次选的一些主题颜色什么的看久了就觉得难看了, 比如这次看到别人的一个主题或者配置挺好看的, 弄到自己那里后过一段时间就感觉好难看了, 哈哈…
最后的最后我发现前几天mathematica 11出了, 貌似是主打neural network, 看了一下实例感觉好强大啊, 一些example写出来很简单但是结果很强大, 暑假最好能弄到, 写神经网络也好写的说, 虽然在R上弄的一个感觉还可以, 但是毕竟到了卷积的一些操作就比较麻烦了, 用tensorflow的化现在感觉还没有学那么深, 一些理论还没有看, 只知道conv-pooling…
好啦今天就这样吧.