001/*
002 * Copyright (C) Cross The Road Electronics.  All rights reserved.
003 * License information can be found in CTRE_LICENSE.txt
004 * For support and suggestions contact support@ctr-electronics.com or file
005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
006 */
007package com.ctre.phoenix6.mechanisms;
008
009import java.util.Optional;
010import java.util.concurrent.atomic.AtomicBoolean;
011import java.util.function.BooleanSupplier;
012
013import com.ctre.phoenix6.StatusCode;
014import com.ctre.phoenix6.configs.DifferentialSensorsConfigs;
015import com.ctre.phoenix6.controls.DifferentialFollower;
016import com.ctre.phoenix6.controls.NeutralOut;
017import com.ctre.phoenix6.controls.CoastOut;
018import com.ctre.phoenix6.controls.StaticBrake;
019import com.ctre.phoenix6.hardware.CANcoder;
020import com.ctre.phoenix6.hardware.Pigeon2;
021import com.ctre.phoenix6.hardware.TalonFX;
022import com.ctre.phoenix6.signals.DifferentialSensorSourceValue;
023
024import com.ctre.phoenix6.controls.ControlRequest;
025import com.ctre.phoenix6.controls.DutyCycleOut;
026import com.ctre.phoenix6.controls.MotionMagicDutyCycle;
027import com.ctre.phoenix6.controls.MotionMagicTorqueCurrentFOC;
028import com.ctre.phoenix6.controls.MotionMagicVoltage;
029import com.ctre.phoenix6.controls.PositionDutyCycle;
030import com.ctre.phoenix6.controls.PositionTorqueCurrentFOC;
031import com.ctre.phoenix6.controls.PositionVoltage;
032import com.ctre.phoenix6.controls.TorqueCurrentFOC;
033import com.ctre.phoenix6.controls.VelocityDutyCycle;
034import com.ctre.phoenix6.controls.VelocityTorqueCurrentFOC;
035import com.ctre.phoenix6.controls.VelocityVoltage;
036import com.ctre.phoenix6.controls.VoltageOut;
037import com.ctre.phoenix6.controls.compound.Diff_DutyCycleOut_Position;
038import com.ctre.phoenix6.controls.compound.Diff_DutyCycleOut_Velocity;
039import com.ctre.phoenix6.controls.compound.Diff_MotionMagicDutyCycle_Position;
040import com.ctre.phoenix6.controls.compound.Diff_MotionMagicDutyCycle_Velocity;
041import com.ctre.phoenix6.controls.compound.Diff_MotionMagicTorqueCurrentFOC_Position;
042import com.ctre.phoenix6.controls.compound.Diff_MotionMagicTorqueCurrentFOC_Velocity;
043import com.ctre.phoenix6.controls.compound.Diff_MotionMagicVoltage_Position;
044import com.ctre.phoenix6.controls.compound.Diff_MotionMagicVoltage_Velocity;
045import com.ctre.phoenix6.controls.compound.Diff_PositionDutyCycle_Position;
046import com.ctre.phoenix6.controls.compound.Diff_PositionDutyCycle_Velocity;
047import com.ctre.phoenix6.controls.compound.Diff_PositionTorqueCurrentFOC_Position;
048import com.ctre.phoenix6.controls.compound.Diff_PositionTorqueCurrentFOC_Velocity;
049import com.ctre.phoenix6.controls.compound.Diff_PositionVoltage_Position;
050import com.ctre.phoenix6.controls.compound.Diff_PositionVoltage_Velocity;
051import com.ctre.phoenix6.controls.compound.Diff_TorqueCurrentFOC_Position;
052import com.ctre.phoenix6.controls.compound.Diff_TorqueCurrentFOC_Velocity;
053import com.ctre.phoenix6.controls.compound.Diff_VelocityDutyCycle_Position;
054import com.ctre.phoenix6.controls.compound.Diff_VelocityDutyCycle_Velocity;
055import com.ctre.phoenix6.controls.compound.Diff_VelocityTorqueCurrentFOC_Position;
056import com.ctre.phoenix6.controls.compound.Diff_VelocityTorqueCurrentFOC_Velocity;
057import com.ctre.phoenix6.controls.compound.Diff_VelocityVoltage_Position;
058import com.ctre.phoenix6.controls.compound.Diff_VelocityVoltage_Velocity;
059import com.ctre.phoenix6.controls.compound.Diff_VoltageOut_Position;
060import com.ctre.phoenix6.controls.compound.Diff_VoltageOut_Velocity;
061
062/**
063 * Manages control of a two-axis differential mechanism.
064 *
065 * This mechanism requires the devices to be Pro licensed and
066 * connected to a CAN FD bus. Unlicensed users and users on a CAN
067 * 2.0 bus can use the {@link SimpleDifferentialMechanism} instead
068 * with limited functionality.
069 */
070public class DifferentialMechanism {
071    /**
072     * Sensor sources for a differential Pigeon 2.
073     */
074    public enum DifferentialPigeon2Source {
075        Yaw,
076        Pitch,
077        Roll
078    }
079
080    /**
081     * Possible reasons for the mechanism to disable.
082     */
083    public enum DisabledReason {
084        /**
085         * No reason given.
086         */
087        None,
088        /**
089         * A remote sensor is not present on CAN Bus.
090         */
091        MissingRemoteSensor,
092        /**
093         * The remote Talon FX used for differential
094         * control is not present on CAN Bus.
095         */
096        MissingDifferentialFX,
097        /**
098         * A remote sensor position has overflowed. Because of the nature
099         * of remote sensors, it is possible for a remote sensor position
100         * to overflow beyond what is supported by the status signal frame.
101         * However, this is rare and cannot occur over the course of an FRC
102         * match under normal use.
103         */
104        RemoteSensorPosOverflow,
105        /**
106         * A device or remote sensor has reset.
107         */
108        DeviceHasReset,
109    }
110
111    /**
112     * Possible reasons for the mechanism to require
113     * user action to resume control.
114     */
115    public enum RequiresUserReason {
116        /**
117         * No reason given.
118         */
119        None,
120        /**
121         * A remote sensor position has overflowed. Because of the nature
122         * of remote sensors, it is possible for a remote sensor position
123         * to overflow beyond what is supported by the status signal frame.
124         * However, this is rare and cannot occur over the course of an FRC
125         * match under normal use.
126         */
127        RemoteSensorPosOverflow,
128        /**
129         * A device or remote sensor has reset.
130         */
131        DeviceHasReset,
132    }
133
134    /**
135     * The default number of retries for config applies.
136     */
137    public static final int kDefaultConfigRetries = 5;
138
139    private final TalonFX _diffAddFX;
140    private final TalonFX _diffSubFX;
141    private final Optional<Pigeon2> _pigeon2;
142    private final DifferentialPigeon2Source _pigeonSource;
143    private final Optional<CANcoder> _cancoder;
144
145    private final DifferentialFollower _diffFollow;
146
147    private final NeutralOut _neutral = new NeutralOut();
148    private final CoastOut _coast = new CoastOut();
149    private final StaticBrake _brake = new StaticBrake();
150
151    private final BooleanSupplier _diffAddFXResetChecker;
152    private final BooleanSupplier _diffSubFXResetChecker;
153    private final Optional<BooleanSupplier> _pigeon2ResetChecker;
154    private final Optional<BooleanSupplier> _cancoderResetChecker;
155
156    private boolean _hasAppliedConfigs = false;
157
158    private final AtomicBoolean _mechanismDisabled = new AtomicBoolean(false);
159    private final AtomicBoolean _requiresUserAction = new AtomicBoolean(false);
160
161    private DisabledReason _disabledReason = DisabledReason.None;
162    private RequiresUserReason _requiresUserReason = RequiresUserReason.None;
163
164    /**
165     * Creates a new differential mechanism using the given two {@link TalonFX} devices.
166     * The mechanism will use the average of the two Talon FX sensors on the primary axis,
167     * and the difference between the two Talon FX sensors on the differential axis.
168     * <p>
169     * This mechanism requires the devices to be Pro licensed and connected to a CAN FD bus.
170     * Unlicensed users and users on a CAN 2.0 bus can use the {@link SimpleDifferentialMechanism}
171     * instead with limited functionality.
172     *
173     * @param differentialAddFX The Talon FX that will have the differential output added to its regular output.
174     * @param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
175     * @param motorDirectionsAlign Whether the differential motors' directions are aligned.
176     */
177    public DifferentialMechanism(TalonFX differentialAddFX, TalonFX differentialSubFX, boolean motorDirectionsAlign)
178    {
179        _diffAddFX = differentialAddFX;
180        _diffSubFX = differentialSubFX;
181        _pigeon2 = Optional.empty();
182        _pigeonSource = null;
183        _cancoder = Optional.empty();
184        _diffFollow = new DifferentialFollower(_diffAddFX.getDeviceID(), !motorDirectionsAlign);
185        _diffAddFXResetChecker = _diffAddFX.getResetOccurredChecker();
186        _diffSubFXResetChecker = _diffSubFX.getResetOccurredChecker();
187        _pigeon2ResetChecker = Optional.empty();
188        _cancoderResetChecker = Optional.empty();
189    }
190
191    /**
192     * Creates a new differential mechanism using the given two {@link TalonFX} devices and
193     * a {@link Pigeon2}. The mechanism will use the average of the two Talon FX sensors on the
194     * primary axis, and the selected Pigeon 2 sensor source on the differential axis.
195     * <p>
196     * This mechanism requires the devices to be Pro licensed and connected to a CAN FD bus.
197     * Unlicensed users and users on a CAN 2.0 bus can use the {@link SimpleDifferentialMechanism}
198     * instead with limited functionality.
199     *
200     * @param differentialAddFX The Talon FX that will have the differential output added to its regular output.
201     * @param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
202     * @param motorDirectionsAlign Whether the differential motors' directions are aligned.
203     * @param pigeon2 The Pigeon 2 to use for the differential axis.
204     * @param pigeonSource The sensor source to use for the Pigeon 2 (Yaw, Pitch, or Roll).
205     */
206    public DifferentialMechanism(TalonFX differentialAddFX, TalonFX differentialSubFX, boolean motorDirectionsAlign, Pigeon2 pigeon2, DifferentialPigeon2Source pigeonSource)
207    {
208        _diffAddFX = differentialAddFX;
209        _diffSubFX = differentialSubFX;
210        _pigeon2 = Optional.of(pigeon2);
211        _pigeonSource = pigeonSource;
212        _cancoder = Optional.empty();
213        _diffFollow = new DifferentialFollower(_diffAddFX.getDeviceID(), !motorDirectionsAlign);
214        _diffAddFXResetChecker = _diffAddFX.getResetOccurredChecker();
215        _diffSubFXResetChecker = _diffSubFX.getResetOccurredChecker();
216        _pigeon2ResetChecker = Optional.of(_pigeon2.get().getResetOccurredChecker());
217        _cancoderResetChecker = Optional.empty();
218    }
219
220    /**
221     * Creates a new differential mechanism using the given two {@link TalonFX} devices and
222     * a {@link CANcoder}. The mechanism will use the average of the two Talon FX sensors on the
223     * primary axis, and the CANcoder position/velocity on the differential axis.
224     * <p>
225     * This mechanism requires the devices to be Pro licensed and connected to a CAN FD bus.
226     * Unlicensed users and users on a CAN 2.0 bus can use the {@link SimpleDifferentialMechanism}
227     * instead with limited functionality.
228     *
229     * @param differentialAddFX The Talon FX that will have the differential output added to its regular output.
230     * @param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
231     * @param motorDirectionsAlign Whether the differential motors' directions are aligned.
232     * @param cancoder The CANcoder to use for the differential axis.
233     */
234    public DifferentialMechanism(TalonFX differentialAddFX, TalonFX differentialSubFX, boolean motorDirectionsAlign, CANcoder cancoder)
235    {
236        _diffAddFX = differentialAddFX;
237        _diffSubFX = differentialSubFX;
238        _pigeon2 = Optional.empty();
239        _pigeonSource = null;
240        _cancoder = Optional.of(cancoder);
241        _diffFollow = new DifferentialFollower(_diffAddFX.getDeviceID(), !motorDirectionsAlign);
242        _diffAddFXResetChecker = _diffAddFX.getResetOccurredChecker();
243        _diffSubFXResetChecker = _diffSubFX.getResetOccurredChecker();
244        _pigeon2ResetChecker = Optional.empty();
245        _cancoderResetChecker = Optional.of(_cancoder.get().getResetOccurredChecker());
246    }
247
248    /**
249     * Get the Talon FX that is differential leader. The differential
250     * leader calculates the output for the differential follower. The
251     * differential leader is also useful for fault detection, and it
252     * reports status signals for the differential controller.
253     *
254     * @return Differential leader Talon FX
255     */
256    public TalonFX getDifferentialLeader()
257    {
258        return _diffAddFX;
259    }
260
261    /**
262     * Get the Talon FX that is differential follower. The differential
263     * follower's position and velocity are used by the differential leader
264     * for the differential controller.
265     *
266     * @return Differential follower Talon FX
267     */
268    public TalonFX getDifferentialFollower()
269    {
270        return _diffSubFX;
271    }
272
273    /**
274     * Apply the mechanism configs to the devices. This should be
275     * called after applying all other configs to the devices.
276     * <p>
277     * If the user does not call this function by the time SetControl
278     * is called, SetControl will apply the configs once.
279     * <p>
280     * This function defaults to retrying up to {@link #kDefaultConfigRetries}.
281     *
282     * @return Status Code of the config applies.
283     */
284    public StatusCode applyConfigs() {
285        return applyConfigs(kDefaultConfigRetries);
286    }
287
288    /**
289     * Apply the mechanism configs to the devices. This should be
290     * called after applying all other configs to the devices.
291     * <p>
292     * If the user does not call this function by the time SetControl
293     * is called, SetControl will apply the configs once.
294     *
295     * @param numRetries Number of retries when applying the configs
296     * @return Status Code of the config applies.
297     */
298    public StatusCode applyConfigs(int numRetries)
299    {
300        StatusCode retval = StatusCode.OK;
301
302        if (numRetries < 1) numRetries = 1;
303
304        /*
305         * The onboard differential controller adds the differential output to its own output
306         * and subtracts the differential output for differential followers, so use _diffAddFX
307         * as the primary controller.
308         */
309        final var diff_cfg = new DifferentialSensorsConfigs();
310
311        /* disable differential control on _diffSubFX */
312        {
313            StatusCode _diffSubFX_retval = StatusCode.OK;
314            for (int i = 0; i < numRetries; ++i) {
315                _diffSubFX_retval = _diffSubFX.getConfigurator().apply(diff_cfg);
316                if (_diffSubFX_retval.isOK()) break;
317            }
318            if (retval.isOK()) {
319                retval = _diffSubFX_retval;
320            }
321        }
322
323        /* set up differential control on _diffAddFX */
324        diff_cfg.DifferentialTalonFXSensorID = _diffSubFX.getDeviceID();
325        if (_pigeon2.isPresent()) {
326            /* use the Pigeon 2 for differential control */
327            switch (_pigeonSource) {
328                case Yaw:
329                default:
330                    diff_cfg.DifferentialSensorSource = DifferentialSensorSourceValue.RemotePigeon2_Yaw;
331                    break;
332                case Pitch:
333                    diff_cfg.DifferentialSensorSource = DifferentialSensorSourceValue.RemotePigeon2_Pitch;
334                    break;
335                case Roll:
336                    diff_cfg.DifferentialSensorSource = DifferentialSensorSourceValue.RemotePigeon2_Roll;
337                    break;
338            }
339            diff_cfg.DifferentialRemoteSensorID = _pigeon2.get().getDeviceID();
340        } else if (_cancoder.isPresent()) {
341            /* use the CANcoder for differential control */
342            diff_cfg.DifferentialSensorSource = DifferentialSensorSourceValue.RemoteCANcoder;
343            diff_cfg.DifferentialRemoteSensorID = _cancoder.get().getDeviceID();
344        } else {
345            /* use the difference between the two Talon FXs for differential control */
346            diff_cfg.DifferentialSensorSource = DifferentialSensorSourceValue.RemoteTalonFX_Diff;
347        }
348
349        {
350            StatusCode _diffAddFX_retval = StatusCode.OK;
351            for (int i = 0; i < numRetries; ++i) {
352                _diffAddFX_retval = _diffAddFX.getConfigurator().apply(diff_cfg);
353                if (_diffAddFX_retval.isOK()) break;
354            }
355            if (retval.isOK()) {
356                retval = _diffAddFX_retval;
357            }
358        }
359
360        if (retval.isOK()) {
361            _hasAppliedConfigs = true;
362        }
363
364        return retval;
365    }
366
367    /**
368     * Call this method periodically to keep the mechanism state updated.
369     */
370    public void periodic()
371    {
372        StatusCode retval = StatusCode.OK;
373
374        /* handle remote sensor position overflow fault */
375        if (_diffAddFX.getFault_RemoteSensorPosOverflow().getValue()) {
376            /* fault the mechanism until the user clears it manually */
377            _requiresUserReason = RequiresUserReason.RemoteSensorPosOverflow;
378            _requiresUserAction.setRelease(true);
379
380            _disabledReason = DisabledReason.RemoteSensorPosOverflow;
381            retval = StatusCode.MechanismFaulted;
382        }
383
384        /* handle missing remote sensor fault */
385        if (_diffAddFX.getFault_RemoteSensorDataInvalid().getValue() ||
386            _diffSubFX.getFault_RemoteSensorDataInvalid().getValue()
387        ) {
388            /* temporarily fault the mechanism while the fault is active */
389            _disabledReason = DisabledReason.MissingRemoteSensor;
390            retval = StatusCode.MechanismFaulted;
391        }
392        /* handle missing differential Talon FX fault */
393        if (_diffAddFX.getFault_MissingDifferentialFX().getValue()) {
394            /* temporarily fault the mechanism while the fault is active */
395            _disabledReason = DisabledReason.MissingDifferentialFX;
396            retval = StatusCode.MechanismFaulted;
397        }
398
399        /* handle if any of the devices have power cycled */
400        final boolean diffAddFX_hasReset = _diffAddFXResetChecker.getAsBoolean();
401        final boolean diffSubFX_hasReset = _diffSubFXResetChecker.getAsBoolean();
402        final boolean pigeon2_hasReset = _pigeon2ResetChecker.isPresent() && _pigeon2ResetChecker.get().getAsBoolean();
403        final boolean cancoder_hasReset = _cancoderResetChecker.isPresent() && _cancoderResetChecker.get().getAsBoolean();
404        final boolean diffAddFX_remsens_hasReset = _diffAddFX.getStickyFault_RemoteSensorReset().getValue();
405        final boolean diffSubFX_remsens_hasReset = _diffSubFX.getStickyFault_RemoteSensorReset().getValue();
406
407        if (diffAddFX_hasReset || diffSubFX_hasReset ||
408            pigeon2_hasReset || cancoder_hasReset ||
409            diffAddFX_remsens_hasReset || diffSubFX_remsens_hasReset
410        ) {
411            /* fault the mechanism until the user clears it manually */
412            _requiresUserReason = RequiresUserReason.DeviceHasReset;
413            _requiresUserAction.setRelease(true);
414
415            _disabledReason = DisabledReason.DeviceHasReset;
416            retval = StatusCode.MechanismFaulted;
417        }
418
419        if (retval.isOK() && _requiresUserAction.getOpaque()) {
420            /* keep the mechanism faulted until user clears the fault */
421            retval = StatusCode.MechanismFaulted;
422        }
423
424        if (!retval.isOK()) {
425            /* disable the mechanism */
426            _mechanismDisabled.setRelease(true);
427        } else {
428            /* re-enable the mechanism */
429            _disabledReason = DisabledReason.None;
430            _mechanismDisabled.setRelease(false);
431        }
432    }
433
434    /**
435     * Get whether the mechanism is currently disabled due to an issue.
436     *
437     * @return true if the mechanism is temporarily disabled
438     */
439    public boolean isDisabled()
440    {
441        return _mechanismDisabled.getAcquire();
442    }
443
444    /**
445     * Get whether the mechanism is currently disabled and requires
446     * user action to re-enable mechanism control.
447     *
448     * @return true if the mechanism is disabled and the user must manually
449     *         perform an action
450     */
451    public boolean requiresUserAction()
452    {
453        return _requiresUserAction.getAcquire();
454    }
455
456    /**
457     * Gets the state of the mechanism.
458     *
459     * @return MechanismState representing the state of the mechanism
460     */
461    public MechanismState getMechanismState()
462    {
463        if (requiresUserAction()) {
464            return MechanismState.RequiresUserAction;
465        } else if (isDisabled()) {
466            return MechanismState.Disabled;
467        } else {
468            return MechanismState.OK;
469        }
470    }
471
472    /**
473     * Indicate to the mechanism that the user has performed the required
474     * action to resume mechanism control.
475     */
476    public void clearUserRequirement()
477    {
478        if (_diffAddFX.getStickyFault_RemoteSensorReset().getValue()) {
479            _diffAddFX.clearStickyFault_RemoteSensorReset();
480        }
481        if (_diffSubFX.getStickyFault_RemoteSensorReset().getValue()) {
482            _diffSubFX.clearStickyFault_RemoteSensorReset();
483        }
484        _requiresUserReason = RequiresUserReason.None;
485        _requiresUserAction.setRelease(false);
486    }
487
488    /**
489     * @return The reason for the mechanism being disabled
490     */
491    public DisabledReason getDisabledReason()
492    {
493        return _disabledReason;
494    }
495    /**
496     * @return The reason for the mechanism requiring user
497     *         action to resume control
498     */
499    public RequiresUserReason getRequiresUserReason()
500    {
501        return _requiresUserReason;
502    }
503
504    private StatusCode beforeControl()
505    {
506        StatusCode retval = StatusCode.OK;
507        if (!_hasAppliedConfigs) {
508            retval = applyConfigs();
509        }
510
511        if (retval.isOK() && _mechanismDisabled.getOpaque()) {
512            /* disable the mechanism */
513            retval = StatusCode.MechanismFaulted;
514        }
515
516        if (!retval.isOK()) {
517            /* neutral the output */
518            setNeutralOut();
519        }
520        return retval;
521    }
522
523    /**
524     * Request neutral output of mechanism. The applied brake type
525     * is determined by the NeutralMode configuration of each device.
526     * <p>
527     * Since the NeutralMode configuration of devices may not align, users
528     * may prefer to use the {@link #setCoastOut()} or {@link #setStaticBrake()} method.
529     *
530     * @return Status Code of the request.
531     */
532    public StatusCode setNeutralOut()
533    {
534        var retval = StatusCode.OK;
535        {
536            final var _diffAddFX_retval = _diffAddFX.setControl(_neutral);
537            if (retval.isOK()) {
538                retval = _diffAddFX_retval;
539            }
540        }
541        {
542            final var _diffSubFX_retval = _diffSubFX.setControl(_neutral);
543            if (retval.isOK()) {
544                retval = _diffSubFX_retval;
545            }
546        }
547        return retval;
548    }
549
550    /**
551     * Request coast neutral output of mechanism. The bridge is
552     * disabled and the rotor is allowed to coast.
553     *
554     * @return Status Code of the request.
555     */
556    public StatusCode setCoastOut()
557    {
558        var retval = StatusCode.OK;
559        {
560            final var _diffAddFX_retval = _diffAddFX.setControl(_coast);
561            if (retval.isOK()) {
562                retval = _diffAddFX_retval;
563            }
564        }
565        {
566            final var _diffSubFX_retval = _diffSubFX.setControl(_coast);
567            if (retval.isOK()) {
568                retval = _diffSubFX_retval;
569            }
570        }
571        return retval;
572    }
573
574    /**
575     * Applies full neutral-brake on the mechanism by shorting
576     * motor leads together.
577     *
578     * @return Status Code of the request.
579     */
580    public StatusCode setStaticBrake()
581    {
582        var retval = StatusCode.OK;
583        {
584            final var _diffAddFX_retval = _diffAddFX.setControl(_brake);
585            if (retval.isOK()) {
586                retval = _diffAddFX_retval;
587            }
588        }
589        {
590            final var _diffSubFX_retval = _diffSubFX.setControl(_brake);
591            if (retval.isOK()) {
592                retval = _diffSubFX_retval;
593            }
594        }
595        return retval;
596    }
597
598    private ControlRequest _diffAddFX_req = null;
599    
600    /**
601     * Sets the control request for this mechanism.
602     *
603     * @param AverageRequest    Average DutyCycleOut request of the mechanism.
604     * @param DifferentialRequest    Differential PositionDutyCycle request of the
605     *                               mechanism. Note: The UpdateFreqHz parameter for
606     *                               this control request will be ignored by the
607     *                               control frame.
608     * @return Status Code of the request.
609     */
610    public StatusCode setControl(DutyCycleOut AverageRequest, PositionDutyCycle DifferentialRequest)
611    {
612        var retval = StatusCode.OK;
613    
614        retval = beforeControl();
615        if (!retval.isOK()) {
616            return retval;
617        }
618        
619        {    
620            Diff_DutyCycleOut_Position _diffAddFX_reqPtr;
621            if (_diffAddFX_req instanceof Diff_DutyCycleOut_Position) {
622                _diffAddFX_reqPtr = (Diff_DutyCycleOut_Position)_diffAddFX_req;
623                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
624                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
625            } else {
626                _diffAddFX_reqPtr = new Diff_DutyCycleOut_Position(AverageRequest, DifferentialRequest);
627                _diffAddFX_req = _diffAddFX_reqPtr;
628            }
629            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
630            
631            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
632            if (retval.isOK()) {
633                retval = _diffAddFX_retval;
634            }
635        }
636        
637        {
638            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
639            if (retval.isOK()) {
640                retval = _diffSubFX_retval;
641            }
642        }
643        
644        return retval;
645    }
646    
647    /**
648     * Sets the control request for this mechanism.
649     *
650     * @param AverageRequest    Average PositionDutyCycle request of the mechanism.
651     * @param DifferentialRequest    Differential PositionDutyCycle request of the
652     *                               mechanism. Note: The UpdateFreqHz parameter for
653     *                               this control request will be ignored by the
654     *                               control frame.
655     * @return Status Code of the request.
656     */
657    public StatusCode setControl(PositionDutyCycle AverageRequest, PositionDutyCycle DifferentialRequest)
658    {
659        var retval = StatusCode.OK;
660    
661        retval = beforeControl();
662        if (!retval.isOK()) {
663            return retval;
664        }
665        
666        {    
667            Diff_PositionDutyCycle_Position _diffAddFX_reqPtr;
668            if (_diffAddFX_req instanceof Diff_PositionDutyCycle_Position) {
669                _diffAddFX_reqPtr = (Diff_PositionDutyCycle_Position)_diffAddFX_req;
670                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
671                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
672            } else {
673                _diffAddFX_reqPtr = new Diff_PositionDutyCycle_Position(AverageRequest, DifferentialRequest);
674                _diffAddFX_req = _diffAddFX_reqPtr;
675            }
676            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
677            
678            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
679            if (retval.isOK()) {
680                retval = _diffAddFX_retval;
681            }
682        }
683        
684        {
685            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
686            if (retval.isOK()) {
687                retval = _diffSubFX_retval;
688            }
689        }
690        
691        return retval;
692    }
693    
694    /**
695     * Sets the control request for this mechanism.
696     *
697     * @param AverageRequest    Average VelocityDutyCYcle request of the mechanism.
698     * @param DifferentialRequest    Differential PositionDutyCycle request of the
699     *                               mechanism. Note: The UpdateFreqHz parameter for
700     *                               this control request will be ignored by the
701     *                               control frame.
702     * @return Status Code of the request.
703     */
704    public StatusCode setControl(VelocityDutyCycle AverageRequest, PositionDutyCycle DifferentialRequest)
705    {
706        var retval = StatusCode.OK;
707    
708        retval = beforeControl();
709        if (!retval.isOK()) {
710            return retval;
711        }
712        
713        {    
714            Diff_VelocityDutyCycle_Position _diffAddFX_reqPtr;
715            if (_diffAddFX_req instanceof Diff_VelocityDutyCycle_Position) {
716                _diffAddFX_reqPtr = (Diff_VelocityDutyCycle_Position)_diffAddFX_req;
717                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
718                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
719            } else {
720                _diffAddFX_reqPtr = new Diff_VelocityDutyCycle_Position(AverageRequest, DifferentialRequest);
721                _diffAddFX_req = _diffAddFX_reqPtr;
722            }
723            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
724            
725            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
726            if (retval.isOK()) {
727                retval = _diffAddFX_retval;
728            }
729        }
730        
731        {
732            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
733            if (retval.isOK()) {
734                retval = _diffSubFX_retval;
735            }
736        }
737        
738        return retval;
739    }
740    
741    /**
742     * Sets the control request for this mechanism.
743     *
744     * @param AverageRequest    Average MotionMagicDutyCycle request of the
745     *                          mechanism.
746     * @param DifferentialRequest    Differential PositionDutyCycle request of the
747     *                               mechanism. Note: The UpdateFreqHz parameter for
748     *                               this control request will be ignored by the
749     *                               control frame.
750     * @return Status Code of the request.
751     */
752    public StatusCode setControl(MotionMagicDutyCycle AverageRequest, PositionDutyCycle DifferentialRequest)
753    {
754        var retval = StatusCode.OK;
755    
756        retval = beforeControl();
757        if (!retval.isOK()) {
758            return retval;
759        }
760        
761        {    
762            Diff_MotionMagicDutyCycle_Position _diffAddFX_reqPtr;
763            if (_diffAddFX_req instanceof Diff_MotionMagicDutyCycle_Position) {
764                _diffAddFX_reqPtr = (Diff_MotionMagicDutyCycle_Position)_diffAddFX_req;
765                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
766                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
767            } else {
768                _diffAddFX_reqPtr = new Diff_MotionMagicDutyCycle_Position(AverageRequest, DifferentialRequest);
769                _diffAddFX_req = _diffAddFX_reqPtr;
770            }
771            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
772            
773            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
774            if (retval.isOK()) {
775                retval = _diffAddFX_retval;
776            }
777        }
778        
779        {
780            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
781            if (retval.isOK()) {
782                retval = _diffSubFX_retval;
783            }
784        }
785        
786        return retval;
787    }
788    
789    /**
790     * Sets the control request for this mechanism.
791     *
792     * @param AverageRequest    Average DutyCycleOut request of the mechanism.
793     * @param DifferentialRequest    Differential VelocityDutyCycle request of the
794     *                               mechanism. Note: The UpdateFreqHz parameter for
795     *                               this control request will be ignored by the
796     *                               control frame.
797     * @return Status Code of the request.
798     */
799    public StatusCode setControl(DutyCycleOut AverageRequest, VelocityDutyCycle DifferentialRequest)
800    {
801        var retval = StatusCode.OK;
802    
803        retval = beforeControl();
804        if (!retval.isOK()) {
805            return retval;
806        }
807        
808        {    
809            Diff_DutyCycleOut_Velocity _diffAddFX_reqPtr;
810            if (_diffAddFX_req instanceof Diff_DutyCycleOut_Velocity) {
811                _diffAddFX_reqPtr = (Diff_DutyCycleOut_Velocity)_diffAddFX_req;
812                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
813                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
814            } else {
815                _diffAddFX_reqPtr = new Diff_DutyCycleOut_Velocity(AverageRequest, DifferentialRequest);
816                _diffAddFX_req = _diffAddFX_reqPtr;
817            }
818            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
819            
820            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
821            if (retval.isOK()) {
822                retval = _diffAddFX_retval;
823            }
824        }
825        
826        {
827            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
828            if (retval.isOK()) {
829                retval = _diffSubFX_retval;
830            }
831        }
832        
833        return retval;
834    }
835    
836    /**
837     * Sets the control request for this mechanism.
838     *
839     * @param AverageRequest    Average PositionDutyCycle request of the mechanism.
840     * @param DifferentialRequest    Differential VelocityDutyCycle request of the
841     *                               mechanism. Note: The UpdateFreqHz parameter for
842     *                               this control request will be ignored by the
843     *                               control frame.
844     * @return Status Code of the request.
845     */
846    public StatusCode setControl(PositionDutyCycle AverageRequest, VelocityDutyCycle DifferentialRequest)
847    {
848        var retval = StatusCode.OK;
849    
850        retval = beforeControl();
851        if (!retval.isOK()) {
852            return retval;
853        }
854        
855        {    
856            Diff_PositionDutyCycle_Velocity _diffAddFX_reqPtr;
857            if (_diffAddFX_req instanceof Diff_PositionDutyCycle_Velocity) {
858                _diffAddFX_reqPtr = (Diff_PositionDutyCycle_Velocity)_diffAddFX_req;
859                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
860                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
861            } else {
862                _diffAddFX_reqPtr = new Diff_PositionDutyCycle_Velocity(AverageRequest, DifferentialRequest);
863                _diffAddFX_req = _diffAddFX_reqPtr;
864            }
865            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
866            
867            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
868            if (retval.isOK()) {
869                retval = _diffAddFX_retval;
870            }
871        }
872        
873        {
874            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
875            if (retval.isOK()) {
876                retval = _diffSubFX_retval;
877            }
878        }
879        
880        return retval;
881    }
882    
883    /**
884     * Sets the control request for this mechanism.
885     *
886     * @param AverageRequest    Average VelocityDutyCycle request of the mechanism.
887     * @param DifferentialRequest    Differential VelocityDutyCycle request of the
888     *                               mechanism. Note: The UpdateFreqHz parameter for
889     *                               this control request will be ignored by the
890     *                               control frame.
891     * @return Status Code of the request.
892     */
893    public StatusCode setControl(VelocityDutyCycle AverageRequest, VelocityDutyCycle DifferentialRequest)
894    {
895        var retval = StatusCode.OK;
896    
897        retval = beforeControl();
898        if (!retval.isOK()) {
899            return retval;
900        }
901        
902        {    
903            Diff_VelocityDutyCycle_Velocity _diffAddFX_reqPtr;
904            if (_diffAddFX_req instanceof Diff_VelocityDutyCycle_Velocity) {
905                _diffAddFX_reqPtr = (Diff_VelocityDutyCycle_Velocity)_diffAddFX_req;
906                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
907                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
908            } else {
909                _diffAddFX_reqPtr = new Diff_VelocityDutyCycle_Velocity(AverageRequest, DifferentialRequest);
910                _diffAddFX_req = _diffAddFX_reqPtr;
911            }
912            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
913            
914            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
915            if (retval.isOK()) {
916                retval = _diffAddFX_retval;
917            }
918        }
919        
920        {
921            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
922            if (retval.isOK()) {
923                retval = _diffSubFX_retval;
924            }
925        }
926        
927        return retval;
928    }
929    
930    /**
931     * Sets the control request for this mechanism.
932     *
933     * @param AverageRequest    Average MotionMagicDutyCycle request of the
934     *                          mechanism.
935     * @param DifferentialRequest    Differential VelocityDutyCycle request of the
936     *                               mechanism. Note: The UpdateFreqHz parameter for
937     *                               this control request will be ignored by the
938     *                               control frame.
939     * @return Status Code of the request.
940     */
941    public StatusCode setControl(MotionMagicDutyCycle AverageRequest, VelocityDutyCycle DifferentialRequest)
942    {
943        var retval = StatusCode.OK;
944    
945        retval = beforeControl();
946        if (!retval.isOK()) {
947            return retval;
948        }
949        
950        {    
951            Diff_MotionMagicDutyCycle_Velocity _diffAddFX_reqPtr;
952            if (_diffAddFX_req instanceof Diff_MotionMagicDutyCycle_Velocity) {
953                _diffAddFX_reqPtr = (Diff_MotionMagicDutyCycle_Velocity)_diffAddFX_req;
954                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
955                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
956            } else {
957                _diffAddFX_reqPtr = new Diff_MotionMagicDutyCycle_Velocity(AverageRequest, DifferentialRequest);
958                _diffAddFX_req = _diffAddFX_reqPtr;
959            }
960            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
961            
962            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
963            if (retval.isOK()) {
964                retval = _diffAddFX_retval;
965            }
966        }
967        
968        {
969            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
970            if (retval.isOK()) {
971                retval = _diffSubFX_retval;
972            }
973        }
974        
975        return retval;
976    }
977    
978    /**
979     * Sets the control request for this mechanism.
980     *
981     * @param AverageRequest    Average VoltageOut request of the mechanism.
982     * @param DifferentialRequest    Differential PositionVoltage request of the
983     *                               mechanism. Note: The UpdateFreqHz parameter for
984     *                               this control request will be ignored by the
985     *                               control frame.
986     * @return Status Code of the request.
987     */
988    public StatusCode setControl(VoltageOut AverageRequest, PositionVoltage DifferentialRequest)
989    {
990        var retval = StatusCode.OK;
991    
992        retval = beforeControl();
993        if (!retval.isOK()) {
994            return retval;
995        }
996        
997        {    
998            Diff_VoltageOut_Position _diffAddFX_reqPtr;
999            if (_diffAddFX_req instanceof Diff_VoltageOut_Position) {
1000                _diffAddFX_reqPtr = (Diff_VoltageOut_Position)_diffAddFX_req;
1001                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1002                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1003            } else {
1004                _diffAddFX_reqPtr = new Diff_VoltageOut_Position(AverageRequest, DifferentialRequest);
1005                _diffAddFX_req = _diffAddFX_reqPtr;
1006            }
1007            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1008            
1009            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1010            if (retval.isOK()) {
1011                retval = _diffAddFX_retval;
1012            }
1013        }
1014        
1015        {
1016            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1017            if (retval.isOK()) {
1018                retval = _diffSubFX_retval;
1019            }
1020        }
1021        
1022        return retval;
1023    }
1024    
1025    /**
1026     * Sets the control request for this mechanism.
1027     *
1028     * @param AverageRequest    Average PositionVoltage request of the mechanism.
1029     * @param DifferentialRequest    Differential PositionVoltage request of the
1030     *                               mechanism. Note: The UpdateFreqHz parameter for
1031     *                               this control request will be ignored by the
1032     *                               control frame.
1033     * @return Status Code of the request.
1034     */
1035    public StatusCode setControl(PositionVoltage AverageRequest, PositionVoltage DifferentialRequest)
1036    {
1037        var retval = StatusCode.OK;
1038    
1039        retval = beforeControl();
1040        if (!retval.isOK()) {
1041            return retval;
1042        }
1043        
1044        {    
1045            Diff_PositionVoltage_Position _diffAddFX_reqPtr;
1046            if (_diffAddFX_req instanceof Diff_PositionVoltage_Position) {
1047                _diffAddFX_reqPtr = (Diff_PositionVoltage_Position)_diffAddFX_req;
1048                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1049                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1050            } else {
1051                _diffAddFX_reqPtr = new Diff_PositionVoltage_Position(AverageRequest, DifferentialRequest);
1052                _diffAddFX_req = _diffAddFX_reqPtr;
1053            }
1054            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1055            
1056            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1057            if (retval.isOK()) {
1058                retval = _diffAddFX_retval;
1059            }
1060        }
1061        
1062        {
1063            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1064            if (retval.isOK()) {
1065                retval = _diffSubFX_retval;
1066            }
1067        }
1068        
1069        return retval;
1070    }
1071    
1072    /**
1073     * Sets the control request for this mechanism.
1074     *
1075     * @param AverageRequest    Average VelocityVoltage request of the mechanism.
1076     * @param DifferentialRequest    Differential PositionVoltage request of the
1077     *                               mechanism. Note: The UpdateFreqHz parameter for
1078     *                               this control request will be ignored by the
1079     *                               control frame.
1080     * @return Status Code of the request.
1081     */
1082    public StatusCode setControl(VelocityVoltage AverageRequest, PositionVoltage DifferentialRequest)
1083    {
1084        var retval = StatusCode.OK;
1085    
1086        retval = beforeControl();
1087        if (!retval.isOK()) {
1088            return retval;
1089        }
1090        
1091        {    
1092            Diff_VelocityVoltage_Position _diffAddFX_reqPtr;
1093            if (_diffAddFX_req instanceof Diff_VelocityVoltage_Position) {
1094                _diffAddFX_reqPtr = (Diff_VelocityVoltage_Position)_diffAddFX_req;
1095                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1096                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1097            } else {
1098                _diffAddFX_reqPtr = new Diff_VelocityVoltage_Position(AverageRequest, DifferentialRequest);
1099                _diffAddFX_req = _diffAddFX_reqPtr;
1100            }
1101            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1102            
1103            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1104            if (retval.isOK()) {
1105                retval = _diffAddFX_retval;
1106            }
1107        }
1108        
1109        {
1110            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1111            if (retval.isOK()) {
1112                retval = _diffSubFX_retval;
1113            }
1114        }
1115        
1116        return retval;
1117    }
1118    
1119    /**
1120     * Sets the control request for this mechanism.
1121     *
1122     * @param AverageRequest    Average MotionMagicVoltage request of the mechanism.
1123     * @param DifferentialRequest    Differential PositionVoltage request of the
1124     *                               mechanism. Note: The UpdateFreqHz parameter for
1125     *                               this control request will be ignored by the
1126     *                               control frame.
1127     * @return Status Code of the request.
1128     */
1129    public StatusCode setControl(MotionMagicVoltage AverageRequest, PositionVoltage DifferentialRequest)
1130    {
1131        var retval = StatusCode.OK;
1132    
1133        retval = beforeControl();
1134        if (!retval.isOK()) {
1135            return retval;
1136        }
1137        
1138        {    
1139            Diff_MotionMagicVoltage_Position _diffAddFX_reqPtr;
1140            if (_diffAddFX_req instanceof Diff_MotionMagicVoltage_Position) {
1141                _diffAddFX_reqPtr = (Diff_MotionMagicVoltage_Position)_diffAddFX_req;
1142                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1143                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1144            } else {
1145                _diffAddFX_reqPtr = new Diff_MotionMagicVoltage_Position(AverageRequest, DifferentialRequest);
1146                _diffAddFX_req = _diffAddFX_reqPtr;
1147            }
1148            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1149            
1150            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1151            if (retval.isOK()) {
1152                retval = _diffAddFX_retval;
1153            }
1154        }
1155        
1156        {
1157            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1158            if (retval.isOK()) {
1159                retval = _diffSubFX_retval;
1160            }
1161        }
1162        
1163        return retval;
1164    }
1165    
1166    /**
1167     * Sets the control request for this mechanism.
1168     *
1169     * @param AverageRequest    Average VoltageOut request of the mechanism.
1170     * @param DifferentialRequest    Differential VelocityVoltage request of the
1171     *                               mechanism. Note: The UpdateFreqHz parameter for
1172     *                               this control request will be ignored by the
1173     *                               control frame.
1174     * @return Status Code of the request.
1175     */
1176    public StatusCode setControl(VoltageOut AverageRequest, VelocityVoltage DifferentialRequest)
1177    {
1178        var retval = StatusCode.OK;
1179    
1180        retval = beforeControl();
1181        if (!retval.isOK()) {
1182            return retval;
1183        }
1184        
1185        {    
1186            Diff_VoltageOut_Velocity _diffAddFX_reqPtr;
1187            if (_diffAddFX_req instanceof Diff_VoltageOut_Velocity) {
1188                _diffAddFX_reqPtr = (Diff_VoltageOut_Velocity)_diffAddFX_req;
1189                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1190                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1191            } else {
1192                _diffAddFX_reqPtr = new Diff_VoltageOut_Velocity(AverageRequest, DifferentialRequest);
1193                _diffAddFX_req = _diffAddFX_reqPtr;
1194            }
1195            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1196            
1197            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1198            if (retval.isOK()) {
1199                retval = _diffAddFX_retval;
1200            }
1201        }
1202        
1203        {
1204            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1205            if (retval.isOK()) {
1206                retval = _diffSubFX_retval;
1207            }
1208        }
1209        
1210        return retval;
1211    }
1212    
1213    /**
1214     * Sets the control request for this mechanism.
1215     *
1216     * @param AverageRequest    Average PositionVoltage request of the mechanism.
1217     * @param DifferentialRequest    Differential VelocityVoltage request of the
1218     *                               mechanism. Note: The UpdateFreqHz parameter for
1219     *                               this control request will be ignored by the
1220     *                               control frame.
1221     * @return Status Code of the request.
1222     */
1223    public StatusCode setControl(PositionVoltage AverageRequest, VelocityVoltage DifferentialRequest)
1224    {
1225        var retval = StatusCode.OK;
1226    
1227        retval = beforeControl();
1228        if (!retval.isOK()) {
1229            return retval;
1230        }
1231        
1232        {    
1233            Diff_PositionVoltage_Velocity _diffAddFX_reqPtr;
1234            if (_diffAddFX_req instanceof Diff_PositionVoltage_Velocity) {
1235                _diffAddFX_reqPtr = (Diff_PositionVoltage_Velocity)_diffAddFX_req;
1236                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1237                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1238            } else {
1239                _diffAddFX_reqPtr = new Diff_PositionVoltage_Velocity(AverageRequest, DifferentialRequest);
1240                _diffAddFX_req = _diffAddFX_reqPtr;
1241            }
1242            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1243            
1244            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1245            if (retval.isOK()) {
1246                retval = _diffAddFX_retval;
1247            }
1248        }
1249        
1250        {
1251            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1252            if (retval.isOK()) {
1253                retval = _diffSubFX_retval;
1254            }
1255        }
1256        
1257        return retval;
1258    }
1259    
1260    /**
1261     * Sets the control request for this mechanism.
1262     *
1263     * @param AverageRequest    Average VelocityVoltage request of the mechanism.
1264     * @param DifferentialRequest    Differential VelocityVoltage request of the
1265     *                               mechanism. Note: The UpdateFreqHz parameter for
1266     *                               this control request will be ignored by the
1267     *                               control frame.
1268     * @return Status Code of the request.
1269     */
1270    public StatusCode setControl(VelocityVoltage AverageRequest, VelocityVoltage DifferentialRequest)
1271    {
1272        var retval = StatusCode.OK;
1273    
1274        retval = beforeControl();
1275        if (!retval.isOK()) {
1276            return retval;
1277        }
1278        
1279        {    
1280            Diff_VelocityVoltage_Velocity _diffAddFX_reqPtr;
1281            if (_diffAddFX_req instanceof Diff_VelocityVoltage_Velocity) {
1282                _diffAddFX_reqPtr = (Diff_VelocityVoltage_Velocity)_diffAddFX_req;
1283                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1284                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1285            } else {
1286                _diffAddFX_reqPtr = new Diff_VelocityVoltage_Velocity(AverageRequest, DifferentialRequest);
1287                _diffAddFX_req = _diffAddFX_reqPtr;
1288            }
1289            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1290            
1291            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1292            if (retval.isOK()) {
1293                retval = _diffAddFX_retval;
1294            }
1295        }
1296        
1297        {
1298            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1299            if (retval.isOK()) {
1300                retval = _diffSubFX_retval;
1301            }
1302        }
1303        
1304        return retval;
1305    }
1306    
1307    /**
1308     * Sets the control request for this mechanism.
1309     *
1310     * @param AverageRequest    Average MotionMagicVoltage request of the mechanism.
1311     * @param DifferentialRequest    Differential VelocityVoltage request of the
1312     *                               mechanism. Note: The UpdateFreqHz parameter for
1313     *                               this control request will be ignored by the
1314     *                               control frame.
1315     * @return Status Code of the request.
1316     */
1317    public StatusCode setControl(MotionMagicVoltage AverageRequest, VelocityVoltage DifferentialRequest)
1318    {
1319        var retval = StatusCode.OK;
1320    
1321        retval = beforeControl();
1322        if (!retval.isOK()) {
1323            return retval;
1324        }
1325        
1326        {    
1327            Diff_MotionMagicVoltage_Velocity _diffAddFX_reqPtr;
1328            if (_diffAddFX_req instanceof Diff_MotionMagicVoltage_Velocity) {
1329                _diffAddFX_reqPtr = (Diff_MotionMagicVoltage_Velocity)_diffAddFX_req;
1330                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1331                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1332            } else {
1333                _diffAddFX_reqPtr = new Diff_MotionMagicVoltage_Velocity(AverageRequest, DifferentialRequest);
1334                _diffAddFX_req = _diffAddFX_reqPtr;
1335            }
1336            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1337            
1338            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1339            if (retval.isOK()) {
1340                retval = _diffAddFX_retval;
1341            }
1342        }
1343        
1344        {
1345            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1346            if (retval.isOK()) {
1347                retval = _diffSubFX_retval;
1348            }
1349        }
1350        
1351        return retval;
1352    }
1353    
1354    /**
1355     * Sets the control request for this mechanism.
1356     *
1357     * @param AverageRequest    Average TorqueCurrentFOC request of the mechanism.
1358     * @param DifferentialRequest    Differential PositionTorqueCurrentFOC request
1359     *                               of the mechanism. Note: The UpdateFreqHz
1360     *                               parameter for this control request will be
1361     *                               ignored by the control frame.
1362     * @return Status Code of the request.
1363     */
1364    public StatusCode setControl(TorqueCurrentFOC AverageRequest, PositionTorqueCurrentFOC DifferentialRequest)
1365    {
1366        var retval = StatusCode.OK;
1367    
1368        retval = beforeControl();
1369        if (!retval.isOK()) {
1370            return retval;
1371        }
1372        
1373        {    
1374            Diff_TorqueCurrentFOC_Position _diffAddFX_reqPtr;
1375            if (_diffAddFX_req instanceof Diff_TorqueCurrentFOC_Position) {
1376                _diffAddFX_reqPtr = (Diff_TorqueCurrentFOC_Position)_diffAddFX_req;
1377                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1378                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1379            } else {
1380                _diffAddFX_reqPtr = new Diff_TorqueCurrentFOC_Position(AverageRequest, DifferentialRequest);
1381                _diffAddFX_req = _diffAddFX_reqPtr;
1382            }
1383            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1384            
1385            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1386            if (retval.isOK()) {
1387                retval = _diffAddFX_retval;
1388            }
1389        }
1390        
1391        {
1392            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1393            if (retval.isOK()) {
1394                retval = _diffSubFX_retval;
1395            }
1396        }
1397        
1398        return retval;
1399    }
1400    
1401    /**
1402     * Sets the control request for this mechanism.
1403     *
1404     * @param AverageRequest    Average PositionTorqueCurrentFOC request of the
1405     *                          mechanism.
1406     * @param DifferentialRequest    Differential PositionTorqueCurrentFOC request
1407     *                               of the mechanism. Note: The UpdateFreqHz
1408     *                               parameter for this control request will be
1409     *                               ignored by the control frame.
1410     * @return Status Code of the request.
1411     */
1412    public StatusCode setControl(PositionTorqueCurrentFOC AverageRequest, PositionTorqueCurrentFOC DifferentialRequest)
1413    {
1414        var retval = StatusCode.OK;
1415    
1416        retval = beforeControl();
1417        if (!retval.isOK()) {
1418            return retval;
1419        }
1420        
1421        {    
1422            Diff_PositionTorqueCurrentFOC_Position _diffAddFX_reqPtr;
1423            if (_diffAddFX_req instanceof Diff_PositionTorqueCurrentFOC_Position) {
1424                _diffAddFX_reqPtr = (Diff_PositionTorqueCurrentFOC_Position)_diffAddFX_req;
1425                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1426                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1427            } else {
1428                _diffAddFX_reqPtr = new Diff_PositionTorqueCurrentFOC_Position(AverageRequest, DifferentialRequest);
1429                _diffAddFX_req = _diffAddFX_reqPtr;
1430            }
1431            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1432            
1433            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1434            if (retval.isOK()) {
1435                retval = _diffAddFX_retval;
1436            }
1437        }
1438        
1439        {
1440            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1441            if (retval.isOK()) {
1442                retval = _diffSubFX_retval;
1443            }
1444        }
1445        
1446        return retval;
1447    }
1448    
1449    /**
1450     * Sets the control request for this mechanism.
1451     *
1452     * @param AverageRequest    Average VelocityTorqueCurrentFOC request of the
1453     *                          mechanism.
1454     * @param DifferentialRequest    Differential PositionTorqueCurrentFOC request
1455     *                               of the mechanism. Note: The UpdateFreqHz
1456     *                               parameter for this control request will be
1457     *                               ignored by the control frame.
1458     * @return Status Code of the request.
1459     */
1460    public StatusCode setControl(VelocityTorqueCurrentFOC AverageRequest, PositionTorqueCurrentFOC DifferentialRequest)
1461    {
1462        var retval = StatusCode.OK;
1463    
1464        retval = beforeControl();
1465        if (!retval.isOK()) {
1466            return retval;
1467        }
1468        
1469        {    
1470            Diff_VelocityTorqueCurrentFOC_Position _diffAddFX_reqPtr;
1471            if (_diffAddFX_req instanceof Diff_VelocityTorqueCurrentFOC_Position) {
1472                _diffAddFX_reqPtr = (Diff_VelocityTorqueCurrentFOC_Position)_diffAddFX_req;
1473                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1474                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1475            } else {
1476                _diffAddFX_reqPtr = new Diff_VelocityTorqueCurrentFOC_Position(AverageRequest, DifferentialRequest);
1477                _diffAddFX_req = _diffAddFX_reqPtr;
1478            }
1479            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1480            
1481            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1482            if (retval.isOK()) {
1483                retval = _diffAddFX_retval;
1484            }
1485        }
1486        
1487        {
1488            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1489            if (retval.isOK()) {
1490                retval = _diffSubFX_retval;
1491            }
1492        }
1493        
1494        return retval;
1495    }
1496    
1497    /**
1498     * Sets the control request for this mechanism.
1499     *
1500     * @param AverageRequest    Average MotionMagicTorqueCurrentFOC request of the
1501     *                          mechanism.
1502     * @param DifferentialRequest    Differential PositionTorqueCurrentFOC request
1503     *                               of the mechanism. Note: The UpdateFreqHz
1504     *                               parameter for this control request will be
1505     *                               ignored by the control frame.
1506     * @return Status Code of the request.
1507     */
1508    public StatusCode setControl(MotionMagicTorqueCurrentFOC AverageRequest, PositionTorqueCurrentFOC DifferentialRequest)
1509    {
1510        var retval = StatusCode.OK;
1511    
1512        retval = beforeControl();
1513        if (!retval.isOK()) {
1514            return retval;
1515        }
1516        
1517        {    
1518            Diff_MotionMagicTorqueCurrentFOC_Position _diffAddFX_reqPtr;
1519            if (_diffAddFX_req instanceof Diff_MotionMagicTorqueCurrentFOC_Position) {
1520                _diffAddFX_reqPtr = (Diff_MotionMagicTorqueCurrentFOC_Position)_diffAddFX_req;
1521                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1522                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1523            } else {
1524                _diffAddFX_reqPtr = new Diff_MotionMagicTorqueCurrentFOC_Position(AverageRequest, DifferentialRequest);
1525                _diffAddFX_req = _diffAddFX_reqPtr;
1526            }
1527            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1528            
1529            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1530            if (retval.isOK()) {
1531                retval = _diffAddFX_retval;
1532            }
1533        }
1534        
1535        {
1536            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1537            if (retval.isOK()) {
1538                retval = _diffSubFX_retval;
1539            }
1540        }
1541        
1542        return retval;
1543    }
1544    
1545    /**
1546     * Sets the control request for this mechanism.
1547     *
1548     * @param AverageRequest    Average TorqueCurrentFOC request of the mechanism.
1549     * @param DifferentialRequest    Differential VelocityTorqueCurrentFOC request
1550     *                               of the mechanism. Note: The UpdateFreqHz
1551     *                               parameter for this control request will be
1552     *                               ignored by the control frame.
1553     * @return Status Code of the request.
1554     */
1555    public StatusCode setControl(TorqueCurrentFOC AverageRequest, VelocityTorqueCurrentFOC DifferentialRequest)
1556    {
1557        var retval = StatusCode.OK;
1558    
1559        retval = beforeControl();
1560        if (!retval.isOK()) {
1561            return retval;
1562        }
1563        
1564        {    
1565            Diff_TorqueCurrentFOC_Velocity _diffAddFX_reqPtr;
1566            if (_diffAddFX_req instanceof Diff_TorqueCurrentFOC_Velocity) {
1567                _diffAddFX_reqPtr = (Diff_TorqueCurrentFOC_Velocity)_diffAddFX_req;
1568                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1569                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1570            } else {
1571                _diffAddFX_reqPtr = new Diff_TorqueCurrentFOC_Velocity(AverageRequest, DifferentialRequest);
1572                _diffAddFX_req = _diffAddFX_reqPtr;
1573            }
1574            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1575            
1576            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1577            if (retval.isOK()) {
1578                retval = _diffAddFX_retval;
1579            }
1580        }
1581        
1582        {
1583            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1584            if (retval.isOK()) {
1585                retval = _diffSubFX_retval;
1586            }
1587        }
1588        
1589        return retval;
1590    }
1591    
1592    /**
1593     * Sets the control request for this mechanism.
1594     *
1595     * @param AverageRequest    Average PositionTorqueCurrentFOC request of the
1596     *                          mechanism.
1597     * @param DifferentialRequest    Differential VelocityTorqueCurrentFOC request
1598     *                               of the mechanism. Note: The UpdateFreqHz
1599     *                               parameter for this control request will be
1600     *                               ignored by the control frame.
1601     * @return Status Code of the request.
1602     */
1603    public StatusCode setControl(PositionTorqueCurrentFOC AverageRequest, VelocityTorqueCurrentFOC DifferentialRequest)
1604    {
1605        var retval = StatusCode.OK;
1606    
1607        retval = beforeControl();
1608        if (!retval.isOK()) {
1609            return retval;
1610        }
1611        
1612        {    
1613            Diff_PositionTorqueCurrentFOC_Velocity _diffAddFX_reqPtr;
1614            if (_diffAddFX_req instanceof Diff_PositionTorqueCurrentFOC_Velocity) {
1615                _diffAddFX_reqPtr = (Diff_PositionTorqueCurrentFOC_Velocity)_diffAddFX_req;
1616                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1617                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1618            } else {
1619                _diffAddFX_reqPtr = new Diff_PositionTorqueCurrentFOC_Velocity(AverageRequest, DifferentialRequest);
1620                _diffAddFX_req = _diffAddFX_reqPtr;
1621            }
1622            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1623            
1624            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1625            if (retval.isOK()) {
1626                retval = _diffAddFX_retval;
1627            }
1628        }
1629        
1630        {
1631            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1632            if (retval.isOK()) {
1633                retval = _diffSubFX_retval;
1634            }
1635        }
1636        
1637        return retval;
1638    }
1639    
1640    /**
1641     * Sets the control request for this mechanism.
1642     *
1643     * @param AverageRequest    Average VelocityTorqueCurrentFOC request of the
1644     *                          mechanism.
1645     * @param DifferentialRequest    Differential VelocityTorqueCurrentFOC request
1646     *                               of the mechanism. Note: The UpdateFreqHz
1647     *                               parameter for this control request will be
1648     *                               ignored by the control frame.
1649     * @return Status Code of the request.
1650     */
1651    public StatusCode setControl(VelocityTorqueCurrentFOC AverageRequest, VelocityTorqueCurrentFOC DifferentialRequest)
1652    {
1653        var retval = StatusCode.OK;
1654    
1655        retval = beforeControl();
1656        if (!retval.isOK()) {
1657            return retval;
1658        }
1659        
1660        {    
1661            Diff_VelocityTorqueCurrentFOC_Velocity _diffAddFX_reqPtr;
1662            if (_diffAddFX_req instanceof Diff_VelocityTorqueCurrentFOC_Velocity) {
1663                _diffAddFX_reqPtr = (Diff_VelocityTorqueCurrentFOC_Velocity)_diffAddFX_req;
1664                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1665                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1666            } else {
1667                _diffAddFX_reqPtr = new Diff_VelocityTorqueCurrentFOC_Velocity(AverageRequest, DifferentialRequest);
1668                _diffAddFX_req = _diffAddFX_reqPtr;
1669            }
1670            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1671            
1672            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1673            if (retval.isOK()) {
1674                retval = _diffAddFX_retval;
1675            }
1676        }
1677        
1678        {
1679            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1680            if (retval.isOK()) {
1681                retval = _diffSubFX_retval;
1682            }
1683        }
1684        
1685        return retval;
1686    }
1687    
1688    /**
1689     * Sets the control request for this mechanism.
1690     *
1691     * @param AverageRequest    Average MotionMagicTorqueCurrentFOC request of the
1692     *                          mechanism.
1693     * @param DifferentialRequest    Differential VelocityTorqueCurrentFOC request
1694     *                               of the mechanism. Note: The UpdateFreqHz
1695     *                               parameter for this control request will be
1696     *                               ignored by the control frame.
1697     * @return Status Code of the request.
1698     */
1699    public StatusCode setControl(MotionMagicTorqueCurrentFOC AverageRequest, VelocityTorqueCurrentFOC DifferentialRequest)
1700    {
1701        var retval = StatusCode.OK;
1702    
1703        retval = beforeControl();
1704        if (!retval.isOK()) {
1705            return retval;
1706        }
1707        
1708        {    
1709            Diff_MotionMagicTorqueCurrentFOC_Velocity _diffAddFX_reqPtr;
1710            if (_diffAddFX_req instanceof Diff_MotionMagicTorqueCurrentFOC_Velocity) {
1711                _diffAddFX_reqPtr = (Diff_MotionMagicTorqueCurrentFOC_Velocity)_diffAddFX_req;
1712                _diffAddFX_reqPtr.AverageRequest = AverageRequest;
1713                _diffAddFX_reqPtr.DifferentialRequest = DifferentialRequest;
1714            } else {
1715                _diffAddFX_reqPtr = new Diff_MotionMagicTorqueCurrentFOC_Velocity(AverageRequest, DifferentialRequest);
1716                _diffAddFX_req = _diffAddFX_reqPtr;
1717            }
1718            _diffAddFX_reqPtr.UpdateFreqHz = _diffAddFX_reqPtr.AverageRequest.UpdateFreqHz;
1719            
1720            final var _diffAddFX_retval = _diffAddFX.setControl(_diffAddFX_reqPtr);
1721            if (retval.isOK()) {
1722                retval = _diffAddFX_retval;
1723            }
1724        }
1725        
1726        {
1727            final var _diffSubFX_retval = _diffSubFX.setControl(_diffFollow);
1728            if (retval.isOK()) {
1729                retval = _diffSubFX_retval;
1730            }
1731        }
1732        
1733        return retval;
1734    }
1735    
1736}