0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[ev3×Java] 複数モーターの制御(メソッド、ランダム、確率、制限時間、配列)

Last updated at Posted at 2020-08-31

この記事はJavaでev3を操作してみたい人のための記事です。
今回はタンクをいろいろな方法で制御していきたいと思います。

目次

0 . 用意するもの
1 . 複数モーターの制御
 1-0 . タンクを前進させるプログラム
 1-1 . メソッドをつくって制御する
 1-2 . 引数を指定できるメソッドをつくる
 1-3 . StopWatchクラスを使うプログラム
 1-4 . メソッドを指定した確率で呼び出すプログラム
 1-5 . 配列を使うプログラム
最後に

0.用意するもの

◯ ev3(タンク)
◯ Lモーター/Mモーター
◯ パソコン(eclipse)
◯ bluetooth
◯ microSD
API Documentation(これをみながら進めていくのがオススメです。)


 

1.複数モーターの制御

1-0 . タンクを前進させるプログラム

◯タンクが5秒間前進して方向転換するプログラムです。
必要なメソッドを並べるだけのシンプルなものですが、順次処理だとうまくいかない部分があるので、工夫が必要です。

tank00.java
//必要なもの(材料)をimportする
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Delay;

//クラスをつくる
public class tank00 {

	//staticメソッドをつくる
    public static void main(String[] args) {

        //インスタンスの生成
        RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
        RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
        //スピードを設定する(単位は[degrees/s])
        l_a.setSpeed(720);
        l_b.setSpeed(720);
        //5秒間前進する
        l_a.forward();
        l_b.forward();
        Delay.msDelay(5000);
        //その場で方向転換する(同時に回転を開始する)
        l_a.rotate(-2160,true);
        l_b.rotate(2160);
        //モータ2つを同時に停止する
        l_a.stop(true);
        l_b.stop();
    }
}

Point : public void rotate(int angle,boolean immediateReturn)
immediateReturn - if true do not wait for the move to complete

rotate()メソッドは第2引数で、その処理の完了を待ってから次の処理を実行するか否かを決定できます。trueにすると、処理の完了を待たずに次の処理を開始します。
これによって、上のプログラムではモーターAとBを両方同時に回転させることができています。


Point : public void stop(boolean immediateReturn)
引数にtrueを指定することによって、モーターを停止させる処理の完了を待たず即座に次の処理を実行することができます。
[参考資料] : Class BaseRegulatedMotor


1-1 . メソッドをつくって制御するプログラム

◯使い回しがしやすいように、メソッドを自分でつくります。

tank01.java
//必要なもの(材料)をimportする
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Delay;

//クラスをつくる
public class tank01 {
	
	//インスタンスの生成
	private final static RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
	private final static RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
	//整数型の変数motorSpeedの定義
	private final static int motorSpeed = 200;
	
	//staticメソッドをつくる
    public static void main(String[] args) {
        //実行するメソッド
        forward();
        turnRight();
        forward();
        stop();
    }

    //メソッドの定義
    public static void forward(){
    	l_a.setSpeed(motorSpeed);
    	l_b.setSpeed(motorSpeed);
    	l_a.forward();
    	l_b.forward();
    	Delay.msDelay(2000);
    }
    //メソッドの定義    
    public static void turnRight(){
    	l_a.setSpeed(motorSpeed);
    	l_b.setSpeed(motorSpeed-100);
    	l_a.forward();
    	l_b.forward();
    	Delay.msDelay(1000);
    }
    //メソッドの定義    
    public static void stop(){
    	l_a.stop(true);
    	l_b.stop();
    }
}

Point : メソッドをつくる
主に"コードをみやすくする"、"再利用する"ためにメソッドをつくります。
関連のあるコードをまとめて1つにすることをモジュール化といいます。
関数をつくることは、モジュール化であると言えます。


1-2 . 引数を指定できるメソッドをつくる

◯引数を指定して、より自由度の高いメソッドをつくっていくプログラムです。

tank02.java
//必要なもの(材料)をimportする
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;

//クラスをつくる
public class tank02 {
	
	//インスタンスの生成
	private final static RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
	private final static RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
	
	//staticメソッドをつくる
    public static void main(String[] args) {
        //実行するメソッド
        tank_drive(80,80,4);
        tank_drive(-100,-100,2);
        tank_drive(-30,30,3);
        stop();
    }

    //メソッドの定義
    public static void tank_drive(int a_speed,int b_speed,int rotations){
    	//マックスの(a_speed)% or (b_speed)% の(絶対値の)スピードが出るようにする
    	l_a.setSpeed(Math.abs((int) l_a.getMaxSpeed()*a_speed/100));
    	l_b.setSpeed(Math.abs((int) l_b.getMaxSpeed()*b_speed/100));
    	
    	//a_speedとb_speedの正負の組み合わせで場合分けする
    	if(a_speed > 0) {
                //a_speed、b_speedともに正
    		if(b_speed > 0) {
    	    	l_a.rotate(rotations*360,true);
    	        l_b.rotate(rotations*360);
                //a_speedは正、b_speedは負
    		}else {
    	    	l_a.rotate(rotations*360,true);
    	        l_b.rotate(rotations*360*-1);
    		}
    	}else {
                //a_speedは負b_speedは正
    		if(b_speed > 0) {
    	    	l_a.rotate(rotations*360*-1,true);
    	        l_b.rotate(rotations*360);
                //a_speed、b_speedともに負
    		}else {
    	    	l_a.rotate(rotations*360*-1,true);
    	        l_b.rotate(rotations*360*-1);
    		}
    	}
    }

    //メソッドの定義    
    public static void stop(){
    	l_a.stop(true);
    	l_b.stop();
    }
}


Point : 絶対値
Math.abs()で求めることができる。
[参考記事] : Java 絶対値を取得するサンプル(abs)


1-3.StopWatchクラスを使うプログラム

◯制限時間を設けるプログラムです。

tank03.java
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Stopwatch;
import java.util.Random;
import lejos.utility.Delay;


public class tank03 {
	//インスタンスの生成
    public static Stopwatch stopwatch = new Stopwatch();
    private final static RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
	private final static RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
	
    //staticメソッドをつくる
    public static void main(String[] args) {     

    	//タイマーをリセット
        stopwatch.reset(); 
        //無限ループ
        while (true) {
        	forward();
            //経過時間を表示する
        	System.out.println(Math.round(stopwatch.elapsed() / 1000));
        	//20秒を過ぎたらモータを停止して、ループを抜ける
        	if(stopwatch.elapsed() > 20 * 1000) {
        		stop();
        		break;
        	}
        }
    }
    //メソッドの定義
    public static void forward(){
    	//インスタンスの生成
    	Random r = new Random();
    	//0-マックススピードの範囲から値をランダムに選択してスピードに設定する
    	l_a.setSpeed(r.nextInt((int) l_a.getMaxSpeed()));
    	l_b.setSpeed(r.nextInt((int) l_a.getMaxSpeed()));
    	l_a.forward();
    	l_b.forward();
    	Delay.msDelay(1000);
    }
    //メソッドの定義   	
    public static void stop(){
    	l_a.stop(true);
    	l_b.stop();
    }
}

Point : Math.round
四捨五入するためのメソッドです。
[参考記事] : Java 四捨五入するサンプル(round)


Point : Randomクラス
ランダムな値を出力します。
[参考記事] : Javaで指定範囲の乱数を生成する:Random.nextInt()


Point : stopwatch.elapsed()
Stopwatchクラスのメソッド。
経過時間を返します。


1-4.メソッドを指定した確率で呼び出すプログラム

◯前進する確率が高くなるように意図的に設定したプログラムです。

.java
import java.util.Random;
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Delay;

public class tank04 {
    private final static RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
	private final static RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
	private final static int motorSpeed = 200;
	
    //staticメソッドをつくる
    public static void main(String[] args) {     
    	l_a.setSpeed(motorSpeed);
    	l_b.setSpeed(motorSpeed);
    	
        //10回処理を繰り返す
    	for(int i = 0;i < 10;i++) {
            //インスタンスの生成
    		Random r = new Random();
            //0から100までの範囲の中から、ランダムに数値を選ぶ
    		int random_value = r.nextInt(100);
    		System.out.println("random_value = " + random_value);
    		
    		//10%の確率で停止
    		if(random_value < 10) {
        		stop();
        	//10%の確率で右に方向転換
        	}else if(random_value < 20) {
        		turnRight();
        	//30%の確率で左に方向転換
        	}else if(random_value < 50) {
        		turnLeft();
        	//50%の確率で前進
        	}else {
        		forward();
        	}
    	}
    }
    //メソッドの定義
    public static void forward(){
    	l_a.forward();
    	l_b.forward();
    	Delay.msDelay(2000);
    }
    //メソッドの定義    
    public static void turnRight(){
    	l_a.forward();
    	l_b.backward();
    	Delay.msDelay(1000);
    }
    //メソッドの定義    
    public static void turnLeft(){
    	l_a.backward();
    	l_b.forward();
    	Delay.msDelay(1000);
    }
    //メソッドの定義    
    public static void stop(){
    	l_a.stop(true);
    	l_b.stop();
    	Delay.msDelay(1000);
    }
}

Point : 確率のコントロール
前進する確率だけが高くなるようにする方法を取り上げました。
しかし、下のように書いてしまうと、意図するものにはなりません。

.java
if(random_value < 100){
    forward();
}else if(random_value < 50){
    turnRight();  
}else if(random_value < 20){
    turnLeft();
}else{
    stop();
}

なぜなら、プログラムは上から順番に処理を実行していくからです。
random_numberが決まったとき、最初にその数値が条件と合致するかをチェックするのは、1番上のif(random_value < 100)です。この場合全ての数値がこの条件を満たすので、forward()メソッドしか実行することができません。


1-5.配列を使うプログラム

◯配列から要素を取り出してスピードに設定するプログラムです。

.java
import lejos.hardware.motor.EV3LargeRegulatedMotor;
import lejos.hardware.port.MotorPort;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Delay;


public class tank05 {
    private final static RegulatedMotor l_a = new EV3LargeRegulatedMotor(MotorPort.A);
	private final static RegulatedMotor l_b = new EV3LargeRegulatedMotor(MotorPort.B);
	
    //staticメソッドをつくる
    public static void main(String[] args) {     
    	//インスタンスの生成
    	//配列の宣言と要素数の決定
        int[] speed_list = new int[5];
        //要素の初期化
        speed_list[0] = 500;
        speed_list[1] = 1000;
        speed_list[2] = 1500;
        speed_list[3] = 2000;
        speed_list[4] = 2500;

        //5回処理を繰り返し、その度にiが1ずつ加算されていく
        for (int i = 0;i < 5;i++) {
        	//配列の要素を使う
        	//count = 2 : speed = 1500 のように表示される
        	System.out.println("count = " + i + ":" + "speed = " + speed_list[i]);
        	l_a.setSpeed(speed_list[i]);
        	l_b.setSpeed(speed_list[i]);
        	l_a.forward();
        	l_b.forward();
        	Delay.msDelay(3000);
        }
    	l_a.stop(true);
    	l_b.stop();
    }
}

Point : 配列の使いかた
配列は、以下の手順で使います。

1.配列の宣言(と要素数の決定)
2.配列の要素の初期化
3.配列の使用


Point : 配列の要素の初期化

配列の要素の初期化にはいくつか方法があります。
規則的な要素を配列に格納していく場合などは、ループと組み合わせて以下のようにできます。

.java
for(int i = 0;i < 5;i++){
    //speed_list = [500,1000,1500,2000,2500]
    speed_list[i] = 500*(i+1);
}

最後に

読んで頂きありがとうございました!!
次回は複数のモーターの制御について書いていきたいと思います!

より良い記事にしていきたいので
 ◯こうした方がわかりやすい
 ◯ここがわかりにくい
 ◯ここが間違っている
 ◯ここをもっと説明して欲しい
などの御意見、御指摘のほどよろしくお願い致します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?