-
Notifications
You must be signed in to change notification settings - Fork 287
Replace deprecated feedforward.calculate(velocity, acceleration) (2027) #3179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…libsuite#3117) * Replace deprecated feedforward.calculate(velocity, acceleration) Update ProfiledPIDController documentation to use the recommended feedforward.calculate(currentVelocity, nextVelocity) overload instead of the deprecated (velocity, acceleration) version. This eliminates manual acceleration calculations and uses the newer API that calculates acceleration internally from velocity change. Fixes wpilibsuite#2963 * Convert ProfiledPIDController feedforward example to use snippets Replace inline code blocks with RLIs to snippets from allwpilib. Java and C++ examples now reference compilable snippet code that will be tested in every allwpilib build. Python remains as inline code block since Python snippets are maintained in robotpy repository. Related: wpilibsuite/allwpilib#8280 * Manually update RLI --------- Co-authored-by: sciencewhiz <[email protected]>
|
\inspector fix all |
Inspector ReportUp To DateOutdated - Automatically FixedInvalid - Manual Intervention Needed
- 37 public void goToPosition(double goalPosition) {
- 38 double pidVal = m_controller.calculate(m_encoder.getDistance(), goalPosition);
- 39 m_motor.setVoltage(
- 40 pidVal
- 41 + m_feedforward.calculateWithVelocities(
- 42 m_lastSpeed, m_controller.getSetpoint().velocity));
- 43 m_lastSpeed = m_controller.getSetpoint().velocity;
- 44 }
+ 37
- 25 void GoToPosition(units::meter_t goalPosition) {
- 26 auto pidVal = m_controller.Calculate(
- 27 units::meter_t{m_encoder.GetDistance()}, goalPosition);
- 28 m_motor.SetVoltage(units::volt_t{pidVal} +
- 29 m_feedforward.Calculate(
- 30 m_lastSpeed, m_controller.GetSetpoint().velocity));
- 31 m_lastSpeed = m_controller.GetSetpoint().velocity;
- 32 }
+ 25
- 202 private void schedule(Command command) {
- 203 if (command == null) {
- 204 DriverStation.reportWarning("Tried to schedule a null command", true);
- 205 return;
- 206 }
- 207 if (m_inRunLoop) {
- 208 m_toSchedule.add(command);
- 209 return;
- 210 }
- 211
- 212 requireNotComposed(command);
- 213
- 214 // Do nothing if the scheduler is disabled, the robot is disabled and the command doesn't
- 215 // run when disabled, or the command is already scheduled.
- 216 if (m_disabled
- 217 || isScheduled(command)
- 218 || RobotState.isDisabled() && !command.runsWhenDisabled()) {
- 219 return;
- 220 }
- 221
- 222 Set<Subsystem> requirements = command.getRequirements();
- 223
- 224 // Schedule the command if the requirements are not currently in-use.
- 225 if (Collections.disjoint(m_requirements.keySet(), requirements)) {
- 226 initCommand(command, requirements);
227 202 } else {
228 203 // Else check if the requirements that are in use have all have interruptible commands,
229 204 // and if so, interrupt those commands and schedule the new command.
230 205 for (Subsystem requirement : requirements) {
231 206 Command requiring = requiring(requirement);
232 207 if (requiring != null
233 208 && requiring.getInterruptionBehavior() == InterruptionBehavior.kCancelIncoming) {
234 209 return;
235 210 }
236 211 }
237 212 for (Subsystem requirement : requirements) {
238 213 Command requiring = requiring(requirement);
239 214 if (requiring != null) {
- 240 cancel(requiring);
+ 215 cancel(requiring, Optional.of(command));
241 216 }
242 217 }
243 218 initCommand(command, requirements);
244 219 }
245 220 }
+ 221
+ 222 /**
+ 223 * Schedules multiple commands for execution. Does nothing for commands already scheduled.
+ 224 *
+ 225 * <p>WARNING: using this function directly can often lead to unexpected behavior and should be
+ 226 * avoided. Instead Triggers should be used to schedule Commands.
+ 227 *
+ 228 * @param commands the commands to schedule. No-op on null.
+ 229 */
+ 230 public void schedule(Command... commands) {
+ 231 for (Command command : commands) {
+ 232 schedule(command);
+ 233 }
+ 234 }
+ 235
+ 236 /**
+ 237 * Runs a single iteration of the scheduler. The execution occurs in the following order:
+ 238 *
+ 239 * <p>Subsystem periodic methods are called.
+ 240 *
+ 241 * <p>Button bindings are polled, and new commands are scheduled from them.
+ 242 *
+ 243 * <p>Currently-scheduled commands are executed.
+ 244 *
+ 245 * <p>End conditions are checked on currently-scheduled commands, and commands that are finished
- 181 private void initCommand(Command command, Set<Subsystem> requirements) {
- 182 m_scheduledCommands.add(command);
- 183 for (Subsystem requirement : requirements) {
- 184 m_requirements.put(requirement, command);
185 181 }
- 186 command.initialize();
- 187 for (Consumer<Command> action : m_initActions) {
- 188 action.accept(command);
+ 182 if (m_inRunLoop) {
+ 183 m_toSchedule.add(command);
+ 184 return;
189 185 }
190 186
- 191 m_watchdog.addEpoch(command.getName() + ".initialize()");
+ 187 requireNotComposed(command);
+ 188
+ 189 // Do nothing if the scheduler is disabled, the robot is disabled and the command doesn't
+ 190 // run when disabled, or the command is already scheduled.
+ 191 if (m_disabled
- 114 void CommandScheduler::Schedule(Command* command) {
- 115 if (m_impl->inRunLoop) {
- 116 m_impl->toSchedule.emplace_back(command);
- 117 return;
- 118 }
- 119
- 120 RequireUngrouped(command);
- 121
- 122 if (m_impl->disabled || m_impl->scheduledCommands.contains(command) ||
- 123 (frc::RobotState::IsDisabled() && !command->RunsWhenDisabled())) {
- 124 return;
- 125 }
- 126
- 127 const auto& requirements = command->GetRequirements();
- 128
- 129 wpi::SmallVector<Command*, 8> intersection;
- 130
131 114 bool isDisjoint = true;
132 115 bool allInterruptible = true;
133 116 for (auto&& i1 : m_impl->requirements) {
134 117 if (requirements.find(i1.first) != requirements.end()) {
135 118 isDisjoint = false;
136 119 allInterruptible &= (i1.second->GetInterruptionBehavior() ==
137 120 Command::InterruptionBehavior::kCancelSelf);
138 121 intersection.emplace_back(i1.second);
139 122 }
140 123 }
141 124
142 125 if (isDisjoint || allInterruptible) {
143 126 if (allInterruptible) {
144 127 for (auto&& cmdToCancel : intersection) {
- 145 Cancel(cmdToCancel);
+ 128 Cancel(cmdToCancel, std::make_optional(command));
146 129 }
147 130 }
148 131 m_impl->scheduledCommands.insert(command);
149 132 for (auto&& requirement : requirements) {
150 133 m_impl->requirements[requirement] = command;
151 134 }
152 135 command->Initialize();
153 136 for (auto&& action : m_impl->initActions) {
154 137 action(*command);
155 138 }
156 139 m_watchdog.AddEpoch(command->GetName() + ".Initialize()");
157 140 }
158 141 }
159 142
+ 143 void CommandScheduler::Schedule(std::span<Command* const> commands) {
+ 144 for (auto command : commands) {
+ 145 Schedule(command);
+ 146 }
+ 147 }
+ 148
+ 149 void CommandScheduler::Schedule(std::initializer_list<Command*> commands) {
+ 150 for (auto command : commands) {
+ 151 Schedule(command);
+ 152 }
+ 153 }
+ 154
+ 155 void CommandScheduler::Schedule(const CommandPtr& command) {
+ 156 Schedule(command.get());
+ 157 }
+ 158
+ 159 void CommandScheduler::Schedule(CommandPtr&& command) {
- 278 // Run the periodic method of all registered subsystems.
- 279 for (Subsystem subsystem : m_subsystems.keySet()) {
- 280 subsystem.periodic();
- 281 if (RobotBase.isSimulation()) {
- 282 subsystem.simulationPeriodic();
+ 278 if (isDisabled && !command.runsWhenDisabled()) {
+ 279 cancel(command, kNoInterruptor);
+ 280 continue;
283 281 }
- 284 m_watchdog.addEpoch(subsystem.getClass().getSimpleName() + ".periodic()");
- 285 }
+ 282
+ 283 command.execute();
+ 284 for (Consumer<Command> action : m_executeActions) {
+ 285 action.accept(command);
- 183 // Run the periodic method of all registered subsystems.
- 184 for (auto&& subsystem : m_impl->subsystems) {
- 185 subsystem.getFirst()->Periodic();
- 186 if constexpr (frc::RobotBase::IsSimulation()) {
- 187 subsystem.getFirst()->SimulationPeriodic();
- 188 }
- 189 m_watchdog.AddEpoch("Subsystem Periodic()");
- 190 }
+ 183 frc::EventLoop* loopCache = m_impl->activeButtonLoop;
+ 184 // Poll buttons for new commands to add.
+ 185 loopCache->Poll();
+ 186 m_watchdog.AddEpoch("buttons.Run()");
+ 187
+ 188 bool isDisabled = frc::RobotState::IsDisabled();
+ 189 // create a new set to avoid iterator invalidation.
+ 190 for (Command* command : wpi::SmallSet(m_impl->scheduledCommands)) {
- 290 // Poll buttons for new commands to add.
- 291 loopCache.poll();
- 292 m_watchdog.addEpoch("buttons.run()");
+ 290 command.end(false);
+ 291 for (Consumer<Command> action : m_finishActions) {
+ 292 action.accept(command);
- 195 // Poll buttons for new commands to add.
- 196 loopCache->Poll();
- 197 m_watchdog.AddEpoch("buttons.Run()");
+ 195 if (isDisabled && !command->RunsWhenDisabled()) {
+ 196 Cancel(command, std::nullopt);
+ 197 continue;
- 295 // Run scheduled commands, remove finished commands.
- 296 for (Iterator<Command> iterator = m_scheduledCommands.iterator(); iterator.hasNext(); ) {
- 297 Command command = iterator.next();
+ 295 iterator.remove();
298 296
- 299 if (!command.runsWhenDisabled() && RobotState.isDisabled()) {
- 300 command.end(true);
- 301 for (Consumer<Command> action : m_interruptActions) {
- 302 action.accept(command);
- 303 }
304 297 m_requirements.keySet().removeAll(command.getRequirements());
- 305 iterator.remove();
- 306 m_watchdog.addEpoch(command.getName() + ".end(true)");
- 307 continue;
+ 298 m_watchdog.addEpoch(command.getName() + ".end(false)");
308 299 }
+ 300 }
+ 301 m_inRunLoop = false;
309 302
- 310 command.execute();
- 311 for (Consumer<Command> action : m_executeActions) {
- 312 action.accept(command);
- 313 }
- 314 m_watchdog.addEpoch(command.getName() + ".execute()");
- 315 if (command.isFinished()) {
- 316 command.end(false);
- 317 for (Consumer<Command> action : m_finishActions) {
- 318 action.accept(command);
- 319 }
- 320 iterator.remove();
+ 303 // Schedule/cancel commands from queues populated during loop
+ 304 for (Command command : m_toSchedule) {
+ 305 schedule(command);
+ 306 }
321 307
- 322 m_requirements.keySet().removeAll(command.getRequirements());
- 323 m_watchdog.addEpoch(command.getName() + ".end(false)");
+ 308 for (int i = 0; i < m_toCancelCommands.size(); i++) {
+ 309 cancel(m_toCancelCommands.get(i), m_toCancelInterruptors.get(i));
+ 310 }
+ 311
+ 312 m_toSchedule.clear();
+ 313 m_toCancelCommands.clear();
+ 314 m_toCancelInterruptors.clear();
+ 315
+ 316 // Add default commands for un-required registered subsystems.
+ 317 for (Map.Entry<Subsystem, Command> subsystemCommand : m_subsystems.entrySet()) {
+ 318 if (!m_requirements.containsKey(subsystemCommand.getKey())
+ 319 && subsystemCommand.getValue() != null) {
+ 320 schedule(subsystemCommand.getValue());
324 321 }
325 322 }
+ 323
+ 324 m_watchdog.disable();
+ 325 if (m_watchdog.isExpired()) {
- 201 for (Command* command : m_impl->scheduledCommands) {
- 202 if (!command->RunsWhenDisabled() && frc::RobotState::IsDisabled()) {
- 203 Cancel(command);
- 204 continue;
- 205 }
- 206
- 207 command->Execute();
208 201 for (auto&& action : m_impl->executeActions) {
209 202 action(*command);
210 203 }
211 204 m_watchdog.AddEpoch(command->GetName() + ".Execute()");
212 205
213 206 if (command->IsFinished()) {
+ 207 m_impl->scheduledCommands.erase(command);
214 208 command->End(false);
215 209 for (auto&& action : m_impl->finishActions) {
216 210 action(*command);
217 211 }
218 212
219 213 for (auto&& requirement : command->GetRequirements()) {
220 214 m_impl->requirements.erase(requirement);
221 215 }
222 216
- 223 m_impl->scheduledCommands.erase(command);
224 217 m_watchdog.AddEpoch(command->GetName() + ".End(false)");
+ 218 // remove owned commands after everything else is done
+ 219 m_impl->ownedCommands.erase(command);
225 220 }
226 221 }
+ 222
+ 223 // Add default commands for un-required registered subsystems.
+ 224 for (auto&& subsystem : m_impl->subsystems) {
+ 225 auto s = m_impl->requirements.find(subsystem.getFirst());
+ 226 if (s == m_impl->requirements.end() && subsystem.getSecond()) {
- 340 // Add default commands for un-required registered subsystems.
- 341 for (Map.Entry<Subsystem, Command> subsystemCommand : m_subsystems.entrySet()) {
- 342 if (!m_requirements.containsKey(subsystemCommand.getKey())
- 343 && subsystemCommand.getValue() != null) {
- 344 schedule(subsystemCommand.getValue());
+ 340 if (subsystem == null) {
+ 341 DriverStation.reportWarning("Tried to register a null subsystem", true);
+ 342 continue;
345 343 }
- 346 }
+ 344 if (m_subsystems.containsKey(subsystem)) {
+ 345 DriverStation.reportWarning("Tried to register an already-registered subsystem", true);
+ 346 continue;
- 240 // Add default commands for un-required registered subsystems.
- 241 for (auto&& subsystem : m_impl->subsystems) {
- 242 auto s = m_impl->requirements.find(subsystem.getFirst());
- 243 if (s == m_impl->requirements.end() && subsystem.getSecond()) {
- 244 Schedule({subsystem.getSecond().get()});
- 245 }
+ 240 return;
246 241 }
+ 242
+ 243 m_impl->subsystems[subsystem] = nullptr;
+ 244 }
+ 245
+ 246 void CommandScheduler::UnregisterSubsystem(Subsystem* subsystem) {
- 73 // Set the scheduler to log Shuffleboard events for command initialize, interrupt, finish
- 74 CommandScheduler.getInstance()
- 75 .onCommandInitialize(
- 76 command ->
- 77 Shuffleboard.addEventMarker(
- 78 "Command initialized", command.getName(), EventImportance.kNormal));
- 79 CommandScheduler.getInstance()
- 80 .onCommandInterrupt(
- 81 command ->
- 82 Shuffleboard.addEventMarker(
- 83 "Command interrupted", command.getName(), EventImportance.kNormal));
- 84 CommandScheduler.getInstance()
- 85 .onCommandFinish(
- 86 command ->
- 87 Shuffleboard.addEventMarker(
- 88 "Command finished", command.getName(), EventImportance.kNormal));
+ 73 * Use this method to define your button->command mappings. Buttons can be created by
+ 74 * instantiating a {@link edu.wpi.first.wpilibj.GenericHID} or one of its subclasses ({@link
+ 75 * edu.wpi.first.wpilibj.Joystick} or {@link PS4Controller}), and then passing it to a {@link
+ 76 * edu.wpi.first.wpilibj2.command.button.JoystickButton}.
+ 77 */
+ 78 private void configureButtonBindings() {
+ 79 // Grab the hatch when the Circle button is pressed.
+ 80 m_driverController.circle().onTrue(m_hatchSubsystem.grabHatchCommand());
+ 81 // Release the hatch when the Square button is pressed.
+ 82 m_driverController.square().onTrue(m_hatchSubsystem.releaseHatchCommand());
+ 83 // While holding R1, drive at half speed
+ 84 m_driverController
+ 85 .R1()
+ 86 .onTrue(Commands.runOnce(() -> m_robotDrive.setMaxOutput(0.5)))
+ 87 .onFalse(Commands.runOnce(() -> m_robotDrive.setMaxOutput(1)));
+ 88 }
- 23 // Log Shuffleboard events for command initialize, execute, finish, interrupt
- 24 frc2::CommandScheduler::GetInstance().OnCommandInitialize(
- 25 [](const frc2::Command& command) {
- 26 frc::Shuffleboard::AddEventMarker(
- 27 "Command initialized", command.GetName(),
- 28 frc::ShuffleboardEventImportance::kNormal);
- 29 });
- 30 frc2::CommandScheduler::GetInstance().OnCommandExecute(
- 31 [](const frc2::Command& command) {
- 32 frc::Shuffleboard::AddEventMarker(
- 33 "Command executed", command.GetName(),
- 34 frc::ShuffleboardEventImportance::kNormal);
- 35 });
- 36 frc2::CommandScheduler::GetInstance().OnCommandFinish(
- 37 [](const frc2::Command& command) {
- 38 frc::Shuffleboard::AddEventMarker(
- 39 "Command finished", command.GetName(),
- 40 frc::ShuffleboardEventImportance::kNormal);
- 41 });
- 42 frc2::CommandScheduler::GetInstance().OnCommandInterrupt(
- 43 [](const frc2::Command& command) {
- 44 frc::Shuffleboard::AddEventMarker(
- 45 "Command interrupted", command.GetName(),
- 46 frc::ShuffleboardEventImportance::kNormal);
- 47 });
+ 23 // Configure the button bindings
+ 24 ConfigureButtonBindings();
+ 25
+ 26 // Set up default drive command
+ 27 m_drive.SetDefaultCommand(frc2::cmd::Run(
+ 28 [this] {
+ 29 m_drive.ArcadeDrive(-m_driverController.GetLeftY(),
+ 30 -m_driverController.GetRightX());
+ 31 },
+ 32 {&m_drive}));
+ 33 }
+ 34
+ 35 void RobotContainer::ConfigureButtonBindings() {
+ 36 // Configure your button bindings here
+ 37
+ 38 // Grab the hatch when the 'Circle' button is pressed.
+ 39 m_driverController.Circle().OnTrue(m_hatch.GrabHatchCommand());
+ 40 // Release the hatch when the 'Square' button is pressed.
+ 41 m_driverController.Square().OnTrue(m_hatch.ReleaseHatchCommand());
+ 42 // While holding R1, drive at half speed
+ 43 m_driverController.R1()
+ 44 .OnTrue(frc2::cmd::RunOnce([this] { m_drive.SetMaxOutput(0.5); }, {}))
+ 45 .OnFalse(frc2::cmd::RunOnce([this] { m_drive.SetMaxOutput(1.0); }, {}));
+ 46 }
+ 47
5 5 package edu.wpi.first.wpilibj.examples.hatchbottraditional.subsystems;
6 6
7 7 import static edu.wpi.first.wpilibj.DoubleSolenoid.Value.kForward;
8 8 import static edu.wpi.first.wpilibj.DoubleSolenoid.Value.kReverse;
9 9
10 10 import edu.wpi.first.util.sendable.SendableBuilder;
11 11 import edu.wpi.first.wpilibj.DoubleSolenoid;
12 12 import edu.wpi.first.wpilibj.PneumaticsModuleType;
13 13 import edu.wpi.first.wpilibj.examples.hatchbottraditional.Constants.HatchConstants;
14 14 import edu.wpi.first.wpilibj2.command.SubsystemBase;
15 15
16 16 /** A hatch mechanism actuated by a single {@link DoubleSolenoid}. */
17 17 public class HatchSubsystem extends SubsystemBase {
18 18 private final DoubleSolenoid m_hatchSolenoid =
19 19 new DoubleSolenoid(
+ 20 0,
20 21 PneumaticsModuleType.CTREPCM,
21 22 HatchConstants.kHatchSolenoidPorts[0],
22 23 HatchConstants.kHatchSolenoidPorts[1]);
23 24
24 25 /** Grabs the hatch. */
25 26 public void grabHatch() {
26 27 m_hatchSolenoid.set(kForward);
27 28 }
28 29
29 30 /** Releases the hatch. */
30 31 public void releaseHatch() {
31 32 m_hatchSolenoid.set(kReverse);
32 33 }
33 34
34 35 @Override
35 36 public void initSendable(SendableBuilder builder) {
36 37 super.initSendable(builder);
37 38 // Publish the solenoid state to telemetry.
38 39 builder.addBooleanProperty("extended", () -> m_hatchSolenoid.get() == kForward, null);
39 40 }
40 41 }
41 42
5 5 #include "subsystems/HatchSubsystem.h"
6 6
7 7 #include <wpi/sendable/SendableBuilder.h>
8 8
9 9 using namespace HatchConstants;
10 10
11 11 HatchSubsystem::HatchSubsystem()
- 12 : m_hatchSolenoid{frc::PneumaticsModuleType::CTREPCM,
+ 12 : m_hatchSolenoid{0, frc::PneumaticsModuleType::CTREPCM,
13 13 kHatchSolenoidPorts[0], kHatchSolenoidPorts[1]} {}
14 14
15 15 void HatchSubsystem::GrabHatch() {
16 16 m_hatchSolenoid.Set(frc::DoubleSolenoid::kForward);
17 17 }
18 18
19 19 void HatchSubsystem::ReleaseHatch() {
20 20 m_hatchSolenoid.Set(frc::DoubleSolenoid::kReverse);
21 21 }
22 22
23 23 void HatchSubsystem::InitSendable(wpi::SendableBuilder& builder) {
24 24 SubsystemBase::InitSendable(builder);
25 25
26 26 // Publish the solenoid state to telemetry.
27 27 builder.AddBooleanProperty(
28 28 "extended",
29 29 [this] { return m_hatchSolenoid.Get() == frc::DoubleSolenoid::kForward; },
30 30 nullptr);
31 31 }
32 32
5 5 package edu.wpi.first.wpilibj.examples.hatchbotinlined.subsystems;
6 6
7 7 import static edu.wpi.first.wpilibj.DoubleSolenoid.Value.kForward;
8 8 import static edu.wpi.first.wpilibj.DoubleSolenoid.Value.kReverse;
9 9
10 10 import edu.wpi.first.util.sendable.SendableBuilder;
11 11 import edu.wpi.first.wpilibj.DoubleSolenoid;
12 12 import edu.wpi.first.wpilibj.PneumaticsModuleType;
13 13 import edu.wpi.first.wpilibj.examples.hatchbotinlined.Constants.HatchConstants;
14 14 import edu.wpi.first.wpilibj2.command.Command;
15 15 import edu.wpi.first.wpilibj2.command.SubsystemBase;
16 16
17 17 /** A hatch mechanism actuated by a single {@link edu.wpi.first.wpilibj.DoubleSolenoid}. */
18 18 public class HatchSubsystem extends SubsystemBase {
19 19 private final DoubleSolenoid m_hatchSolenoid =
20 20 new DoubleSolenoid(
+ 21 0,
21 22 PneumaticsModuleType.CTREPCM,
22 23 HatchConstants.kHatchSolenoidPorts[0],
23 24 HatchConstants.kHatchSolenoidPorts[1]);
24 25
25 26 /** Grabs the hatch. */
26 27 public Command grabHatchCommand() {
27 28 // implicitly require `this`
28 29 return this.runOnce(() -> m_hatchSolenoid.set(kForward));
29 30 }
30 31
31 32 /** Releases the hatch. */
32 33 public Command releaseHatchCommand() {
33 34 // implicitly require `this`
34 35 return this.runOnce(() -> m_hatchSolenoid.set(kReverse));
35 36 }
36 37
37 38 @Override
38 39 public void initSendable(SendableBuilder builder) {
39 40 super.initSendable(builder);
40 41 // Publish the solenoid state to telemetry.
41 42 builder.addBooleanProperty("extended", () -> m_hatchSolenoid.get() == kForward, null);
42 43 }
43 44 }
44 45
5 5 #include "subsystems/HatchSubsystem.h"
6 6
7 7 #include <wpi/sendable/SendableBuilder.h>
8 8
9 9 using namespace HatchConstants;
10 10
11 11 HatchSubsystem::HatchSubsystem()
- 12 : m_hatchSolenoid{frc::PneumaticsModuleType::CTREPCM,
+ 12 : m_hatchSolenoid{0, frc::PneumaticsModuleType::CTREPCM,
13 13 kHatchSolenoidPorts[0], kHatchSolenoidPorts[1]} {}
14 14
15 15 frc2::CommandPtr HatchSubsystem::GrabHatchCommand() {
16 16 // implicitly require `this`
17 17 return this->RunOnce(
18 18 [this] { m_hatchSolenoid.Set(frc::DoubleSolenoid::kForward); });
19 19 }
20 20
21 21 frc2::CommandPtr HatchSubsystem::ReleaseHatchCommand() {
22 22 // implicitly require `this`
23 23 return this->RunOnce(
24 24 [this] { m_hatchSolenoid.Set(frc::DoubleSolenoid::kReverse); });
25 25 }
26 26
27 27 void HatchSubsystem::InitSendable(wpi::SendableBuilder& builder) {
28 28 SubsystemBase::InitSendable(builder);
29 29
30 30 // Publish the solenoid state to telemetry.
31 31 builder.AddBooleanProperty(
32 32 "extended",
33 33 [this] { return m_hatchSolenoid.Get() == frc::DoubleSolenoid::kForward; },
34 34 nullptr);
35 35 }
36 36
- 117 @Override
- 118 public void periodic() {
- 119 // Update the odometry in the periodic block
- 120 m_odometry.update(
- 121 Rotation2d.fromDegrees(getHeading()),
- 122 m_leftEncoder.getDistance(),
- 123 m_rightEncoder.getDistance());
- 124 m_fieldSim.setRobotPose(getPose());
- 125 }
+ 117
- 30 void Periodic() override;
+ 30
- 30 void DriveSubsystem::Periodic() {
- 31 // Implementation of subsystem periodic method goes here.
- 32 m_odometry.Update(m_gyro.GetRotation2d(),
- 33 units::meter_t{m_leftEncoder.GetDistance()},
- 34 units::meter_t{m_rightEncoder.GetDistance()});
- 35 m_fieldSim.SetRobotPose(m_odometry.GetPose());
- 36 }
+ 30 |
This reverts commit 084297c.
a955fe5 to
6aea02d
Compare
|
\inspector fix all |
source/docs/software/advanced-controls/controllers/profiled-pidcontroller.rst
Outdated
Show resolved
Hide resolved
Co-authored-by: Ryan Blue <[email protected]>
Update ProfiledPIDController documentation to use the recommended feedforward.calculate(currentVelocity, nextVelocity) overload instead of the deprecated (velocity, acceleration) version.
This eliminates manual acceleration calculations and uses the newer API that calculates acceleration internally from velocity change.
Fixes #2963
Replace inline code blocks with RLIs to snippets from allwpilib. Java and C++ examples now reference compilable snippet code that will be tested in every allwpilib build.
Python remains as inline code block since Python snippets are maintained in robotpy repository.
Related: wpilibsuite/allwpilib#8280