工作筆記 程式組
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
import edu.wpi.first.wpilibj.DigitalInput;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends TimedRobot {
WPI_TalonSRX mLeftFront = new WPI_TalonSRX(1);
WPI_TalonSRX mLeftBack = new WPI_TalonSRX(4);
WPI_TalonSRX mRightFront = new WPI_TalonSRX(2);
WPI_TalonSRX mRightBack = new WPI_TalonSRX(3);
SpeedControllerGroup leftDrive = new SpeedControllerGroup(mLeftFront, mLeftBack);
SpeedControllerGroup rightDrive = new SpeedControllerGroup(mRightFront, mRightBack);
DifferentialDrive Drive = new DifferentialDrive(leftDrive, rightDrive);
DigitalInput toplimitSwitch = new DigitalInput(0);
DigitalInput bottomlimitSwitch = new DigitalInput(1);
Encoder encoder = new Encoder(0, 1);
Joystick js1 = new Joystick(0);
@Override
public void robotInit() {
mLeftFront.setInverted(true);
mLeftBack.setInverted(false);
mRightFront.setInverted(false);
mRightBack.setInverted(false);
}
@Override
public void robotPeriodic() {
}
@Override
public void autonomousInit() {
}
@Override
public void autonomousPeriodic() {
}
@Override
public void teleopInit() {
}
@Override
public void teleopPeriodic() {
setMotorSpeed(js1.getRawAxis(2));
if (js1.getRawButton(1))
Drive.arcadeDrive(js1.getRawAxis(1), js1.getRawAxis(1));
if (encoder.getDistance() < 5) {
Drive.arcadeDrive(.5, .5);
} else {
Drive.arcadeDrive(0, 0);
}
}
public void setMotorSpeed(double speed) {
if (speed > 0) {
if (toplimitSwitch.get()) {
leftDrive.set(0);
}
else {
leftDrive.set(speed);
}
}
else {
if (bottomlimitSwitch.get()) {
leftDrive.set(0);
} else {
leftDrive.set(speed);
}
}
if (speed > 0) {
if (toplimitSwitch.get()) {
rightDrive.set(0);
}
else {
rightDrive.set(speed);
}
}
else {
if (bottomlimitSwitch.get()) {
rightDrive.set(0);
} else {
rightDrive.set(speed);
}
}
}
@Override
public void disabledInit() {
}
@Override
public void disabledPeriodic() {
}
@Override
public void testInit() {
}
@Override
public void testPeriodic() {
}
}
按左邊的Eyedcopper再點選limelight偵測到的反光條就可以顯示出他離感應器中心的X,Y座標
(官方的設定)
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
import com.kauailabs.navx.frc.AHRS;
import edu.wpi.first.wpilibj.ADXRS450_Gyro;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.SPI;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.interfaces.Gyro;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends TimedRobot {
private static final String kDefaultAuto = "Default";
private static final String kCustomAuto = "My Auto";
private String m_autoSelected;
private final SendableChooser<String> m_chooser = new SendableChooser<>();
public final int kFrontLeftChannel = 3;
public final int kRearLeftChannel = 4;
public final int kFrontRightChannel = 1;
public final int kRearRightChannel = 2;
public final int leftStick_X = 0;
public final int leftStick_Y = 1;
public final int rightStick_X = 4;
public final int rightStick_Y = 5;
public final int trigger_L = 2;
public final int trigger_R = 3;
public final int Btn_A = 1;
public final int Btn_B = 2;
public final int Btn_X = 3;
public final int Btn_Y = 4;
public final int Btn_LB = 5;
public final int Btn_RB = 6;
public final int Btn_LS = 9;
public final int Btn_RS = 10;
double ySpeed;
double xSpeed;
double zRotation;
double kP = 1;
double currentangle;
Gyro gyro = new AHRS(SPI.Port.kMXP);
WPI_TalonSRX m_frontLeft = new WPI_TalonSRX(kFrontLeftChannel);
WPI_TalonSRX m_rearLeft = new WPI_TalonSRX(kRearLeftChannel);
WPI_TalonSRX m_frontRight = new WPI_TalonSRX(kFrontRightChannel);
WPI_TalonSRX m_rearRight = new WPI_TalonSRX(kRearRightChannel);
SpeedControllerGroup left = new SpeedControllerGroup(m_frontLeft, m_rearLeft);
SpeedControllerGroup right = new SpeedControllerGroup(m_frontRight, m_rearRight);
DifferentialDrive drive = new DifferentialDrive(left, right);
Joystick joystick = new Joystick(0);
@Override
public void robotInit() {
m_frontRight.setInverted(true);
m_rearRight.setInverted(true);
m_frontLeft.setInverted(false);
m_rearLeft.setInverted(false);
SmartDashboard.putNumber("Gyro", gyro.getAngle());
currentangle = gyro.getAngle();
if(currentangle >= 360 ){
currentangle -= -360;
}
while(currentangle >= 5 || currentangle <= -5){
if(currentangle >=3)/*its turning left(rightspeed > leftspeed)*/{
left.set(0.8);
right.set(0.1);
}else{
right.set(0.8);
left.set(0.1);
}
}
}
@Override
public void robotPeriodic() {
}
@Override
public void autonomousInit() {
m_autoSelected = m_chooser.getSelected();
// m_autoSelected = SmartDashboard.getString("Auto Selector", kDefaultAuto);
System.out.println("Auto selected: " + m_autoSelected);
}
@Override
public void autonomousPeriodic() {
double error = -gyro.getRate();
drive.tankDrive(.5 + kP * error, .5 - kP * error);
}
@Override
public void teleopInit() {
}
@Override
public void teleopPeriodic() {
ySpeed = -joystick.getRawAxis(leftStick_Y) * -0.5;
xSpeed = joystick.getRawAxis(leftStick_X)* -0.5;
zRotation = joystick.getRawAxis(rightStick_X)* 0.5;
m_frontLeft.set(ySpeed + xSpeed + zRotation);
m_frontRight.set(ySpeed - xSpeed - zRotation);
m_rearLeft.set(ySpeed - xSpeed + zRotation);
m_rearRight.set(ySpeed + xSpeed - zRotation);
}
@Override
public void disabledInit() {
}
@Override
public void disabledPeriodic() {
}
@Override
public void testInit() {
}
@Override
public void testPeriodic() {
}
}
目前有一部分錯誤 周四會進行小調整
今天大致看完PathWeaver的資料,程式也大致寫出來了,只是差一個RamseteConrtroller沒用好,但禮拜四要聖誕晚餐應該不會動到太多。程式晚點貼上來。更 程式在下面
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
import com.kauailabs.navx.frc.AHRS;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.CvSource;
import edu.wpi.cscore.UsbCamera;
import edu.wpi.first.cameraserver.CameraServer;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.wpilibj.AnalogInput;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.SPI;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.networktables.NetworkTable;
public class Robot extends TimedRobot {
// PWM channels
public final int kFrontLeftChannel = 3;
public final int kRearLeftChannel = 1;
public final int kFrontRightChannel = 4;
public final int kRearRightChannel = 2;
public final int joystickPort = 0;
public final int rightUltrasonicPort = 1;
public final int rearUltrasonicPort = 0;
// driver station ports
public final int leftStick_X = 0;
public final int leftStick_Y = 1;
public final int rightStick_X = 4;
public final int rightStick_Y = 5;
public final int trigger_L = 2;
public final int trigger_R = 3;
public final int Btn_A = 1;
public final int Btn_B = 2;
public final int Btn_X = 3;
public final int Btn_Y = 4;
public final int Btn_LB = 5;
public final int Btn_RB = 6;
public final int Btn_LS = 9;
public final int Btn_RS = 10;
// Motors
WPI_TalonSRX m_frontLeft = new WPI_TalonSRX(kFrontLeftChannel);
WPI_TalonSRX m_rearLeft = new WPI_TalonSRX(kRearLeftChannel);
WPI_TalonSRX m_frontRight = new WPI_TalonSRX(kFrontRightChannel);
WPI_TalonSRX m_rearRight = new WPI_TalonSRX(kRearRightChannel);
// SpeedControllerGroup and DifferentialDrive
SpeedControllerGroup leftGroup = new SpeedControllerGroup(m_frontLeft, m_rearLeft);
SpeedControllerGroup rightGroup = new SpeedControllerGroup(m_frontRight, m_rearRight);
DifferentialDrive drive = new DifferentialDrive(leftGroup, rightGroup);
public MecanumDrive m_Drive;
// Joystick
Joystick joystick = new Joystick(joystickPort);
// Gyro
AHRS gyro = new AHRS(SPI.Port.kMXP);
// Ultrasonic
AnalogInput rightUltrasonic = new AnalogInput(rightUltrasonicPort);
AnalogInput rearUltrasonic = new AnalogInput(rearUltrasonicPort);
// Microsoft Camera
UsbCamera camera = CameraServer.getInstance().startAutomaticCapture();
CvSink cvSink = CameraServer.getInstance().getVideo();
CvSource outputStream = CameraServer.getInstance().putVideo("Blur", 640, 480);
// Limelight
NetworkTable table = NetworkTableInstance.getDefault().getTable("limelight");
NetworkTableEntry tx = table.getEntry("tx"); // Horizontal Offset From Crosshair To Target (-27 degrees to 27 degrees)
NetworkTableEntry ty = table.getEntry("ty"); // Vertical Offset From Crosshair To Target (-20.5 degrees to 20.5 degrees)
NetworkTableEntry ta = table.getEntry("ta"); // Target Area (0% of image to 100% of image)
NetworkTableEntry tv = table.getEntry("tv"); // Whether the limelight has any valid targets (0 or 1)
// Variables (limelight)
double x;
double y;
double area;
boolean v;
// Variables (drivetrain)
double xSpeed;
double ySpeed;
double zRotation;
// Variables (gyro)
double currentAngle;
@Override
public void robotInit() {
// drivetrain
m_Drive = new MecanumDrive(m_frontLeft, m_rearLeft, m_frontRight, m_rearRight);
// motors inverted
m_frontRight.setInverted(true);
m_rearRight.setInverted(true);
m_frontLeft.setInverted(true);
m_rearLeft.setInverted(true);
}
@Override
public void robotPeriodic() {
// read values periodically
x = tx.getDouble(0.0);
y = ty.getDouble(0.0);
area = ta.getDouble(0.0);
v = tv.getBoolean(false);
// post to smart dashboard periodically (limelight)
SmartDashboard.putNumber("LimelightX", x);
SmartDashboard.putNumber("LimelightY", y);
SmartDashboard.putNumber("LimelightArea", area);
SmartDashboard.putBoolean("LimelightV", v);
// post to smart dashboard periodically (gyro)
currentAngle = gyro.getAngle();
if (currentAngle >= 360) currentAngle -= 360;
else if (currentAngle <= 0) currentAngle += 360;
SmartDashboard.putNumber("currentAngle", currentAngle);
}
@Override
public void autonomousInit() {}
/** This function is called periodically during autonomous. */
@Override
public void autonomousPeriodic() {}
/** This function is called once when teleop is enabled. */
@Override
public void teleopInit() {
//gyro.reset();
}
void aimWithLimelight() {
double KpSheering = 0.05;
double heading_error = -x;
double min_command = 0.3;
double sheering_adjust = 0.0;
if(x > 0.5) {
sheering_adjust = KpSheering * heading_error - min_command;
} else if (x < -0.5){
sheering_adjust = KpSheering * heading_error + min_command;
}
m_Drive.driveCartesian(0, 0, sheering_adjust * 0.5);
SmartDashboard.putNumber("heading_error", heading_error);
SmartDashboard.putNumber("sheering_adjust", sheering_adjust);
}
/** This function is called periodically during operator control. */
@Override
public void teleopPeriodic() {
// Gyro Reset
if( joystick.getRawButton(Btn_Y) ){
gyro.reset();
}
// drivetrain
ySpeed = joystick.getRawAxis(leftStick_Y) * 0.5;
xSpeed = -joystick.getRawAxis(leftStick_X) * 0.5;
zRotation = -joystick.getRawAxis(rightStick_X) * 0.5;
m_Drive.driveCartesian(ySpeed, xSpeed, zRotation);
if(joystick.getRawButton(Btn_A)) {
aimWithLimelight();
}
}
/** This function is called once when the robot is disabled. */
@Override
public void disabledInit() {}
/** This function is called periodically when disabled. */
@Override
public void disabledPeriodic() {}
/** This function is called once when test mode is enabled. */
@Override
public void testInit() {}
/** This function is called periodically during test mode. */
@Override
public void testPeriodic() {}
}
今天的我在和 matt 測試 limelight,做了這麼多我發現到還是在 limelight finder 找到目標物和確認 tx ty 都跑得動且是穩定的是最難的。完成上述後,我直接複製上次準備好的程式測試 tx 讓底盤瞄準反光布條且轉向目標物,因為底盤是 mecanum drivetrain 所以在思考自轉花了點時間,但後來還是完成了也有請許志恩和王智凱來協助測試。接著是 ty ,我們在調整 kp 時花了很多時間,但怎麼調都是條不好。後來經過測試後發現到如果一直按下 btn b 調整與目標物距離時,則有比較好,但這樣的話 auto 就可能沒辦法到很好,這個下禮拜二還要再測試才行。
今天把Pathweaver寫出來,我有自己寫的一段程式與找到的一段程式,這裡貼上的是Example Code,希望可以把兩個程式合在一起,能在下禮拜測試並修改程式。只是我不知道小台機器人有沒有Gyro跟Encoder,如果有下禮拜就應該可以測試,沒有的話應該測試不了。再說。上面是DriveSubsystem,下面是RobotContainer
package frc.robot.subsystems;
import edu.wpi.first.wpilibj.ADXRS450_Gyro;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.PWMSparkMax;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import frc.robot.Constants.DriveConstants;
import edu.wpi.first.wpilibj.geometry.Pose2d;
import edu.wpi.first.wpilibj.interfaces.Gyro;
import edu.wpi.first.wpilibj.kinematics.DifferentialDriveOdometry;
import edu.wpi.first.wpilibj.kinematics.DifferentialDriveWheelSpeeds;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
WPI_TalonFX leftFront = new WPI_TalonFX(DriveConstants.kLeftMotor1Port);
WPI_TalonFX leftBack = new WPI_TalonFX(DriveConstants.kLeftMotor2Port);
WPI_TalonFX rightFront = new WPI_TalonFX(DriveConstants.kRightMotor1Port);
WPI_TalonFX rightBack = new WPI_TalonFX(DriveConstants.kRightMotor2Port);
// The motors on the left side of the drive.
private final SpeedControllerGroup m_leftMotors =
new SpeedControllerGroup(leftFront,leftBack);
// The motors on the right side of the drive.
private final SpeedControllerGroup m_rightMotors =
new SpeedControllerGroup(rightFront,rightBack);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
// The left-side drive encoder
private final Encoder m_leftEncoder =
new Encoder(
DriveConstants.kLeftEncoderPorts[0],
DriveConstants.kLeftEncoderPorts[1],
DriveConstants.kLeftEncoderReversed);
// The right-side drive encoder
private final Encoder m_rightEncoder =
new Encoder(
DriveConstants.kRightEncoderPorts[0],
DriveConstants.kRightEncoderPorts[1],
DriveConstants.kRightEncoderReversed);
// The gyro sensor
private final Gyro m_gyro = new ADXRS450_Gyro();
// Odometry class for tracking robot pose
private final DifferentialDriveOdometry m_odometry;
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
m_rightEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
resetEncoders();
m_odometry = new DifferentialDriveOdometry(m_gyro.getRotation2d());
}
@Override
public void periodic() {
// Update the odometry in the periodic block
m_odometry.update(
m_gyro.getRotation2d(), m_leftEncoder.getDistance(), m_rightEncoder.getDistance());
}
/**
* Returns the currently-estimated pose of the robot.
*
* @return The pose.
*/
public Pose2d getPose() {
return m_odometry.getPoseMeters();
}
/**
* Returns the current wheel speeds of the robot.
*
* @return The current wheel speeds.
*/
public DifferentialDriveWheelSpeeds getWheelSpeeds() {
return new DifferentialDriveWheelSpeeds(m_leftEncoder.getRate(), m_rightEncoder.getRate());
}
/**
* Resets the odometry to the specified pose.
*
* @param pose The pose to which to set the odometry.
*/
public void resetOdometry(Pose2d pose) {
resetEncoders();
m_odometry.resetPosition(pose, m_gyro.getRotation2d());
}
/**
* Drives the robot using arcade controls.
*
* @param fwd the commanded forward movement
* @param rot the commanded rotation
*/
public void arcadeDrive(double fwd, double rot) {
m_drive.arcadeDrive(fwd, rot);
}
/**
* Controls the left and right sides of the drive directly with voltages.
*
* @param leftVolts the commanded left output
* @param rightVolts the commanded right output
*/
public void tankDriveVolts(double leftVolts, double rightVolts) {
m_leftMotors.setVoltage(leftVolts);
m_rightMotors.setVoltage(-rightVolts);
m_drive.feed();
}
/** Resets the drive encoders to currently read a position of 0. */
public void resetEncoders() {
m_leftEncoder.reset();
m_rightEncoder.reset();
}
/**
* Gets the average distance of the two encoders.
*
* @return the average of the two encoder readings
*/
public double getAverageEncoderDistance() {
return (m_leftEncoder.getDistance() + m_rightEncoder.getDistance()) / 2.0;
}
/**
* Gets the left drive encoder.
*
* @return the left drive encoder
*/
public Encoder getLeftEncoder() {
return m_leftEncoder;
}
/**
* Gets the right drive encoder.
*
* @return the right drive encoder
*/
public Encoder getRightEncoder() {
return m_rightEncoder;
}
/**
* Sets the max output of the drive. Useful for scaling the drive to drive more slowly.
*
* @param maxOutput the maximum output to which the drive will be constrained
*/
public void setMaxOutput(double maxOutput) {
m_drive.setMaxOutput(maxOutput);
}
/** Zeroes the heading of the robot. */
public void zeroHeading() {
m_gyro.reset();
}
/**
* Returns the heading of the robot.
*
* @return the robot's heading in degrees, from -180 to 180
*/
public double getHeading() {
return m_gyro.getRotation2d().getDegrees();
}
/**
* Returns the turn rate of the robot.
*
* @return The turn rate of the robot, in degrees per second
*/
public double getTurnRate() {
return -m_gyro.getRate();
}
}
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot;
import static edu.wpi.first.wpilibj.XboxController.Button;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj.controller.PIDController;
import edu.wpi.first.wpilibj.controller.RamseteController;
import edu.wpi.first.wpilibj.controller.SimpleMotorFeedforward;
import frc.robot.Constants.AutoConstants;
import frc.robot.Constants.DriveConstants;
import frc.robot.Constants.OIConstants;
import frc.robot.subsystems.DriveSubsystem;
import edu.wpi.first.wpilibj.geometry.Pose2d;
import edu.wpi.first.wpilibj.geometry.Rotation2d;
import edu.wpi.first.wpilibj.geometry.Translation2d;
import edu.wpi.first.wpilibj.trajectory.Trajectory;
import edu.wpi.first.wpilibj.trajectory.TrajectoryConfig;
import edu.wpi.first.wpilibj.trajectory.TrajectoryGenerator;
import edu.wpi.first.wpilibj.trajectory.constraint.DifferentialDriveVoltageConstraint;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.RamseteCommand;
import edu.wpi.first.wpilibj2.command.RunCommand;
import edu.wpi.first.wpilibj2.command.button.JoystickButton;
import java.util.List;
/**
* This class is where the bulk of the robot should be declared. Since Command-based is a
* "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot}
* periodic methods (other than the scheduler calls). Instead, the structure of the robot (including
* subsystems, commands, and button mappings) should be declared here.
*/
public class RobotContainer {
// The robot's subsystems
private final DriveSubsystem m_robotDrive = new DriveSubsystem();
// The driver's controller
XboxController m_driverController = new XboxController(OIConstants.kDriverControllerPort);
/** The container for the robot. Contains subsystems, OI devices, and commands. */
public RobotContainer() {
// Configure the button bindings
configureButtonBindings();
// Configure default commands
// Set the default drive command to split-stick arcade drive
m_robotDrive.setDefaultCommand(
// A split-stick arcade command, with forward/backward controlled by the left
// hand, and turning controlled by the right.
new RunCommand(
() ->
m_robotDrive.arcadeDrive(
m_driverController.getY(GenericHID.Hand.kLeft),
m_driverController.getX(GenericHID.Hand.kRight)),
m_robotDrive));
}
/**
* Use this method to define your button->command mappings. Buttons can be created by
* instantiating a {@link GenericHID} or one of its subclasses ({@link
* edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then calling passing it to a
* {@link JoystickButton}.
*/
private void configureButtonBindings() {
// Drive at half speed when the right bumper is held
new JoystickButton(m_driverController, Button.kBumperRight.value)
.whenPressed(() -> m_robotDrive.setMaxOutput(0.5))
.whenReleased(() -> m_robotDrive.setMaxOutput(1));
}
/**
* Use this to pass the autonomous command to the main {@link Robot} class.
*
* @return the command to run in autonomous
*/
public Command getAutonomousCommand() {
// Create a voltage constraint to ensure we don't accelerate too fast
var autoVoltageConstraint =
new DifferentialDriveVoltageConstraint(
new SimpleMotorFeedforward(
DriveConstants.ksVolts,
DriveConstants.kvVoltSecondsPerMeter,
DriveConstants.kaVoltSecondsSquaredPerMeter),
DriveConstants.kDriveKinematics,
10);
// Create config for trajectory
TrajectoryConfig config =
new TrajectoryConfig(
AutoConstants.kMaxSpeedMetersPerSecond,
AutoConstants.kMaxAccelerationMetersPerSecondSquared)
// Add kinematics to ensure max speed is actually obeyed
.setKinematics(DriveConstants.kDriveKinematics)
// Apply the voltage constraint
.addConstraint(autoVoltageConstraint);
// An example trajectory to follow. All units in meters.
Trajectory exampleTrajectory =
TrajectoryGenerator.generateTrajectory(
// Start at the origin facing the +X direction
new Pose2d(0, 0, new Rotation2d(0)),
// Pass through these two interior waypoints, making an 's' curve path
List.of(new Translation2d(1, 1), new Translation2d(2, -1)),
// End 3 meters straight ahead of where we started, facing forward
new Pose2d(3, 0, new Rotation2d(0)),
// Pass config
config);
RamseteCommand ramseteCommand =
new RamseteCommand(
exampleTrajectory,
m_robotDrive::getPose,
new RamseteController(AutoConstants.kRamseteB, AutoConstants.kRamseteZeta),
new SimpleMotorFeedforward(
DriveConstants.ksVolts,
DriveConstants.kvVoltSecondsPerMeter,
DriveConstants.kaVoltSecondsSquaredPerMeter),
DriveConstants.kDriveKinematics,
m_robotDrive::getWheelSpeeds,
new PIDController(DriveConstants.kPDriveVel, 0, 0),
new PIDController(DriveConstants.kPDriveVel, 0, 0),
// RamseteCommand passes volts to the callback
m_robotDrive::tankDriveVolts,
m_robotDrive);
// Reset odometry to the starting pose of the trajectory.
m_robotDrive.resetOdometry(exampleTrajectory.getInitialPose());
// Run path following command, then stop at the end.
return ramseteCommand.andThen(() -> m_robotDrive.tankDriveVolts(0, 0));
}
}
今天在弄防疫門的網路盒,一開始跟以往一樣在Firmware階段很順利,但在Configure階段都會出錯誤,已經照著說明把其他連接停用,但還是很奇妙地出了錯誤,最後在試著各種方法,像在Firmware階段先不打隊伍數字,在Configure,但還是失敗,結果最後連讓電腦連接到網路盒都有問題,不知是網路線接觸不良,還是網路盒的問題。
以下是查到的官網解決辦法,但已經將其他連線排除了
消毒門的網路盒一開始遇到了網路線接觸不良的問題但是在configure的時候卻會顯示錯誤,根據網路上的說法是無法把網路盒連到筆電的ip其中可能的原因是有網路已經連到那個ip以至於無法順利設定連接,我們也試著把除了乙太網路的連接方式都關掉,也確定沒有任何網路再干擾,卻還是不能連…