Discover best selling sofas, Lounge chairs and get an extra 10% off using the code SEDONA10

需求简述:

乐高EV3,开发环境是LejOS,需求如下:
1、EV3沿黑线行驶,传感器保持探测黑线边缘以确保路径准确;
2、当前方遇到障碍物时,需要即时躲避并绕过障碍物,继续回到黑线沿黑线行驶。

需求分析:

整体需求为两个部分,可以概括为巡线和避障,如果继续拆分,大致可以分为以下几个部分:
1、传感器:颜色传感器和超声波传感器,分别为巡线和避障提供信息;
2、马达动作:负责EV3的前进、后退、转向等动作;
3、巡线模块和避障模块。

实际项目中,传感器模块、马达控制模块、巡线模块和避障模块应该是分开的,因此,单看巡线和避障两个模块,它们应该与其它模块相配合,具体要看项目的整体规划。

GPT-4/GPTS实操部分:

一、假设只用一个类,那么具体巡线和避障都会变成方法,这个跟通常项目的结构是不符的,但其中的代码经过简单改造也可以使用。

  • 利用的GPTS:https://chat.openai.com/g/g-HgZuFuuBK-professional-coder-auto-programming
  • Prompt: 请帮我写一个class,开发环境是LejOS,用于legoEV3躲避障碍物,具体要求如下: EV3沿黑线行驶,传感器保持探测黑线边缘以确保路径准确; 当前方遇到障碍物时,需要即时躲避并绕过障碍物,继续回到黑线沿黑线行驶。
  • 生成代码过程中,会分为若干步骤,可以根据提示逐渐丰富代码,略去中间过程,给出最终给出的代码,具体过程可点击连接查看:https://chat.openai.com/share/2cd02941-70f0-491e-840c-f5aaa6ca02d5,分享的GPT链接可能存在代码和过程丢失,如果不完整,请告诉我。
import lejos.hardware.motor.Motor;
import lejos.robotics.RegulatedMotor;
import lejos.robotics.navigation.DifferentialPilot;
import lejos.hardware.sensor.EV3ColorSensor;
import lejos.hardware.sensor.EV3UltrasonicSensor;
import lejos.hardware.port.SensorPort;
import lejos.robotics.SampleProvider;

/**
 * ObstacleAvoidance class enhanced with Proportional Control for precise line following.
 */
public class ObstacleAvoidance {
    private DifferentialPilot pilot;
    private EV3ColorSensor colorSensor;
    private EV3UltrasonicSensor ultrasonicSensor;
    // Line following control parameters
    private final float BLACK_LINE_THRESHOLD = 0.3f;
    private final float KP = 300; // Proportional gain constant

    public ObstacleAvoidance() {
        RegulatedMotor leftMotor = Motor.A;
        RegulatedMotor rightMotor = Motor.D;
        this.pilot = new DifferentialPilot(2.2f, 11.0f, leftMotor, rightMotor);
        this.colorSensor = new EV3ColorSensor(SensorPort.S1);
        this.ultrasonicSensor = new EV3UltrasonicSensor(SensorPort.S4);
    }

    /**
     * Follows the line with Proportional Control to adjust steering based on deviation.
     */
    private void followLine() {
        float[] sample = new float[colorSensor.getRedMode().sampleSize()];
        colorSensor.getRedMode().fetchSample(sample, 0);
        float lightIntensity = sample[0];
        float error = BLACK_LINE_THRESHOLD - lightIntensity;
        float turn = KP * error;

        pilot.steer(turn);
    }

    private void checkAndAvoidObstacles() {
        SampleProvider distance = ultrasonicSensor.getDistanceMode();
        float[] sample = new float[distance.sampleSize()];
        distance.fetchSample(sample, 0);
        if (sample[0] < 0.3) { // Check if obstacle is within 0.3 meters
            pilot.stop();
            // Execute simple avoidance maneuver
            pilot.travel(-10);
            pilot.rotate(90);
            pilot.travel(20);
            pilot.rotate(-90);
            pilot.travel(10);
        }
    }

    public void run() {
        while (true) {
            followLine();
            checkAndAvoidObstacles();
        }
    }

    public static void main(String[] args) {
        ObstacleAvoidance robot = new ObstacleAvoidance();
        robot.run();
    }
}

二、不假设有多少类,只提出详细需求和某些技术细节(比如多线程要求使用Thread和Runnable),逐步生成代码。

  • 利用的GPTS:https://chat.openai.com/g/g-HgZuFuuBK-professional-coder-auto-programming
  • Prompt:乐高EV3,开发环境是LejOS,需要实现以下需求: 1、EV3沿黑线行驶,传感器保持探测黑线边缘以确保路径准确; 2、当前方遇到障碍物时,需要即时躲避并绕过障碍物,继续回到黑线沿黑线行驶。 请注意两个需求之间的衔接,也就是当存在障碍物时,优先执行避障操作,再回到黑线;确认已回到黑线后,继续进行巡线行驶。 可以根据需要设定多个类,如涉及多线程,实现方法为Thread类和实现Runnable接口。 对于黑色的检测,请使用阈值,比如colorSample[0] < 0.3 。
  • 这里也只给出最终代码,具体过程可参考:https://chat.openai.com/share/2b4a720d-e9bb-4fda-99fd-f8d77e8da861,分享的GPT链接可能存在代码和过程丢失,如果不完整,请告诉我。
第一步:编写 Main.java
我们将从创建主类开始,这个类会初始化所有需要的组件,并开始执行行驶逻辑。
import lejos.hardware.Button;
import lejos.hardware.lcd.LCD;
import lejos.utility.Delay;

public class Main {
    public static void main(String[] args) {
        LCD.drawString("EV3 Line Follower", 0, 0);
        
        // 初始化组件
        SensorMonitor sensorMonitor = new SensorMonitor();
        MotorController motorController = new MotorController();
        LineFollower lineFollower = new LineFollower(sensorMonitor, motorController);
        ObstacleAvoider obstacleAvoider = new ObstacleAvoider(sensorMonitor, motorController);
        
        // 主循环
        while (!Button.ESCAPE.isDown()) {
            if (sensorMonitor.isObstacleDetected()) {
                obstacleAvoider.avoidObstacle();
            } else if (sensorMonitor.isOnLine()) {
                lineFollower.followLine();
            } else {
                // 非黑线上,尝试找回黑线
                lineFollower.searchForLine();
            }
            Delay.msDelay(50); // 稍微延时减少处理负荷
        }
        
        // 退出程序
        LCD.clear();
        LCD.drawString("Program stopped", 0, 0);
        Delay.msDelay(2000);
        System.exit(0);
    }
}

在这一步中,我们创建了程序的入口点,初始化了监测和控制组件,并启动了一个主循环,根据传感器读数来决定机器人的行为。接下来的步骤将会分别实现这些组件的内部逻辑。

第二步:编写 LineFollower.java
这个类的主要职责是使EV3机器人沿着黑线行驶。我们将使用传感器的读数来调整机器人的方向,确保它始终跟随着黑线。
import lejos.robotics.RegulatedMotor;
import lejos.robotics.navigation.DifferentialPilot;
import lejos.hardware.motor.Motor;
import lejos.hardware.sensor.EV3ColorSensor;
import lejos.robotics.SampleProvider;

public class LineFollower {
    private SensorMonitor sensorMonitor;
    private MotorController motorController;

    // 构造函数
    public LineFollower(SensorMonitor sensorMonitor, MotorController motorController) {
        this.sensorMonitor = sensorMonitor;
        this.motorController = motorController;
    }

    // 沿着黑线行驶的方法
    public void followLine() {
        float[] colorSample = sensorMonitor.getColorSample();

        // 判断是否在黑线上
        if (colorSample[0] < 0.3) {
            // 如果在黑线上,直行
            motorController.forward();
        } else {
            // 如果偏离了黑线,调整方向
            motorController.adjustDirection(colorSample[0]);
        }
    }

    // 寻找黑线的方法
    public void searchForLine() {
        // 简单的寻找黑线策略,可以根据需要进行优化
        motorController.turnLeft();
    }
}

在这个类中,我们依赖于SensorMonitor来获取当前的颜色样本,并根据这个样本来判断机器人是否处于黑线上。如果检测到偏离黑线,我们将调用MotorController的方法来调整机器人的方向。

第三步:编写 ObstacleAvoider.java
这个类负责当机器人遇到障碍物时,检测并绕过障碍物,然后重新寻找并回到黑线上继续行驶的逻辑。
public class ObstacleAvoider {
    private SensorMonitor sensorMonitor;
    private MotorController motorController;

    public ObstacleAvoider(SensorMonitor sensorMonitor, MotorController motorController) {
        this.sensorMonitor = sensorMonitor;
        this.motorController = motorController;
    }

    public void avoidObstacle() {
        // 停止当前的行动
        motorController.stop();

        // 执行避障策略
        // 例如,后退一小段,然后向右转动一定角度
        motorController.backward(500); // 后退500毫秒
        motorController.turnRight(90); // 向右转90度

        // 继续前进,直到再次找到黑线
        while (!sensorMonitor.isOnLine()) {
            motorController.forward();
            try {
                Thread.sleep(100); // 短暂等待,以便传感器检测
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 找到黑线后,调整方向以重新对准黑线
        motorController.adjustToLine();
    }
}

ObstacleAvoider类利用SensorMonitor来判断机器人何时需要避障,以及MotorController来执行具体的避障动作,如后退和转向。避障策略可以根据实际情况进行调整。

此外,当机器人绕过障碍物后,它会尝试重新寻找黑线,并调用MotorControlleradjustToLine方法(我们将在MotorController类中定义此方法)以确保机器人能够正确地重新对准并沿着黑线继续前进。

第四步:编写 SensorMonitor.java
SensorMonitor类负责监测所有传感器的读数,包括颜色传感器和距离传感器,以便确定机器人当前是否在黑线上以及是否有障碍物在前方。
import lejos.hardware.sensor.EV3ColorSensor;
import lejos.hardware.sensor.EV3UltrasonicSensor;
import lejos.hardware.port.SensorPort;
import lejos.robotics.SampleProvider;

public class SensorMonitor {
    private EV3ColorSensor colorSensor;
    private EV3UltrasonicSensor ultrasonicSensor;
    private SampleProvider colorSampleProvider;
    private SampleProvider distanceSampleProvider;
    private float[] colorSample;
    private float[] distanceSample;

    public SensorMonitor() {
        colorSensor = new EV3ColorSensor(SensorPort.S1);
        ultrasonicSensor = new EV3UltrasonicSensor(SensorPort.S4);
        
        colorSampleProvider = colorSensor.getMode("Red");
        distanceSampleProvider = ultrasonicSensor.getDistanceMode();
        
        colorSample = new float[colorSampleProvider.sampleSize()];
        distanceSample = new float[distanceSampleProvider.sampleSize()];
    }

    public boolean isOnLine() {
        colorSampleProvider.fetchSample(colorSample, 0);
        return colorSample[0] < 0.3;
    }

    public boolean isObstacleDetected() {
        distanceSampleProvider.fetchSample(distanceSample, 0);
        return distanceSample[0] < 0.25; // 25cm or closer
    }

    public float[] getColorSample() {
        colorSampleProvider.fetchSample(colorSample, 0);
        return colorSample;
    }

    public void closeSensors() {
        colorSensor.close();
        ultrasonicSensor.close();
    }
}

在这个类中,我们初始化了颜色和超声波传感器,并为它们各自定义了样本提供器。isOnLine方法用于判断机器人是否在黑线上,通过颜色传感器的红光模式读数判断。isObstacleDetected方法用于通过超声波传感器判断是否检测到障碍物。

这样,SensorMonitor就能提供关于环境状态的实时信息,供LineFollowerObstacleAvoider类使用。

第五步:编写 MotorController.java
MotorController类负责直接控制机器人的马达,实现前进、后退、转向等基本动作。这个类将被LineFollowerObstacleAvoider等类用于执行具体的移动操作。
import lejos.hardware.motor.Motor;
import lejos.robotics.RegulatedMotor;
import lejos.robotics.navigation.DifferentialPilot;

public class MotorController {
    private RegulatedMotor leftMotor = Motor.A;
    private RegulatedMotor rightMotor = Motor.D;
    private DifferentialPilot pilot;

    public MotorController() {
        pilot = new DifferentialPilot(3.2f, 17.5f, leftMotor, rightMotor);
        pilot.setTravelSpeed(10); // 设置前进速度
        pilot.setRotateSpeed(20); // 设置转向速度
    }

    public void forward() {
        pilot.forward();
    }

    public void backward(long milliseconds) {
        pilot.backward();
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        pilot.stop();
    }

    public void turnLeft(int angle) {
        pilot.rotate(-angle);
    }

    public void turnRight(int angle) {
        pilot.rotate(angle);
    }

    public void stop() {
        pilot.stop();
    }

    public void adjustDirection(float colorIntensity) {
        if (colorIntensity < 0.3) {
            turnLeft(10);
        } else {
            turnRight(10);
        }
    }

    public void adjustToLine() {
        // 此处可以添加更复杂的逻辑来调整机器人的方向,以便更准确地对准黑线
        // 当前简单实现:如果机器人已经偏离黑线,则小幅度左转来寻找黑线
        turnLeft(5);
    }
}

这个类使用了LeJOS库中的DifferentialPilot类来控制两个轮子的马达,从而实现平滑的移动和转向。我们设置了基本的前进和转向速度,以及如何利用这些基础动作来执行更复杂的行为,如避障和沿线行驶的微调。

adjustDirection方法根据颜色传感器的强度来决定是应该向左微调还是向右微调,以保持在黑线上。adjustToLine则是在绕过障碍物并试图重新定位到黑线上时调用的方法。

至此,我们完成了乐高EV3机器人沿黑线行驶并能够检测并绕过障碍物的基本功能的开发。这个项目展示了如何在LeJOS开发环境中使用面向对象的方法来模块化地组织和实现复杂的行为逻辑。

大概过程已经展示完毕。具体项目中,结构可能有所不同,需要根据具体结构来进行调整;同时,你也可以提供详细的项目结构甚至代码内容等,提供更多的信息让GPT生成更精确的代码。还有一些技巧比如说分割你的任务,让GPT给出中间步骤、分步回答等,都可以得到更符合需求的代码。利用GPT编程可以说是自身软件开发思想的一个具体体现,也挺有意思的,多多实践吧。

Leave a Reply