Kullanışlı Özellikler

Önceden açıklanan metodolojiler, komut tabanlı robot kodu yazmak için iyi çalışacak olsa da, komut tabanlı kitaplıklar, komut tabanlı kodun ayrıntı/ karmaşıklığını büyük ölçüde azaltabilen daha gelişmiş kullanıcılar için çeşitli kolaylık özellikleri içerir. Kullanıcıların, komut tabanlı kitaplıklardan elde ettikleri değeri en üst düzeye çıkarmak için bu özelliklere aşina olmaları şiddetle tavsiye edilir.

Inline-Satır İçi Komut Tanımları

Kullanıcılar açıkça komut sınıfları yazarak (CommandBase alt sınıfını oluşturarak veya Command uygulayarak) komutlar oluşturabilirken, birçok komut için (tek bir alt sistem yöntemini çağıranlar gibi) bu, çok sayıda gereksiz standart kod gerektirir. Bunu hafifletmeye yardımcı olmak için, komut tabanlı kitaplıkta bulunan önceden yazılmış komutların çoğu satır içi-inline olabilir - yani komut gövdesi, komut oluşturma sırasında tek bir kod satırında tanımlanabilir.

Alt Yordamları-Subroutines Parametre Olarak Aktarma

Bir komut tanımını satır içi yapmak için, kullanıcılar komutların yapıcı parametreleri olarak hangi kodu çalıştıracağını belirtmek için bir yol gerektirir. Neyse ki, hem Java hem de C++, kullanıcılara alt rutinleri parametre olarak geçirme yeteneği sunar.

Method Referansları (Java)

Java’da, parametre olarak aktarılabilen bir alt yordama yapılan başvuruya yöntem başvurusu denir. Bir yöntem başvurusunun genel sözdizimi object::method dir. Yöntemin kendisi parametre olduğu için hiçbir yöntem parametresinin dahil edilmediğine dikkat edin. Yöntem çağrılmıyor - başka bir kod parçasına (bu durumda, bir komut) aktarılıyor, böylece * o * kod gerektiğinde onu çağırabilir. Yöntem referansları hakkında daha fazla bilgi için, bkz. “Resmi Oracle dokümantasyonu.

Lambda İfadeleri (Java)

While method references work well for passing a subroutine that has already been written, often it is inconvenient/wasteful to write a subroutine solely for the purpose of sending as a method reference, if that subroutine will never be used elsewhere. To avoid this, Java also supports a feature called “lambda expressions.” A lambda expression is an inline method definition - it allows a subroutine to be defined inside of a parameter list. For specifics on how to write Java lambda expressions, see this tutorial.

Lambda İfadeleri (C++)

Uyarı

Due to complications in C++ semantics, capturing this in a C++ lambda can cause a null pointer exception if done from a component command of a command group. Whenever possible, C++ users should capture relevant command members explicitly and by value. For more details, see here.

C++, Java yöntemi referanslarına yakın bir eşdeğerden yoksundur - üye işlevlere işaretçiler, örtük this parametresinin varlığı nedeniyle genellikle doğrudan parametre olarak kullanılamaz. Bununla birlikte, C++ lambda ifadeleri sunar - ek olarak, C++ tarafından sunulan lambda ifadeleri Java’dakilerden birçok yönden daha güçlüdür. C++ lambda ifadelerinin nasıl yazılacağına ilişkin ayrıntılar için bkz. Cppreference.

Satır İçi - inline Komut Örneği

Öyleyse, satır içi bir komut tanımı pratikte nasıl görünür?

InstantCommand sınıfı, satır içi işlemden büyük ölçüde yararlanan bir komut türü örneği sağlar. HatchBotInlined örnek projesinden (Java <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/hatchbotinlined> __, C ++ <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/HatchbotInlined> __) aşağıdakileri göz önünde bulundurun:

 99
100
101
102
103
104
    new JoystickButton(m_driverController, Button.kB.value)
        .whenPressed(new InstantCommand(m_hatchSubsystem::releaseHatch, m_hatchSubsystem));
    // While holding the shoulder button, drive at half speed
    new JoystickButton(m_driverController, Button.kBumperRight.value)
        .whenPressed(() -> m_robotDrive.setMaxOutput(0.5))
        .whenReleased(() -> m_robotDrive.setMaxOutput(1));

Bitmeden önce yalnızca bir yöntemi çağıran ayrı GrabHatch ve ReleaseHatch komutlarını savurgan bir şekilde yazmak yerine, her ikisi de uygun alt sistem yöntemini geçerek basit bir satır içi tanımlamayla gerçekleştirilebilir.

Dahil Edilen Komut Türleri

The command-based library includes a variety of pre-written commands for commonly-encountered use cases. Many of these commands are intended to be used “out-of-the-box” via inlining, however they may be subclassed, as well. A list of the included pre-made commands can be found below, along with brief examples of each - for more rigorous documentation, see the API docs (Java, C++).

ConditionalCommand

ConditionalCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/ConditionalCommand.html> __, C ++), kullanıcı tarafından belirtilen doğru veya yanlış koşuluna bağlı olarak çalıştırıldığında iki komuttan birini çalıştırır:

// Runs either commandOnTrue or commandOnFalse depending on the value of m_limitSwitch.get()
new ConditionalCommand(commandOnTrue, commandOnFalse, m_limitSwitch::get)

SelectCommand

Not

SelectCommand’ın Java sürümü basitçe bir Object kullanırken, C++ sürümü anahtar türüne göre şablonlanmıştır.

Not

SelectCommand’ın alternatif bir sürümü, çalıştırılacak komutu sağlayan bir yöntemi kullanır - bu çok kısa olabilir, ancak komutun gereksinimlerini anlamayı imkansız hale getirir ve bu nedenle, gereksinimleri manuel olarak SelectCommand’e eklemekten kullanıcıyı sorumlu bırakır.

SelectCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/SelectCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1SelectCommand.html> __), kullanıcı tanımlı bir seçicinin değerine dayalı olarak bir komut seçiminden birini çalıştıran `` ConditionalCommand ‘’ sınıfının bir genellemesidir. Aşağıdaki örnek kod, SelectCommand örnek projesinden alınmıştır (Java, C ++ <https://github.com/wpilibsuite/allwpilib/tree/main/wpilibcExamples/src/main/cpp/examples/SelectCommand> __):

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class RobotContainer {
  // The enum used as keys for selecting the command to run.
  private enum CommandSelector {
    ONE,
    TWO,
    THREE
  }

  // An example selector method for the selectcommand.  Returns the selector that will select
  // which command to run.  Can base this choice on logical conditions evaluated at runtime.
  private CommandSelector select() {
    return CommandSelector.ONE;
  }

  // An example selectcommand.  Will select from the three commands based on the value returned
  // by the selector method at runtime.  Note that selectcommand works on Object(), so the
  // selector does not have to be an enum; it could be any desired type (string, integer,
  // boolean, double...)
  private final Command m_exampleSelectCommand =
      new SelectCommand(
          // Maps selector values to commands
          Map.ofEntries(
              Map.entry(CommandSelector.ONE, new PrintCommand("Command one was selected!")),
              Map.entry(CommandSelector.TWO, new PrintCommand("Command two was selected!")),
              Map.entry(CommandSelector.THREE, new PrintCommand("Command three was selected!"))),
          this::select);

InstantCommand

``InstantCommand``sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/InstantCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1InstantCommand.html> __), başlatma sırasında tek bir eylem yürütür ve ardından hemen sona erer:

// Actuates the hatch subsystem to grab the hatch
new InstantCommand(m_hatchSubsystem::grabHatch, m_hatchSubsystem)

RunCommand

RunCommand sınıfı (“Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/RunCommand.html>” __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1RunCommand.html> __), belirtilen bir yöntemi execute() bloğunda tekrar tekrar çalıştırır. Varsayılan olarak bitiş koşullarına sahip değildir; kullanıcılar ya alt sınıflara ayırabilir ya da eklemek için <#command-decorator-methods> _ süsleyebilir.

// A split-stick arcade command, with forward/backward controlled by the left
// hand, and turning controlled by the right.
new RunCommand(() -> m_robotDrive.arcadeDrive(
    -driverController.getY(GenericHID.Hand.kLeft),
    driverController.getX(GenericHID.Hand.kRight)),
    m_robotDrive)

StartEndCommand

StartEndCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/StartEndCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1StartEndCommand.html> __), başlangıçta bir eylem ve biterken ikinci bir eylem yürütür. Varsayılan olarak bitiş koşullarına sahip değildir; kullanıcılar bunları alt sınıflara ayırabilir veya eklemek için satır içi bir komutu <#command-decorator-methods> _ dekore edebilir.

new StartEndCommand(
    // Start a flywheel spinning at 50% power
    () -> m_shooter.shooterSpeed(0.5),
    // Stop the flywheel at the end of the command
    () -> m_shooter.shooterSpeed(0.0),
    // Requires the shooter subsystem
    m_shooter
)

FunctionalCommand

FunctionalCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/FunctionalCommand.html> __, C ++), dört Command yönteminin tümünün yöntem başvuruları veya lambdas olarak aktarılmasına izin verir:

new FunctionalCommand(
    // Reset encoders on command start
    m_robotDrive::resetEncoders,
    // Start driving forward at the start of the command
    () -> m_robotDrive.arcadeDrive(kAutoDriveSpeed, 0),
    // Stop driving at the end of the command
    interrupted -> m_robotDrive.arcadeDrive(0, 0),
    // End the command when the robot's driven distance exceeds the desired value
    () -> m_robotDrive.getAverageEncoderDistance() >= kAutoDriveDistanceInches,
    // Require the drive subsystem
    m_robotDrive
)

PrintCommand

PrintCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/PrintCommand.html> __, C ++) belirli bir dizeyi yazdırır.

new PrintCommand("This message will be printed!")

ScheduleCommand - Program Komutu

ScheduleCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/ScheduleCommand.html> __, C++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1ScheduleCommand.html> __) belirli bir komutu zamanlar ve anında sona erer:

// Schedules commandToSchedule when run
new ScheduleCommand(commandToSchedule)

Bu genellikle komut gruplarından “forking off-çatallanma” için kullanışlıdır: varsayılan olarak, komut gruplarındaki komutlar, komut grubu boyunca çalıştırılır ve scheduler-zamanlayıcı tarafından asla görülmez. Buna göre, gereksinimleri grubun gereksinimlerine eklenir. Bu genellikle iyi olsa da, bazen tüm komut grubunun tek bir komutun gereksinimlerini karşılaması istenmeyen bir durumdur - iyi bir çözüm, komut grubundan “fork off - çatal atmak” ve bu komutu ayrı ayrı programlamaktır.

ProxyScheduleCommand

ProxyScheduleCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/ProxyScheduleCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1ProxyScheduleCommand.html> __) belirli bir komutu zamanlar ve bu komut sona erene kadar bitmez:

// Schedules commandToSchedule when run, does not end until commandToSchedule is no longer scheduled
new ProxyScheduleCommand(commandToSchedule)

Bu genellikle komut gruplarından “forking off - çatallama” için kullanışlıdır: varsayılan olarak, komut gruplarındaki komutlar komut grubu boyunca çalıştırılır ve zamanlayıcı tarafından asla kendileri görülmez. Buna göre, gereksinimleri grubun gereksinimlerine eklenir. Bu genellikle iyi olsa da, bazen tüm komut grubunun tek bir komutun gereksinimlerini karşılaması istenmeyen bir durumdur - iyi bir çözüm, komut grubundan “fork off” ve komutu ayrı ayrı programlamaktır.

WaitCommand

WaitCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/WaitCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1WaitCommand.html> __) hiçbir şey yapmaz ve ilk zamanlamasının ardından belirli bir süre geçtikten sonra sona erer:

// Ends 5 seconds after being scheduled
new WaitCommand(5)

Bu genellikle bir komut grubunun bir bileşeni olarak kullanışlıdır.

WaitCommand, belirli bir süre boyunca çalışan daha karmaşık bir komut oluşturmak için de alt sınıflara ayrılabilir. Bu yöntemde WaitCommand’ın zamanlayıcısının çalışması için WaitCommand kullanılıyorsa, kullanıcı WaitCommand ın Initialize, End ve IsFinished yöntemlerinin hala çağrıldığından emin olmalıdır.

WaitUntilCommand

Uyarı

WaitUntilCommand tarafından kullanılan maç sayacı resmi bir maç saati sağlamaz! Oldukça doğru olsa da, bu zamanlayıcının kullanılması robotunuzun eylemlerinin yasallığını garanti edemez.

WaitUntilCommand sınıfı (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/WaitUntilCommand.html> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1WaitUntilCommand.html> __) hiçbir şey yapmaz ve belirli bir koşul gerçekleştiğinde veya belirtilen bir eşleşme süresi geçene kadar sona erer.

// Ends after the 60-second mark of the current match
new WaitUntilCommand(60)

// Ends after m_limitSwitch.get() returns true
new WaitUntilCommand(m_limitSwitch::get)

PerpetualCommand

PerpetualCommand sınıfı (`` Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/PerpetualCommand.html> ‘’ __, C++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1PerpetualCommand.html>), belirli bir komutu bitiş koşulu kaldırılmış olarak çalıştırır, böylece sonsuza kadar çalışır (harici olarak kesintiye uğramadıkça):

// Will run commandToRunForever perpetually, even if its isFinished() method returns true
new PerpetualCommand(commandToRunForever)

Command Dekoratör Yöntemleri

The Command interface contains a number of defaulted “decorator” methods which can be used to add additional functionality to existing commands. A “decorator” method is a method that takes an object (in this case, a command) and returns an object of the same type (i.e. a command) with some additional functionality added to it. A list of the included decorator methods with brief examples is included below - for rigorous documentation, see the API docs (Java, C++).

withTimeout

``withTimeout()``dekoratörü (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/Command.html#withTimeout(double)> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1Command.html#a3a10e79038afc9bc7c98461b7dbb895b> __) bir komuta zaman aşımı ekler. Zaman aşımı süresi dolarsa dekore edilmiş komut kesintiye uğrayacaktır:

// Will time out 5 seconds after being scheduled, and be interrupted
button.whenPressed(command.withTimeout(5));

withInterrupt

``withInterrupt()’’ (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/Command.html#withInterrupt(java.util.function.BooleanSupplier)> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1Command.html#a4a6078c253a1578b3310833dcdfc01f0> __) dekoratörü, komutun kesintiye uğrayacağı bir koşul ekler:

// Will be interrupted if m_limitSwitch.get() returns true
button.whenPressed(command.withInterrupt(m_limitSwitch::get));

ve sonra

andThen() dekoratörü (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/Command.html#andThen(java.lang.Runnable)> __, `C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1Command.html#ade79bfb9d4ad670cdcb35369c0081b37> `__), komut bittikten sonra yürütülecek bir yöntem ekler:

// Will print "hello" after ending
button.whenPressed(command.andThen(() -> System.out.println("hello")));

beforeStarting

beforeStarting() dekoratörü (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/Command.html#beforeStarting(java.lang.Runnable)> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1Command.html#a65155a6d7062deed375da196d2ba4c89> __), komut başlamadan önce yürütülecek bir yöntem ekler:

// Will print "hello" before starting
button.whenPressed(command.beforeStarting(() -> System.out.println("hello")));

alongWith (yalnızca Java)

Not

Bu dekoratör, teknik kısıtlamalar nedeniyle C++ ‘da desteklenmez - kullanıcılar bunun yerine basit bir şekilde paralel bir komut grubu oluşturmalıdır.

The alongWith() decorator returns a parallel command group. All commands will execute at the same time and each will end independently of each other:

// Will be a parallel command group that ends after three seconds with all three commands running their full duration.
button.whenPressed(oneSecCommand.alongWith(twoSecCommand, threeSecCommand));

raceWith (Sadece Java)

Not

Bu dekoratör, teknik kısıtlamalar nedeniyle C++ ‘da desteklenmez - kullanıcılar bunun yerine basit bir şekilde paralel bir yarış grubu oluşturmalıdır.

The raceWith() decorator returns a parallel race group that ends as soon as the first command ends. At this point all others are interrupted. It doesn’t matter which command is the calling command:

// Will be a parallel race group that ends after one second with the two and three second commands getting interrupted.
button.whenPressed(twoSecCommand.raceWith(oneSecCommand, threeSecCommand));

deadlineWith (Sadece Java)

Not

Bu dekoratör, teknik kısıtlamalar nedeniyle C++ ‘da desteklenmez - kullanıcılar bunun yerine basit bir şekilde paralel bir deadline grubu oluşturmalıdır.

The deadlineWith() decorator returns a parallel deadline group with the calling command being the deadline. When this deadline command ends it will interrupt any others that are not finished:

// Will be a parallel deadline group that ends after two seconds (the deadline) with the three second command getting interrupted (one second command already finished).
button.whenPressed(twoSecCommand.deadlineWith(oneSecCommand, threeSecCommand));

withName (yalnızca Java)

Not

Bu dekoratör, teknik kısıtlamalar nedeniyle C ++ ‘da desteklenmez - kullanıcılar bunun yerine komutun adını kendi komut sınıfları içinde ayarlamalıdır.

``withName()``dekoratörü <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandBase.html#withName(java.lang.String)> __ bir komuta bir ad ekler. Bu ad, komut `gönderilebilir arabirim <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/CommandBase.html#initSendable(edu.wpi.first.wpilibj.smartdashboard.SendableBuilder)> __ aracılığıyla gönderildiğinde bir gösterge panosunda görünecektir.

// This command will be called "My Command".
var command = new PrintCommand("Hello robot!").withName("My Command");

perpetually-sürekli

``perpetually()` dekoratörü (Java <https://first.wpi.edu/wpilib/allwpilib/docs/release/java/edu/wpi/first/wpilibj2/command/Command.html#perpetually()> __, C ++ <https://first.wpi.edu/wpilib/allwpilib/docs/release/cpp/classfrc2_1_1Command.html#ae1583c73c9b953d8ff730d4809926518> __), sonsuza kadar çalışması için bir komutun bitiş koşulunu kaldırır.

// Will run forever unless externally interrupted, regardless of command.isFinished()
button.whenPressed(command.perpetually());

Decorators-Dekoratörleri Oluşturmak

Tüm komut grupları gibi dekoratörlerin de oluşturulabileceğini unutmayın! Bu, çok güçlü ve kısa satır içi-inline ifadelere izin verir:

// Will run fooCommand, and then a race between barCommand and bazCommand
button.whenPressed(fooCommand.andThen(barCommand.raceWith(bazCommand)));

Komut Grupları için Statik Üretim Yöntemleri (yalnızca Java)

Not

Bu üretim yöntemleri, ayrıntıdaki azalma minimum düzeyde olacağından C++ komut kitaplığına dahil edilmemiştir - C++ komutları, new anahtar sözcüğüne duyulan ihtiyacı ortadan kaldırarak yığın olarak tahsis edilmelidir.

Kullanıcılar komut gruplarını bildirmek için andThen, alongWith, raceWith ve deadlineWith dekoratörlerini kullanmak istemiyor, ancak yine de kurucuları çağırmaya kıyasla ayrıntı düzeyini azaltmak istiyorsa, ` CommandGroupBase sınıfı, komut gruplarını bildirmek için dört statik fabrika methodu içerir: sequence(), parallel(), race() ve deadline(). Bir komut grubu alt sınıfından veya `` import static-içe aktarım durağan ‘’ ile birlikte kullanıldığında bunlar son derece özlü hale gelir ve komut kompozisyonuna büyük ölçüde yardımcı olur:

public class ExampleSequence extends SequentialCommandGroup {

  // Will run a FooCommand, and then a race between a BarCommand and a BazCommand
  public ExampleSequence() {
    addCommands(
        new FooCommand(),
        race(
            new BarCommand(),
            new BazCommand()
        )
    );
  }

}