Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed YKNCT_Movement SBDBT BNO055 YKNCT_MD YKNCT_I2C
Diff: main.cpp
- Revision:
- 15:02c68793a266
- Parent:
- 14:4c49218bb9fb
--- a/main.cpp Thu Mar 26 06:59:05 2020 +0000
+++ b/main.cpp Thu Mar 26 17:13:54 2020 +0000
@@ -21,6 +21,22 @@
ROCATION Target;
/* 定数定義 ------------------------------------------------------------------*/
+
+/* スラローム自動移動の座標最大数 */
+const int SlalomPointMAX=10;
+/* [0][1][2]…X,Y,Theta(deg) [3]許容残り距離 */
+const int SlalomPoint[SlalomPointMAX][4] = {
+ { 500, 500, 0, 0},
+ {1950, 1250, 0, 100},
+ {1950, 2750, 0, 100},
+ { 510, 2750, 0, 100},
+ { 510, 4250, 0, 100},
+ {1950, 4250, 0, 100},
+ {1950, 5750, 0, 100},
+ {1210, 5750, 0, 100},
+ {1210, 9000, 0, 100},
+ {5515, 9000, 0, 0}
+};
/* マクロ定義 ----------------------------------------------------------------*/
/* 関数プロトタイプ宣言 -------------------------------------------------------*/
@@ -33,8 +49,11 @@
/* オムニ関係 */
void SubOmuni(int X,int Y,int R);
+/* ジャイロ補整 */
+void CompYaw(void);
+
/* 台形制御値代入 */
-int omuni_control(int tar_x, int tar_y, int tar_theta, int error);
+int omuni_control(int X0,int Y0,int X1,int Y1,double tar_theta, int error);
/* 移動する点を探す */
int lncl(double *pt1, double *pt2, double *xyr, double *xy);
@@ -46,6 +65,10 @@
/* 自動シーケンス */
int auto_mode=0;
+int auto_sequence=0;
+
+/* ゾーン指定 0…青,1…赤 */
+bool zone=0;
/* 直読みエンコーダ角度保存(degree) */
double EncoderDeg[EncoderMAX] = {0};
@@ -56,9 +79,6 @@
/* 自動yaw補整目標角度 */
double TarTheta=0;
-/* 補正値用定数 */
-int cor=4;
-
/* クラス定義 ----------------------------------------------------------------*/
/* 割り込み用クラス */
@@ -67,12 +87,6 @@
/* gyro用タイマ */
Timer yawCnt;
-/* P制御終了タイマ */
-Timer P_fin;
-
-/* タイマ加速 */
-Timer Acc_time;
-
/* UART (Tx,Rx) */
Serial telemetry(USBTX, USBRX, 115200);
@@ -118,6 +132,11 @@
MD.Init(2,MD_SMB);
MD.Init(3,MD_SMB);
+ /* タイマ-スタート */
+ yawCnt.start();
+ /* タイマーリセット */
+ yawCnt.reset();
+
telemetry.printf("\n\rMainLoopStart");
/* メインループ --------------------------------------------------------------*/
while(1) {
@@ -142,11 +161,14 @@
/* I2CMD実行 */
MD.Exe();
- /* タイマ-スタート */
- yawCnt.start();
- /* タイマーリセット */
- yawCnt.reset();
-
+ /* Startで各種初期化 */
+ if(Start) {
+ NowLoc.X=0;
+ NowLoc.Y=0;
+ NowLoc.theta=0;
+ TarTheta=0;
+ auto_sequence=0;
+ }
/* 操縦権変更 ×停止 △手動 〇自動 */
if(DS3.CROSS) operate=0;
@@ -169,14 +191,12 @@
int y_val = (double)(64-DS3.LY)*100/64;
int r_val = (double)(DS3.RX-64)*100/64;
- /* 目標角更新 */
+ SubOmuni(x_val, y_val, r_val);
+
+ /* 目標角更新・ジャイロ補整 */
if(DS3.RX!=64) yawCnt.reset();
if(yawCnt.read_ms()<1000) TarTheta=NowLoc.theta;
-
- /* gyro値による補正 */
- r_val += (TarTheta-NowLoc.theta)*cor;
-
- SubOmuni(x_val, y_val, r_val);
+ CompYaw();
}
/* 操縦権:自動 */
@@ -184,69 +204,31 @@
switch(auto_mode) {
/* スタート待機処理 */
case 0:
- /* オンボードSWで次のステップに */
- if(UB) auto_mode++;
+ /* オンボードSWで終了処理,次のステップに */
+ if(UB){
+ auto_mode++;
+ auto_sequence=1;
+ }
break;
- /* 〇〇の処理(青ゾーン) */
+ /* 最初のスラローム */
case 1:
- if(omuni_control(1950, 1250, 0, 100) == 1) auto_mode++;
- break;
- case 2:
- if(omuni_control(1950, 2750, 0, 100) == 1) auto_mode++;
- break;
- case 3:
- if(omuni_control(510, 2750, 0, 100) == 1) auto_mode++;
- break;
- case 4:
- if(omuni_control(510, 4250, 0, 100) == 1) auto_mode++;
- break;
- case 5:
- if(omuni_control(1950, 4250, 0, 100) == 1) auto_mode++;
- break;
- case 6:
- if(omuni_control(1950, 5750, 0, 100) == 1) auto_mode++;
- break;
- case 7:
- if(omuni_control(1210, 5750, 0, 100) == 1) auto_mode++;
- break;
- case 8:
- if(omuni_control(1210, 9000, 0, 100) == 1) auto_mode++;
- break;
- case 9:
- if(omuni_control(5515, 9000, 0, 100) == 1) auto_mode++;
+ /* 経路追従移動 */
+ if(omuni_control(
+ SlalomPoint[auto_sequence-1][0],SlalomPoint[auto_sequence-1][1],
+ SlalomPoint[auto_sequence][0],SlalomPoint[auto_sequence][1],
+ SlalomPoint[auto_sequence][2],SlalomPoint[auto_sequence][3])==0)
+ {
+ /* 次のポイントを目標に */
+ auto_sequence++;
+ /* 目標が最大数に達したら終了処理 */
+ if(auto_sequence==SlalomPointMAX){
+ auto_sequence=1;
+ auto_mode++;
+ }
+ }
break;
- /* 〇〇の処理(赤ゾーン) */
- /*case 1:
- if(omuni_control(-1950, 1250, 0, 100) == 1) auto_mode++;
- break;
- case 2:
- if(omuni_control(-1950, 2750, 0, 100) == 1) auto_mode++;
- break;
- case 3:
- if(omuni_control(-510, 2750, 0, 100) == 1) auto_mode++;
- break;
- case 4:
- if(omuni_control(-510, 4250, 0, 100) == 1) auto_mode++;
- break;
- case 5:
- if(omuni_control(-1950, 4250, 0, 100) == 1) auto_mode++;
- break;
- case 6:
- if(omuni_control(-1950, 5750, 0, 100) == 1) auto_mode++;
- break;
- case 7:
- if(omuni_control(-1210, 5750, 0, 100) == 1) auto_mode++;
- break;
- case 8:
- if(omuni_control(-1210, 9000, 0, 100) == 1) auto_mode++;
- break;
- case 9:
- if(omuni_control(-5515, 9000, 0, 100) == 1) auto_mode++;
- break;
- */
-
/* 終了処理 */
default:
auto_mode=0;
@@ -258,51 +240,6 @@
}
}
-
-/*******************************************************************************
-* @概要 自己位置推定関数
-* @引数 なし
-* @返り値 なし
-*******************************************************************************/
-void LocEstimate(void)
-{
- static double GyroDeg[2]= {0};
- static double EncDeg[2][2]= {0};
- static double disp[3]= {0};
-
-
-
- /* ジャイロの値取得 */
- bno.get_angles();
- GyroDeg[1]=GyroDeg[0];
- GyroDeg[0]=bno.euler.yaw;
- if(GyroDeg[0]!=0) {
- /* 359→0を跨いだ時,前回の値を0から逆回転で負の値で表記 */
- if(GyroDeg[1]<90 && GyroDeg[0]>270) GyroDeg[1]+=360;
- /* 0→359を跨いだ時,前回の値を360以上の値で表記 */
- else if(GyroDeg[1]>270 && GyroDeg[0]<90) GyroDeg[1]-=360;
- /* 差を求める*/
- disp[2]=GyroDeg[1]-GyroDeg[0];
- }
- /* Enc2つの差分求める */
- for(int i=0; i<2; i++) {
- EncDeg[i][1]=EncDeg[i][0];
- EncDeg[i][0]=EncoderDeg[i];
- disp[i]=DEG_TO_DIS(EncDeg[i][1]-EncDeg[i][0]);
- }
- /* 差分を加速度として保存 */
- NowAcc.theta = disp[2];
- NowAcc.X = -disp[0] * cos(DEG_TO_RAD(NowLoc.theta)) - disp[1] * sin(DEG_TO_RAD(NowLoc.theta));
- NowAcc.Y = -disp[0] * sin(DEG_TO_RAD(NowLoc.theta)) + disp[1] * cos(DEG_TO_RAD(NowLoc.theta));
- /* 差分を累積して現在位置を保存 */
- NowLoc.X += NowAcc.X;
- NowLoc.Y += NowAcc.Y;
- NowLoc.theta += NowAcc.theta;
-}
-
-
-
-
/* 割り込み(100us) *************************************************************/
void IT_CallBack(void)
{
@@ -348,7 +285,44 @@
}
+/*******************************************************************************
+* @概要 自己位置推定関数
+* @引数 なし
+* @返り値 なし
+*******************************************************************************/
+void LocEstimate(void)
+{
+ static double GyroDeg[2]= {0};
+ static double EncDeg[2][2]= {0};
+ static double disp[3]= {0};
+ /* ジャイロの値取得 */
+ bno.get_angles();
+ GyroDeg[1]=GyroDeg[0];
+ GyroDeg[0]=bno.euler.yaw;
+ if(GyroDeg[0]!=0) {
+ /* 359→0を跨いだ時,前回の値を0から逆回転で負の値で表記 */
+ if(GyroDeg[1]<90 && GyroDeg[0]>270) GyroDeg[1]+=360;
+ /* 0→359を跨いだ時,前回の値を360以上の値で表記 */
+ else if(GyroDeg[1]>270 && GyroDeg[0]<90) GyroDeg[1]-=360;
+ /* 差を求める*/
+ disp[2]=GyroDeg[1]-GyroDeg[0];
+ }
+ /* Enc2つの差分求める */
+ for(int i=0; i<2; i++) {
+ EncDeg[i][1]=EncDeg[i][0];
+ EncDeg[i][0]=EncoderDeg[i];
+ disp[i]=DEG_TO_DIS(EncDeg[i][1]-EncDeg[i][0]);
+ }
+ /* 差分を加速度として保存 */
+ NowAcc.theta = disp[2];
+ NowAcc.X = -disp[0] * cos(DEG_TO_RAD(NowLoc.theta)) - disp[1] * sin(DEG_TO_RAD(NowLoc.theta));
+ NowAcc.Y = -disp[0] * sin(DEG_TO_RAD(NowLoc.theta)) + disp[1] * cos(DEG_TO_RAD(NowLoc.theta));
+ /* 差分を累積して現在位置を保存 */
+ NowLoc.X += NowAcc.X;
+ NowLoc.Y += NowAcc.Y;
+ NowLoc.theta += NowAcc.theta;
+}
/*******************************************************************************
@@ -363,9 +337,6 @@
Y=Rest(Y,100);
R=Rest(R,100);
-
-
-
/* オムニ計算結果をtmpに */
int tmp[4]= {0};
@@ -382,75 +353,77 @@
}
-
+/*******************************************************************************
+* @概要 yaw角補整
+* @引数 tar 目標角度
+* @返り値 なし
+*******************************************************************************/
+void CompYaw(void)
+{
+ double r_val = (TarTheta-NowLoc.theta)*4;
+ SubOmuni(0,0, r_val);
+}
/*******************************************************************************
* @概要 OEI式座標追従・P制御
- * @引数 tar_x :目標のx座標
- * @引数 tar_y :目標のy座標
- * @引数 tar_theta:目標角
- * @引数 error :次ステップに進む基準とする距離
+ * @引数 X0,Y0 :直線始点のx,y座標
+ * @引数 X1,Y1 :直線終点のx,y座標
+ * @引数 tar_theta :目標角
+ * @引数 error :次ステップに進む基準とする距離
* @返り値 0(継続) 1(移動完了)
*******************************************************************************/
-int omuni_control(int tar_x, int tar_y, int tar_theta, int error)
+int omuni_control(int X0,int Y0,int X1,int Y1,double tar_theta, int error)
{
- static int log_distance = 0;
- static int be_tar_x = NowLoc.X, be_tar_y = NowLoc.Y;
- static double log_theta = 0;
+
+ /* 最初の角度・移動距離を記録しておく */
+ static int log_distance = 0, log_theta = 0;
static bool dis_flag = 0;
if(dis_flag==0) {
- /* タイマー初期化 */
- Acc_time.reset();
- P_fin.reset();
- /* タイマー始動 */
- Acc_time.start();
- P_fin.start();
- /* 現在角度を記録しておく */
+ /* 現在の角度・移動距離を記録しておく */
log_theta = NowLoc.theta;
- /* 現在座標と目標座標との距離を記録しておく */
- log_distance = (int)sqrt(pow((double)tar_x - NowLoc.X, 2.0) + pow((double)tar_y - NowLoc.Y, 2.0));
+ log_distance = sqrt(pow((double)X1 - NowLoc.X, 2.0) + pow((double)Y1 - NowLoc.Y, 2.0))-error;
/* フラグ回収 */
dis_flag=1;
}
- int x_val = 0, x_dec_val = 0;
- int y_val = 0, y_dec_val = 0;
- int t_val = 0;
+ /* 線の始点代入 */
+ double start[2] = {X0,Y0};
+ /* 線の終点代入 */
+ double end[2] = {X1,Y1};
+ /* 探査円の中心と半径代入 */
+ double circle[3] = {
+ NowLoc.X,NowLoc.Y,
+ sqrt(pow(NowAcc.X,2)+pow(NowAcc.Y,2)) * 1.5
+ };
- double theta_tar = 0.0;
- double start[2] = {0}, end[2] = {0}, circle[3] = {0}, P_tar[2] = {0};
-
- /* 線の始点代入 */
- start[0] = be_tar_x;
- start[1] = be_tar_y;
- /* 線の終点代入 */
- end[0] = tar_x;
- end[1] = tar_y;
- /* 探査円の中心と半径代入 */
- circle[0] = NowLoc.X;
- circle[1] = NowLoc.Y;
- circle[2] = sqrt(pow(NowAcc.X,2)+pow(NowAcc.Y,2)) * 1.5;
- /* 半径の制限 */
- circle[2] = Rest(circle[2], 100);
-
+ /* 残り距離計算 */
+ double remain = (int)sqrt(pow((double)X1 - NowLoc.X, 2.0) + pow((double)Y1 - NowLoc.Y, 2.0));
+
+ /* 探査円半径を残り距離以下に */
+ if(circle[2]>remain)
+ circle[2]=remain;
+
+ /* 探査円と経路直線との交点 */
+ double P_tar[2] = {0};
+
/* 目標点の探索、代入 */
lncl(start, end, circle, P_tar);
-
- /* 減速処理の値代入 */
- x_dec_val = ABS((P_tar[0] - NowLoc.X) * 0.06);
- y_dec_val = ABS((P_tar[1] - NowLoc.Y) * 0.06);
- x_val = x_dec_val;
- y_val = y_dec_val;
+
+
+ /* X,Y,Rそれぞれの操作量 */
+ double x_val = 0,y_val = 0;
- /* 最低を決める */
- x_val = M_MAX(x_val, 20);
- y_val = M_MAX(y_val, 20);
+ /* 減速処理の値代入 */
+ x_val = ABS(P_tar[0] - NowLoc.X) * 0.06;
+ y_val = ABS(P_tar[1] - NowLoc.Y) * 0.06;
- /* 100以内に収める */
- x_val = Rest(x_val, 100);
- y_val = Rest(y_val, 100);
+ /* 最低・最高を決める */
+ x_val = M_MAX(x_val, 20);
+ x_val = M_MIN(x_val, 100);
+ y_val = M_MAX(y_val, 20);
+ y_val = M_MIN(y_val, 100);
/* 正負を決める */
if ((P_tar[0] - NowLoc.X) < 0)
@@ -458,44 +431,23 @@
if ((P_tar[1] - NowLoc.Y) < 0)
y_val *= -1;
- /* 残り距離計算 */
- int remain = (int)sqrt(pow((double)tar_x - NowLoc.X, 2.0) + pow((double)tar_y - NowLoc.Y, 2.0));
- /* 移動量に応じたthetaを求める */
- theta_tar = (((double)log_distance - remain) / log_distance) * (tar_theta - log_theta) + log_theta;
- /* 合わせるthetaと現在thetaの差分からtheta補整をかける */
- t_val = (theta_tar - NowLoc.theta) * 1.5;
-
- t_val = Rest(t_val, 20);
-
- SubOmuni(x_val, y_val, t_val);
-
- /* 終了処理 */
- if(error != 0 && error >= remain) {
- be_tar_x = tar_x;
- be_tar_y = tar_y;
- return 1;
- } else if ((5 > ABS(remain)) && ABS(tar_theta - NowLoc.theta) < 0.1) {
- x_val = 0;
- y_val = 0;
- }
- if (x_val == 0 && y_val == 0)
- P_fin.start();
- else
- P_fin.reset();
-
- if (P_fin.read_ms() > 100) {
- /* タイマー停止 */
- P_fin.stop();
- /* フラグを建て直す */
- dis_flag=0;
-
- return 1;
- }
- return 0;
-}
+ /* オムニ計算 */
+ SubOmuni(x_val, y_val,0);
+ /* 移動量に応じたその瞬間の合わせるthetaを求める */
+ TarTheta = (((double)log_distance - (remain - error)) / log_distance) * (tar_theta - log_theta) + log_theta;
+ /* thetaに合わせる */
+ CompYaw();
+ /* 残り距離がほぼないなら終了 */
+ if(ABS(error - remain)<3) {
+ /* Theta基準値を最終に */
+ TarTheta=tar_theta;
+ return 0;
+ }
+ return remain;
+}
/*******************************************************************************
@@ -513,30 +465,21 @@
double fygx, fxgy, t, fginv, t1, t2, x1, y1, x2, y2, sqdst1, sqdst2;
double accy = 1.0E-15;
-
-
-
/* X,Yそれぞれの変化量 */
double xlk = pt2[0] - pt1[0];
double ylk = pt2[1] - pt1[1];
/* 偏差 */
double rsq = sqrt(pow(xlk, 2.0) + pow(ylk, 2.0));
-
-
/* 0の除算時異常終了 */
if (rsq < accy) return (-1);
double rinv = 1.0 / rsq;
-
-
/* ax+by+cの式の係数をそれぞれ */
a = -ylk * rinv;
b = xlk * rinv;
c = (pt1[0] * pt2[1] - pt2[0] * pt1[1]) * rinv;
-
-
/* rootは1になる */
root = 1.0 / (a * a + b * b);
/* 直線の法線ベクトルと直線上の点の位置ベクトルとの内積 */
@@ -553,16 +496,11 @@
/* 2つの合成 */
fgsq = fsq + gsq;
-
-
-
xjo = xyr[0] - xo;
yjo = xyr[1] - yo;
fygx = f * yjo - g * xjo;
root = xyr[2] * xyr[2] * fgsq - fygx * fygx;
-
-
/* 2つの関数が近い 3点で接する時異常終了 */
if (fgsq < accy) return (3);
/* 円と線が接さない 0点で接する時異常終了 */
@@ -594,8 +532,7 @@
if (sqdst1 < sqdst2) {
xy[0] = x1;
xy[1] = y1;
- }
- else {
+ } else {
xy[0] = x2;
xy[1] = y2;
}