1

超音波センサーを取り付けたNXTロボットを作ろうとしています。距離が 15 になるまで走行し、その後エンジンを停止する必要があります。止まったら回さなければいけませんが、動きません。

import lejos.nxt.*;

public class test {
    public static void main(String [] args) throws InterruptedException {
        UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
        for (int i = 0; i < 5; i++) {       
            try {
                Motor.B.rotate(-1500 , true);
                Motor.C.rotate(-1500 , true);
            } catch (Exception E){}

            while ( ultra.getDistance() < 15 ) {
                Motor.B.backward();
                Motor.C.backward();
            }

            LCD.clear();
            LCD.drawString("Distance : "+ultra.getDistance(), 0, 0);
        } 

        Button.waitForAnyPress();
    }
}

私の古いコードも機能しませんでした:

import lejos.nxt.*;

public class test {

public static void main(String [] args) throws InterruptedException {
    UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
    try {
        Motor.B.rotate(-720);
        Motor.C.rotate(-720);

         } catch (Exception E){}

    for (int i = 0; i < 5; i++)
    {
    LCD.drawString("Distance : "+ultra.getDistance(), 0, i);
              Thread.sleep(2000);
         int maxDistance = ultra.getDistance();
         if (maxDistance < 15){
             Motor.B.stop();
             Motor.C.stop();
         }
    }
    Button.waitForAnyPress();
}
}
4

1 に答える 1

4

仮定

さて、見た目からすると、あなたのコードはおそらくあなたが望んでいることをしていません。(今後、スタック オーバーフローに関する質問を書くときは、予想される動作と、どのような誤った動作が見られるかを詳細に明確にしてください。とにかく、これらは通常、私たちが最初に尋ねる 2 つの質問です。)

まず最初に、B と C に 2 つのモーター、S1 にセンサーを配置して、NXT キットが適切にセットアップされていることを確認する必要があります。その場合は、読み続けてください。

コードの解釈

モーターコマンド:

try {
    Motor.B.rotate(-1500, true);
    Motor.C.rotate(-1500, true);
} catch (Exception E) {}

有効なモーター コマンドのように見えますが、ちょっと待ってください! モーターが反対方向を指す 2 つの車輪に接続された二輪ロボットを使用していますか? しかし、モーターの制限角度に同じ距離と方向を使用しています! 車輪が互いに反対になっている場合、これはロボットを円を描くように回転させるだけです。

注:コメントに書かれているように、モーターは適切に構成されているため、この部分は無視してください。

ロボットが円を描くように回転する

プラスをマイナスに変更してモーターの 1 つの方向を変更すると、両方が同時に動作して、ロボットを前進させます (間違ったものを変更すると、後退します!)。

trueまた、 2 番目の引数として渡すことに注意してください。

Motor.B.rotate(-1500, true);
Motor.C.rotate(-1500, true);

Javadoc によると、この関数は非常に具体的な方法で作成されます(強調鉱山):

immediateReturnが true の場合、メソッドはすぐに戻り、モーターは自動的に停止します

制限に達する前にいずれかのモーター メソッドが呼び出されると、回転がキャンセルされます。

最初の文は、これが私たちのやりたいことを実行することを意味します。これは、モーターに正しい限界角度を自分で見つけるように指示しますが、プログラムにそれを待たせません。ただし、2 番目の文は、他のモーター コマンドが呼び出されると、指定された制限角度まで移動を停止することを意味します。はい、そのとおり。これらの次の数行は、モーターの動きを止めて、代わりにモーターの言うことを実行します。

さて、このコードには次の 2 つの理由で問題があります。

while (ultra.getDistance() < 30) {
    Motor.B.backward();
    Motor.C.backward();
}

まず、これらのコマンドは、前の 2 つのモーター コマンドの実行を即座に停止します。これは、基本的に、モーターがまっすぐにジャンプして「後退」し、距離センサーが と等しいかそれ以上になるまでループすることを意味し30ます。これは実際に私たちが望んでいるものですが、もう少し必要です...

第二に、センサーが より大きい距離を読み取った後、30モーターが停止するように指示されることはありません! したがって、プログラムが距離を表示していて、ボタンが押されるのを待っている場合でも、プログラムはまだ動いています!

解決策

さて、変更する必要があることがいくつかあります。

  • 最初のモーター コマンドは、正しい位置に移動するよう指示するその後のコマンドによってブロックされています。
  • モーターは停止するべきときに停止しません。

以下は、これらの問題のそれぞれに対処するために編集されたコードです。変更内容を示すために、変更を行った場所にメモを含めました。

import lejos.nxt.*;

public class test {
    public static void main(String [] args) throws InterruptedException {
        UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
        for (int i = 0; i < 5; i++) {

            // No initial motor movement (because it did nothing anyway)

            // We change this to approach from either direction.
            while (ultra.getDistance() != 30) {
                // Check whether it's behind or ahead of it.
                // Assuming that B- and C- increase distance, and B+ and C+ decrease it (depends on robot configuration).
                // This is called a feedback loop, by the way.
                if (ultra.getDistance() < 30) { // Move forward (distance+)
                    Motor.B.backward();
                    Motor.C.backward();
                } else { // Move backward (distance-)
                    Motor.B.forward();
                    Motor.C.forward();
                }
            }

            // We only get here when the distance is right, so stop the motors.
            Motor.B.stop();
            Motor.C.stop();               

            LCD.clear();
            LCD.drawString("Distance : "+ultra.getDistance(), 0, 0);
        }
        Button.waitForAnyPress();
    }
}

さて、このコードは完全ではありません。滑りやすい路面では前方と後方の間で振動する傾向がある (適用されるトルクの違いにより、左右にわずかに回転する可能性があります)、またはセンサーが正しい位置を逃してロボットがオーバーシュートする場合があります。

このコードは、センサーが最初に正しい位置を報告するまで、ロボットが指定された位置で安定するまで待機しません。繰り返しになりますが、ホイールの牽引力が適切でない場合、モーターがスムーズに加速するように設定されている場合、またはモーターの速度が速すぎる場合は、少し滑る可能性があります。

これらの欠陥を修正するには、加速とスリップを考慮したより高度なタイプのフィードバック ループが必要であり、モーターを停止する前に、ロボットが正しい位置で短時間安定するまで待つ必要があります。

ただし、これにより、いわば正しい方向に進むはずです。

編集コメントで指定されているように、ドライブモーターの方向性を修正しました。

于 2015-09-22T14:30:08.440 に答える