WPILib ile Fizik Simülasyonu

Çünkü durum-uzay gösterimi , :systems ‘in dynamics kompakt bir şekilde temsil etmemize olanak tanır, robotlarda fiziksel sistemleri simüle etmek için onu kullanabiliriz. Bu simülatörlerin amacı, mevcut simülasyon dışı kullanıcı kodunu değiştirmeden robot mekanizmalarının hareketini simüle etmektir. Bu tür simülatörlerin temel akışı aşağıdaki gibidir:

  • Normal kullanıcı kodunda:

    • PID veya benzer kontrol algoritmaları, kodlayıcı (veya diğer sensör) okumalarından voltaj komutları üretir

    • Motor çıkışları ayarlandı

  • Simülasyon periyodik kodunda:

    • Simülasyonun state`i, :term:`inputs genellikle bir PID döngüsünden ayarlanmış motorlardan gelen voltajlar kullanılarak güncellenir.

    • Simüle edilmiş kodlayıcı (veya diğer sensör) okumaları, sonraki zaman adımında kullanıcı kodunun kullanılması için ayarlanır

WPILib’in Simülasyon Sınıfları

WPILib’de aşağıdaki fizik simülasyon sınıfları mevcuttur:

  • Doğrusal dinamikli sistemleri modellemek için LinearSystemSim,

  • FlywheelSim - Volan Sim

  • DiferansiyelDrivetrainSim

  • ElevatorSim, which models gravity in the direction of elevator motion

  • SingleJointedArmSim, which models gravity proportional to the arm angle

  • Akü voltajı düşüşünü çekilen akımlara göre tahmin eden BatterySim

Tüm simülasyon sınıfları (diferansiyel sürücü simülatörü haricinde) LinearSystemSim sınıfından miras alır. Varsayılan olarak, dinamikler doğrusal sistem dinamikleridir \(\mathbf{x}_{k+1} = \mathbf{A}\mathbf{x}_k + \mathbf{B}\mathbf{u}_k\) . Alt sınıflar UpdateX(x, u, dt) gibi methorları, yerçekimi modelleme, özel ve doğrusal olmayan dinamikler sağlamak için yöntemini geçersiz kılar.

Not

Swerve support for simulation is in the works, but we cannot provide an ETA. For updates on progress, please follow this pull request.

Kullanıcı Kodunda Kullanım

Aşağıdakiler WPILib’den edinilebilir elevatorsimulation example project.

In addition to standard objects such as motors and encoders, we instantiate our elevator simulator using known constants such as carriage mass and gearing reduction. We also instantiate an EncoderSim, which sets the distance and rate read by our Encoder.

In the following example, we simulate an elevator given the mass of the moving carriage (in kilograms), the radius of the drum driving the elevator (in meters), the gearing reduction between motor and drum as output over input (so usually greater than one), the minimum and maximum height of the elevator (in meters), the starting height of the elevator, and some random noise to add to our position estimate.

Not

Asansör ve kol simülatörleri, simüle edilmiş konumun verilen minimum veya maksimum yükseklik veya açıları aşmasını önleyecektir. Sonsuz dönme veya harekete sahip bir mekanizmayı simüle etmek istiyorsanız, LinearSystemSim daha iyi bir seçenek olabilir.

47  // Simulation classes help us simulate what's going on, including gravity.
48  private final ElevatorSim m_elevatorSim =
49      new ElevatorSim(
50          m_elevatorGearbox,
51          Constants.kElevatorGearing,
52          Constants.kCarriageMass,
53          Constants.kElevatorDrumRadius,
54          Constants.kMinElevatorHeightMeters,
55          Constants.kMaxElevatorHeightMeters,
56          true,
57          0,
58          VecBuilder.fill(0.01));
59  private final EncoderSim m_encoderSim = new EncoderSim(m_encoder);
51  // Simulation classes help us simulate what's going on, including gravity.
52  frc::sim::ElevatorSim m_elevatorSim{m_elevatorGearbox,
53                                      Constants::kElevatorGearing,
54                                      Constants::kCarriageMass,
55                                      Constants::kElevatorDrumRadius,
56                                      Constants::kMinElevatorHeight,
57                                      Constants::kMaxElevatorHeight,
58                                      true,
59                                      0_m,
60                                      {0.01}};
61  frc::sim::EncoderSim m_encoderSim{m_encoder};

Daha sonra, teleopPeriodic/TeleopPeriodic (Java/C++), asansörümüzü yerden 30 inç yükseklikte bir ayar noktasına götürmek için basit bir PID kontrol döngüsü kullanır.

31  @Override
32  public void teleopPeriodic() {
33    if (m_joystick.getTrigger()) {
34      // Here, we set the constant setpoint of 0.75 meters.
35      m_elevator.reachGoal(Constants.kSetpointMeters);
36    } else {
37      // Otherwise, we update the setpoint to 0.
38      m_elevator.reachGoal(0.0);
39    }
40  }
 99  public void reachGoal(double goal) {
100    m_controller.setGoal(goal);
101
102    // With the setpoint value we run PID control like normal
103    double pidOutput = m_controller.calculate(m_encoder.getDistance());
104    double feedforwardOutput = m_feedforward.calculate(m_controller.getSetpoint().velocity);
105    m_motor.setVoltage(pidOutput + feedforwardOutput);
106  }
20void Robot::TeleopPeriodic() {
21  if (m_joystick.GetTrigger()) {
22    // Here, we set the constant setpoint of 0.75 meters.
23    m_elevator.ReachGoal(Constants::kSetpoint);
24  } else {
25    // Otherwise, we update the setpoint to 0.
26    m_elevator.ReachGoal(0.0_m);
27  }
28}
42void Elevator::ReachGoal(units::meter_t goal) {
43  m_controller.SetGoal(goal);
44  // With the setpoint value we run PID control like normal
45  double pidOutput =
46      m_controller.Calculate(units::meter_t{m_encoder.GetDistance()});
47  units::volt_t feedforwardOutput =
48      m_feedforward.Calculate(m_controller.GetSetpoint().velocity);
49  m_motor.SetVoltage(units::volt_t{pidOutput} + feedforwardOutput);
50}

Daha sonra, simulationPeriodic/SimulationPeriodic (Java/C++), asansörün simüle edilmiş konumunu güncellemek için motora uygulanan gerilimi kullanır. Sadece simüle edilmiş robotlar için periyodik olarak çalıştığı için SimulationPeriodic kullanıyoruz. Bu, simülasyon kodumuzun gerçek bir robot üzerinde çalıştırılmayacağı anlamına gelir.

Not

Classes inheriting from command-based’s Subsystem can override the inherited simulationPeriodic() method. Other classes will need their simulation update methods called from Robot’s simulationPeriodic.

Son olarak, simüle edilmiş kodlayıcının mesafe okuması, simüle edilmiş asansörün konumu kullanılarak ayarlanır ve robotun pil voltajı, asansör tarafından çekilen tahmini akımı kullanılarak ayarlanır.

79  public void simulationPeriodic() {
80    // In this method, we update our simulation of what our elevator is doing
81    // First, we set our "inputs" (voltages)
82    m_elevatorSim.setInput(m_motorSim.getSpeed() * RobotController.getBatteryVoltage());
83
84    // Next, we update it. The standard loop time is 20ms.
85    m_elevatorSim.update(0.020);
86
87    // Finally, we set our simulated encoder's readings and simulated battery voltage
88    m_encoderSim.setDistance(m_elevatorSim.getPositionMeters());
89    // SimBattery estimates loaded battery voltages
90    RoboRioSim.setVInVoltage(
91        BatterySim.calculateDefaultBatteryLoadedVoltage(m_elevatorSim.getCurrentDrawAmps()));
92  }
20void Elevator::SimulationPeriodic() {
21  // In this method, we update our simulation of what our elevator is doing
22  // First, we set our "inputs" (voltages)
23  m_elevatorSim.SetInput(frc::Vectord<1>{
24      m_motorSim.GetSpeed() * frc::RobotController::GetInputVoltage()});
25
26  // Next, we update it. The standard loop time is 20ms.
27  m_elevatorSim.Update(20_ms);
28
29  // Finally, we set our simulated encoder's readings and simulated battery
30  // voltage
31  m_encoderSim.SetDistance(m_elevatorSim.GetPosition().value());
32  // SimBattery estimates loaded battery voltages
33  frc::sim::RoboRioSim::SetVInVoltage(
34      frc::sim::BatterySim::Calculate({m_elevatorSim.GetCurrentDraw()}));
35}