2013b/Member/michaegon/Mission1
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
目次
#contents
*課題1内容 [#vb71dca6]
>自作したコースに沿って一周するするロボットを作成せよ。
>
>ただし、次の点に注意すること
>
>一人は時計回り用、もう一人は半時計回うり用のプログラムを...
>次のステップでプログラムを作成すること。
>交差点をきちんと認識し、正しく判断して通過できるようにす...
>確実に一周できるようにする。スタート地点から出発して元に...
>空き缶を交差点から10cm以上離した線上に起き、それを一旦ど...
>1個の空き缶でうまくいったら、2個の空き缶でやってみる。
以上[[2013b/Mission1]]より引用
&aname(map);
コース図
#ref(coi.jpg);
*メンバー [#zab397a9]
[[dyuma>2013b/Member/dyuma/Mission1]]~
ロボット製作(+ロボット管理)・プログラミングとどちらもこ...
[[pepo>2013b/Member/pepo/Mission1]]~
ロボットを組ませたら彼の右に出るものはいない。(ただし情...
michaegon~
このページの著者~
プログラムの方をやってます。
*ロボット概要 [#t8caacae]
今回の課題にあたってチームで使ったロボットの前面には、ラ...
**アーム [#caac7b24]
#ref(robot.jpg);
今回使ったアームは、物をつかむよりは確実性があるだろうと...
普段のアームは上図のようにおりている状態ではなく、上がっ...
**光センサー [#wd2ba5d2]
#ref(light.jpg);
ライントレース用の光センサーは設置位置に気を配りました。~
説明書に書いてある通りに作ったロボットだと、光センサーの...
今回はタイヤの軸に極力光センサーを近づけて、ロボットの構...
以下では右タイヤをモーターB、左タイヤをモーターC、アーム...
*プログラム概要 [#u38c8111]
ここでは、このページの著者michaegonが作成したプログラムの...
他メンバーが作成したプログラムについては他メンバーのペー...
**PID_4.1.nxc(ライントレース用) [#bea8657d]
#define KP 1.55 // 比例ゲイン
#define KI 0.00005// 積分ゲイン
#define KD 0.85// 微分ゲイン
#define DT 1
#define THRESHOLD 50 // 閾値
#define SPEED1 40 // 高速
#define SPEED2 25 // 低速
#define GO(s,t) OnFwdSync(OUT_BC,s,t); Wait(DT);
#define JUDGE_T 2500 // ギアチェンジ基準時間
float pid;
int result;
int dev[2]; // 偏差
long time;
int flag;
float integral;
/*?*/
inline int ope_amount(int sensor)
{
dev[0]=dev[1]; // 過去のセンサー値と閾値の差
dev[1]=sensor-THRESHOLD; // 現在のセンサー値と閾値の差
if (dev[1]==dev[0]) { // もしセンサー値の変化がない場合...
integral=0;
}
integral+=(dev[1]+dev[0])*DT/2.0; // 積分を計算する
pid=KP*dev[1]+KI*integral+KD*(dev[1]-dev[0])/DT;
if (-100>pid) {
result=-100;
} else if (100<pid) {
result=100;
} else {
result=pid;
}
return result; // -100から100の間でシンクロ率を返す
}
/*?*/
task gearchange()
{
time=CurrentTick();
until (SENSOR_1<=THRESHOLD || CurrentTick()-time>=JUDGE...
if (CurrentTick()-time>=JUDGE_T) {
flag=1;
} else {
flag=2;
}
}
task main()
{
SetSensorLight(S1);
// 低速版
while (true) { // 左エッジ用
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_UP);
break;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
Low:
GO(SPEED2,ope_amount(SENSOR_1));
}
// 高速用
while (true) { // 左エッジ
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_DOWN);
goto Low;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
GO(SPEED1,ope_amount(SENSOR_1));
}
}
※このプログラムは時計回りライントレース用です。
***経緯・基本方針 [#f7c7d47f]
PID_4.1.nxcはメンバーの[[dyuma>#zab397a9]]の、設定した閾...
/*
閾値と光センサーの値の差によってカーブ量を決めるプログラム
時計回りライントレース用
*/
#define SPEED 30 // 前進スピード
#define THRESHOLD 50 // 閾値
#define turn_right(s) OnFwd(OUT_C,SPEED); OnRev(OUT_B,s)...
#define turn_left(s) OnFwd(OUT_B,SPEED); OnRev(OUT_C,s);...
task main()
{
SetSensorLight(S1);
int back; // 逆回転する方のタイヤのスピード
while (true) {
while (SENSOR_1<THRESHOLD) { // ロボットがライン上に...
back=THRESHOLD-SENSOR_1; // 閾値とセンサー実測値の...
turn_right(back); // ライン上にいるときは右に曲がる
Wait(1);
}
while (SENSOR_1>=THRESHOLD) { // ロボットがライン外に...
back=SENSOR_1-THRESHOLD;
turn_left(back); // ライン外にいるときは左に曲がる
Wait(1);
}
}
}
このプログラムには、まっすぐ進めず走行がジグザグになり滑...
何か解決策はないか調べていたところ、見つけたのが"PID制御"...
>PID制御(ピーアイディーせいぎょ = Proportional Integral D...
「PID制御」『フリー百科事典 ウィキペディア日本語版』(htt...
今回は、操作量をope、変数x,y,z、定数Kp(比例ゲインという...
#ref(tex1.jpg)
PID_4.1.nxcでは、OnFwdSyncに用いるモーターの同期(シンク...
&ruby(Proportional){比例};(P)制御では、比例ゲインKpと、閾...
ロボットの現在位置が閾値(今回はラインの境界上)から離れ...
&ruby(Integral){積分};(I)制御では、積分ゲインKiと、過去の...
比例(P)制御だけでは、ロボットが閾値近辺を進んでいる時は操...
&ruby(Derivative){積分};(D)制御では、微分ゲインKdと、光セ...
***KP,KI,KDの決定方法 [#h5ec5df1]
比例ゲインKP,積分ゲインKI,微分ゲインKDの最適な値を見つけ...
今回は限界感度法を試してみました。
限界感度法では、まずはじめにKI=KD=0としてP制御だけで走行...
このときKPの値を徐々に増やしていって、ロボットが持続的に...
このときのロボットの振動周期をTuとおいて、Ku,TuからPID制...
このようにうまく限界感度法が使えればよかったのですが、実...
そもそもKPの値をいくら大きくしても振動が持続せずにすぐに...
ということで今回は初めから手作業で値を決めました。~
PID制御の中でメインになるのはP制御で、ID制御はP制御の補助...
次に、I制御を加えてカーブを走行させます。I制御では若干の...
最後のD制御は、急激なコース変化に対応させるためのもので、...
***? inline関数ope_amount [#k44c6886]
/*PID_4.1.nxcの一部*/
#define KP 1.55 // 比例ゲイン
#define KI 0.00005// 積分ゲイン
#define KD 0.85// 微分ゲイン
#define DT 1
#define THRESHOLD 50 // 閾値
float pid;
int result;
int dev[2];
float integral;
inline int ope_amount(int sensor)
{
dev[0]=dev[1]; // 過去の偏差
dev[1]=sensor-THRESHOLD; // 現在の偏差
if (dev[1]==dev[0]) { // もし偏差変化がない場合はintegr...
integral=0;
}
integral+=(dev[1]+dev[0])*DT/2.0; // 積分を計算する
pid=KP*dev[1]+KI*integral+KD*(dev[1]-dev[0])/DT;
if (-100>pid) {
result=-100;
} else if (100<pid) {
result=100;
} else {
result=pid; // int型にキャスト
}
return result;
}
KPは比例ゲイン、KIは積分ゲイン、KPは微分ゲイン、DTは光セ...
dev[0]には1ミリ秒前の光センサーの値と閾値の差(偏差)、de...
次はI制御のための準備です。integralには、1ミリ秒ごとに(de...
#ref(integral.jpg)
このとき、integralに偏差が蓄積し続けると、I制御での補正が...
浮動小数点pidには、PID制御によって決定した操作量を入れま...
ここで、~
Kp*dev[1]はP制御、~
Ki*integralはI制御、~
また、DTを微小時間とみなして光センサー値推移のグラフの傾...
Kd*(dev[1]-dev[0])/DTはD制御による操作量を表しています。
#ref(d.jpg),left
上で求めたpidをOnFwdSyncのシンクロ率(範囲は-100から100ま...
***? メインタスク・サブタスクgearchange [#f48902aa]
/*PID_4.1.nxcの一部*/
#define THRESHOLD 50 // 閾値
#define SPEED1 40 // 高速
#define SPEED2 25 // 低速
#define GO(s,t) OnFwdSync(OUT_BC,s,t); Wait(DT);
#define JUDGE_T 2500 // ギアチェンジ基準時間
int flag;
task gearchange()
{
time=CurrentTick();
until (SENSOR_1<=THRESHOLD || CurrentTick()-time>=JUDGE...
if (CurrentTick()-time>=JUDGE_T) {
flag=1;
} else {
flag=2;
}
}
task main()
{
SetSensorLight(S1);
// 低速走行ループ
while (true) { // 左エッジ用
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_UP);
break;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
Low:
GO(SPEED2,ope_amount(SENSOR_1));
}
// 高速走行ループ
while (true) { // 左エッジ
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_DOWN);
goto Low;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
GO(SPEED1,ope_amount(SENSOR_1));
}
}
もともとのメインタスクは、~
task main()
{
while (true) {
GO(SPEED1,ope_amount(SENSOR_1));
}
}
だけでした。これでもライントレースはできるのですが、交差...
交差点を直線だと認識して通過してくれるのはありがたいので...
このプログラムを実行させると、まずは低速でライントレース...
このループにいる限り、ロボットは交差点もT字路もカーブと判...
よって、初めのT字路は無事に曲がることができますが、このま...
さて、初めのT字路を、左に曲がった場合は次に直角カーブの外...
このとき、どうしてもロボットはラインよりも若干大回りにな...
この現象は、比例ゲインなどを適切な値にしておけば、今回の...
低速ライントレースのループ中で、光センサーの値が閾値より...
サブタスクgearchangeは、以下の動作をします。
+光センサーの値が閾値より大きくなっている(ロボットがライ...
+もし光センサーの値が閾値より大きかった時間が、~
JUDGE_T以上だった場合は、flagに1を代入~
JUDGE_T以下だった場合はflagに2を代入
すると、メインタスク内のif文が実行されます。このif文では、
+サブタスクgearchangeを停止させる
+flagを0に戻す
+gearchangeで~
flagに1が代入されていた(ロボットがJUDGE_T以上ライン外に...
flagに2が代入されていた(ロボットがJUDGE_Tに達する前にラ...
この機能は高速ライントレースのループにも搭載されています。
ここで、ロボットがコースを時計回りにライントレースさせて...
+低速走行で始まり、初めのT字路を左に曲がる
+次の直角カーブの外側を回る~
このとき、JUDGE_T以上ラインから外れてロボットが回るので、...
+高速走行中では、交差点やT字路を直線と判断して通過してい...
+2つめの交差点を抜けてヘアピンカーブの外側を回る部分に差...
カーブの曲がり具合に追いつけずJUDGE_T以上ロボットがライン...
+その後差し掛かるT字路は低速走行中なのでカーブ判定して曲...
このようにコースを一周できました。
ちなみに、
GO(SPEED2,ope_amount(SENSOR_1));
GO(SPEED1,ope_amount(SENSOR_1));
の部分を、
GO(SPEED2,-ope_amount(SENSOR_1));
GO(SPEED1,-ope_aount(SENSOR_1));
に変えるだけで反時計周りのライントレースもできました。
**can_move.nxc(缶移動関連) [#p5edb615]
/*
定義部
*/
#define SPEED1 40
#define SPIN RotateMotorEx(OUT_BC,100,180,100,true,true)...
#define CATCH(s) RotateMotor(OUT_A,s,180); Wait(2000); O...
/*
関数
*/
inline void can_move()
{
Float(OUT_BC);
Wait(100);
Off(OUT_BC);
CATCH(100); // 缶をつかんだ状態
RotateMotorEx(OUT_BC,SPEED1,1080,0,true,true); // 若干...
Wait(100);
Off(OUT_BC);
/*
旋回
回転角は適宜変更してください
*/
SPIN;
CATCH(-100);
/*
旋回
回転角は適宜変更を
*/
SPIN;
}
/*
task main内組み込み用
*/
task main()
{
SetSensorLowspeed(S2);
if (SensorUS(S2)<=10) {
can_move();
}
}
※実際にはこれをPID_4.1.nxcに組み込んで使用します。
***基本方針 [#naba760e]
ライントレース中に前方に缶があるとき、超音波センサーで測...
***inline関数can_move [#mdaee0c0]
缶との距離が10cmになったらFloatで止まらせます。SPEED1が40...
完全に止まったら、アームをおろして缶を抱え込みます。その...
その後にもう1度その場で旋回して前を向いて、本来のライン...
*反省点・改善点 [#p4525d91]
PID制御に使うKP,KI,KDの最適な値を求めるのが難しかったです...
調べていると求め方があったのですが、なかなかその方法を使...
結局手探りで値探しをすることになってしまってずいぶん時間...
今後は1から手探りにならないような方法を探して、適切な値...
チームとしては[[dyuma>#zab397a9]]が缶を動かすプログラムの...
ただ、個人的には、PIDの方でKP,KI,KDの値探しに時間をかけす...
終了行:
目次
#contents
*課題1内容 [#vb71dca6]
>自作したコースに沿って一周するするロボットを作成せよ。
>
>ただし、次の点に注意すること
>
>一人は時計回り用、もう一人は半時計回うり用のプログラムを...
>次のステップでプログラムを作成すること。
>交差点をきちんと認識し、正しく判断して通過できるようにす...
>確実に一周できるようにする。スタート地点から出発して元に...
>空き缶を交差点から10cm以上離した線上に起き、それを一旦ど...
>1個の空き缶でうまくいったら、2個の空き缶でやってみる。
以上[[2013b/Mission1]]より引用
&aname(map);
コース図
#ref(coi.jpg);
*メンバー [#zab397a9]
[[dyuma>2013b/Member/dyuma/Mission1]]~
ロボット製作(+ロボット管理)・プログラミングとどちらもこ...
[[pepo>2013b/Member/pepo/Mission1]]~
ロボットを組ませたら彼の右に出るものはいない。(ただし情...
michaegon~
このページの著者~
プログラムの方をやってます。
*ロボット概要 [#t8caacae]
今回の課題にあたってチームで使ったロボットの前面には、ラ...
**アーム [#caac7b24]
#ref(robot.jpg);
今回使ったアームは、物をつかむよりは確実性があるだろうと...
普段のアームは上図のようにおりている状態ではなく、上がっ...
**光センサー [#wd2ba5d2]
#ref(light.jpg);
ライントレース用の光センサーは設置位置に気を配りました。~
説明書に書いてある通りに作ったロボットだと、光センサーの...
今回はタイヤの軸に極力光センサーを近づけて、ロボットの構...
以下では右タイヤをモーターB、左タイヤをモーターC、アーム...
*プログラム概要 [#u38c8111]
ここでは、このページの著者michaegonが作成したプログラムの...
他メンバーが作成したプログラムについては他メンバーのペー...
**PID_4.1.nxc(ライントレース用) [#bea8657d]
#define KP 1.55 // 比例ゲイン
#define KI 0.00005// 積分ゲイン
#define KD 0.85// 微分ゲイン
#define DT 1
#define THRESHOLD 50 // 閾値
#define SPEED1 40 // 高速
#define SPEED2 25 // 低速
#define GO(s,t) OnFwdSync(OUT_BC,s,t); Wait(DT);
#define JUDGE_T 2500 // ギアチェンジ基準時間
float pid;
int result;
int dev[2]; // 偏差
long time;
int flag;
float integral;
/*?*/
inline int ope_amount(int sensor)
{
dev[0]=dev[1]; // 過去のセンサー値と閾値の差
dev[1]=sensor-THRESHOLD; // 現在のセンサー値と閾値の差
if (dev[1]==dev[0]) { // もしセンサー値の変化がない場合...
integral=0;
}
integral+=(dev[1]+dev[0])*DT/2.0; // 積分を計算する
pid=KP*dev[1]+KI*integral+KD*(dev[1]-dev[0])/DT;
if (-100>pid) {
result=-100;
} else if (100<pid) {
result=100;
} else {
result=pid;
}
return result; // -100から100の間でシンクロ率を返す
}
/*?*/
task gearchange()
{
time=CurrentTick();
until (SENSOR_1<=THRESHOLD || CurrentTick()-time>=JUDGE...
if (CurrentTick()-time>=JUDGE_T) {
flag=1;
} else {
flag=2;
}
}
task main()
{
SetSensorLight(S1);
// 低速版
while (true) { // 左エッジ用
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_UP);
break;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
Low:
GO(SPEED2,ope_amount(SENSOR_1));
}
// 高速用
while (true) { // 左エッジ
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_DOWN);
goto Low;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
GO(SPEED1,ope_amount(SENSOR_1));
}
}
※このプログラムは時計回りライントレース用です。
***経緯・基本方針 [#f7c7d47f]
PID_4.1.nxcはメンバーの[[dyuma>#zab397a9]]の、設定した閾...
/*
閾値と光センサーの値の差によってカーブ量を決めるプログラム
時計回りライントレース用
*/
#define SPEED 30 // 前進スピード
#define THRESHOLD 50 // 閾値
#define turn_right(s) OnFwd(OUT_C,SPEED); OnRev(OUT_B,s)...
#define turn_left(s) OnFwd(OUT_B,SPEED); OnRev(OUT_C,s);...
task main()
{
SetSensorLight(S1);
int back; // 逆回転する方のタイヤのスピード
while (true) {
while (SENSOR_1<THRESHOLD) { // ロボットがライン上に...
back=THRESHOLD-SENSOR_1; // 閾値とセンサー実測値の...
turn_right(back); // ライン上にいるときは右に曲がる
Wait(1);
}
while (SENSOR_1>=THRESHOLD) { // ロボットがライン外に...
back=SENSOR_1-THRESHOLD;
turn_left(back); // ライン外にいるときは左に曲がる
Wait(1);
}
}
}
このプログラムには、まっすぐ進めず走行がジグザグになり滑...
何か解決策はないか調べていたところ、見つけたのが"PID制御"...
>PID制御(ピーアイディーせいぎょ = Proportional Integral D...
「PID制御」『フリー百科事典 ウィキペディア日本語版』(htt...
今回は、操作量をope、変数x,y,z、定数Kp(比例ゲインという...
#ref(tex1.jpg)
PID_4.1.nxcでは、OnFwdSyncに用いるモーターの同期(シンク...
&ruby(Proportional){比例};(P)制御では、比例ゲインKpと、閾...
ロボットの現在位置が閾値(今回はラインの境界上)から離れ...
&ruby(Integral){積分};(I)制御では、積分ゲインKiと、過去の...
比例(P)制御だけでは、ロボットが閾値近辺を進んでいる時は操...
&ruby(Derivative){積分};(D)制御では、微分ゲインKdと、光セ...
***KP,KI,KDの決定方法 [#h5ec5df1]
比例ゲインKP,積分ゲインKI,微分ゲインKDの最適な値を見つけ...
今回は限界感度法を試してみました。
限界感度法では、まずはじめにKI=KD=0としてP制御だけで走行...
このときKPの値を徐々に増やしていって、ロボットが持続的に...
このときのロボットの振動周期をTuとおいて、Ku,TuからPID制...
このようにうまく限界感度法が使えればよかったのですが、実...
そもそもKPの値をいくら大きくしても振動が持続せずにすぐに...
ということで今回は初めから手作業で値を決めました。~
PID制御の中でメインになるのはP制御で、ID制御はP制御の補助...
次に、I制御を加えてカーブを走行させます。I制御では若干の...
最後のD制御は、急激なコース変化に対応させるためのもので、...
***? inline関数ope_amount [#k44c6886]
/*PID_4.1.nxcの一部*/
#define KP 1.55 // 比例ゲイン
#define KI 0.00005// 積分ゲイン
#define KD 0.85// 微分ゲイン
#define DT 1
#define THRESHOLD 50 // 閾値
float pid;
int result;
int dev[2];
float integral;
inline int ope_amount(int sensor)
{
dev[0]=dev[1]; // 過去の偏差
dev[1]=sensor-THRESHOLD; // 現在の偏差
if (dev[1]==dev[0]) { // もし偏差変化がない場合はintegr...
integral=0;
}
integral+=(dev[1]+dev[0])*DT/2.0; // 積分を計算する
pid=KP*dev[1]+KI*integral+KD*(dev[1]-dev[0])/DT;
if (-100>pid) {
result=-100;
} else if (100<pid) {
result=100;
} else {
result=pid; // int型にキャスト
}
return result;
}
KPは比例ゲイン、KIは積分ゲイン、KPは微分ゲイン、DTは光セ...
dev[0]には1ミリ秒前の光センサーの値と閾値の差(偏差)、de...
次はI制御のための準備です。integralには、1ミリ秒ごとに(de...
#ref(integral.jpg)
このとき、integralに偏差が蓄積し続けると、I制御での補正が...
浮動小数点pidには、PID制御によって決定した操作量を入れま...
ここで、~
Kp*dev[1]はP制御、~
Ki*integralはI制御、~
また、DTを微小時間とみなして光センサー値推移のグラフの傾...
Kd*(dev[1]-dev[0])/DTはD制御による操作量を表しています。
#ref(d.jpg),left
上で求めたpidをOnFwdSyncのシンクロ率(範囲は-100から100ま...
***? メインタスク・サブタスクgearchange [#f48902aa]
/*PID_4.1.nxcの一部*/
#define THRESHOLD 50 // 閾値
#define SPEED1 40 // 高速
#define SPEED2 25 // 低速
#define GO(s,t) OnFwdSync(OUT_BC,s,t); Wait(DT);
#define JUDGE_T 2500 // ギアチェンジ基準時間
int flag;
task gearchange()
{
time=CurrentTick();
until (SENSOR_1<=THRESHOLD || CurrentTick()-time>=JUDGE...
if (CurrentTick()-time>=JUDGE_T) {
flag=1;
} else {
flag=2;
}
}
task main()
{
SetSensorLight(S1);
// 低速走行ループ
while (true) { // 左エッジ用
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_UP);
break;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
Low:
GO(SPEED2,ope_amount(SENSOR_1));
}
// 高速走行ループ
while (true) { // 左エッジ
if (flag==1) {
stop gearchange;
flag=0;
PlaySound(SOUND_DOWN);
goto Low;
} else if (flag==2) {
stop gearchange;
flag=0;
}
if (SENSOR_1>THRESHOLD) {
start gearchange;
}
GO(SPEED1,ope_amount(SENSOR_1));
}
}
もともとのメインタスクは、~
task main()
{
while (true) {
GO(SPEED1,ope_amount(SENSOR_1));
}
}
だけでした。これでもライントレースはできるのですが、交差...
交差点を直線だと認識して通過してくれるのはありがたいので...
このプログラムを実行させると、まずは低速でライントレース...
このループにいる限り、ロボットは交差点もT字路もカーブと判...
よって、初めのT字路は無事に曲がることができますが、このま...
さて、初めのT字路を、左に曲がった場合は次に直角カーブの外...
このとき、どうしてもロボットはラインよりも若干大回りにな...
この現象は、比例ゲインなどを適切な値にしておけば、今回の...
低速ライントレースのループ中で、光センサーの値が閾値より...
サブタスクgearchangeは、以下の動作をします。
+光センサーの値が閾値より大きくなっている(ロボットがライ...
+もし光センサーの値が閾値より大きかった時間が、~
JUDGE_T以上だった場合は、flagに1を代入~
JUDGE_T以下だった場合はflagに2を代入
すると、メインタスク内のif文が実行されます。このif文では、
+サブタスクgearchangeを停止させる
+flagを0に戻す
+gearchangeで~
flagに1が代入されていた(ロボットがJUDGE_T以上ライン外に...
flagに2が代入されていた(ロボットがJUDGE_Tに達する前にラ...
この機能は高速ライントレースのループにも搭載されています。
ここで、ロボットがコースを時計回りにライントレースさせて...
+低速走行で始まり、初めのT字路を左に曲がる
+次の直角カーブの外側を回る~
このとき、JUDGE_T以上ラインから外れてロボットが回るので、...
+高速走行中では、交差点やT字路を直線と判断して通過してい...
+2つめの交差点を抜けてヘアピンカーブの外側を回る部分に差...
カーブの曲がり具合に追いつけずJUDGE_T以上ロボットがライン...
+その後差し掛かるT字路は低速走行中なのでカーブ判定して曲...
このようにコースを一周できました。
ちなみに、
GO(SPEED2,ope_amount(SENSOR_1));
GO(SPEED1,ope_amount(SENSOR_1));
の部分を、
GO(SPEED2,-ope_amount(SENSOR_1));
GO(SPEED1,-ope_aount(SENSOR_1));
に変えるだけで反時計周りのライントレースもできました。
**can_move.nxc(缶移動関連) [#p5edb615]
/*
定義部
*/
#define SPEED1 40
#define SPIN RotateMotorEx(OUT_BC,100,180,100,true,true)...
#define CATCH(s) RotateMotor(OUT_A,s,180); Wait(2000); O...
/*
関数
*/
inline void can_move()
{
Float(OUT_BC);
Wait(100);
Off(OUT_BC);
CATCH(100); // 缶をつかんだ状態
RotateMotorEx(OUT_BC,SPEED1,1080,0,true,true); // 若干...
Wait(100);
Off(OUT_BC);
/*
旋回
回転角は適宜変更してください
*/
SPIN;
CATCH(-100);
/*
旋回
回転角は適宜変更を
*/
SPIN;
}
/*
task main内組み込み用
*/
task main()
{
SetSensorLowspeed(S2);
if (SensorUS(S2)<=10) {
can_move();
}
}
※実際にはこれをPID_4.1.nxcに組み込んで使用します。
***基本方針 [#naba760e]
ライントレース中に前方に缶があるとき、超音波センサーで測...
***inline関数can_move [#mdaee0c0]
缶との距離が10cmになったらFloatで止まらせます。SPEED1が40...
完全に止まったら、アームをおろして缶を抱え込みます。その...
その後にもう1度その場で旋回して前を向いて、本来のライン...
*反省点・改善点 [#p4525d91]
PID制御に使うKP,KI,KDの最適な値を求めるのが難しかったです...
調べていると求め方があったのですが、なかなかその方法を使...
結局手探りで値探しをすることになってしまってずいぶん時間...
今後は1から手探りにならないような方法を探して、適切な値...
チームとしては[[dyuma>#zab397a9]]が缶を動かすプログラムの...
ただ、個人的には、PIDの方でKP,KI,KDの値探しに時間をかけす...
ページ名: