Skip to content

Conversation

@SyntaxBreak
Copy link
Contributor

No description provided.

.with_k_s(0)
.with_k_v(0)
.with_k_a(0)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is an arm, we'll also want a feedforward term to compensate for gravity.

I presume this has been CAD'ed by now? I'd recommend plugging it into https://www.reca.lc/arm to get some theoretical gains.


@feedback
def get_absolute_deployment_encoder_position(self):
return self.deployment_encoder.get()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure there won't be any offset?

@rafzip
Copy link
Collaborator

rafzip commented Feb 8, 2026

@greptileai

@greptile-apps
Copy link

greptile-apps bot commented Feb 8, 2026

Greptile Overview

Greptile Summary

Adds a deployable intake demo by introducing a TalonFX-driven deployer with a DutyCycleEncoder absolute position reference (components/intake.py), new IDs for the deployer and encoder (ids.py), and binds deploy/retract to the gamepad POV in testPeriodic (robot.py).

The main integration points are: MyRobot (operator input) → IntakeComponent (target state) → motor controllers (SparkMax intake, TalonSRX funnels, TalonFX deployer).

Confidence Score: 2/5

  • Not safe to merge as-is due to deployer control unit/zeroing bugs and incorrect POV conditionals.
  • The deployer TalonFX is commanded with values labeled as degrees but used as position setpoints, and its initial position is seeded from an unscaled DutyCycleEncoder fraction; both issues will deterministically drive the mechanism to incorrect positions. Additionally, the POV checks in testPeriodic use truthiness and will trigger deploy/retract when the POV is not pressed.
  • components/intake.py, robot.py

Important Files Changed

Filename Overview
components/intake.py Adds deployable intake (TalonFX + DutyCycleEncoder) and separate intake/funnel outputs; currently mixes degrees with TalonFX position units and seeds position from raw DutyCycleEncoder fraction.
ids.py Adds CAN ID for intake deployer Talon and DIO channel for the deployment encoder; no functional issues spotted.
robot.py Adds POV controls to deploy/retract intake in testPeriodic; uses truthiness of getPOV() leading to commands running when POV not pressed.

Sequence Diagram

sequenceDiagram
    participant Driver as Driver (XboxController)
    participant Robot as MyRobot.testPeriodic
    participant Intake as IntakeComponent
    participant Deployer as TalonFX (deployment_motor)
    participant Encoder as DutyCycleEncoder

    Note over Intake: __init__ configures deployer
    Intake->>Encoder: get()
    Intake->>Deployer: set_position(abs_fraction)

    Driver->>Robot: POV angle changes
    alt POV == 0 (deploy)
        Robot->>Intake: deploy_intake()
        Intake-->>Intake: target_deployment_angle = DEPLOYED_INTAKE_ANGLE
    else POV == 180 (retract)
        Robot->>Intake: retract_intake()
        Intake-->>Intake: target_deployment_angle = RETRACTED_INTAKE_ANGLE
    end

    Robot->>Intake: intake.execute()
    Intake->>Deployer: set_position(target_deployment_angle)

Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 19 to 22
RETRACTED_INTAKE_ANGLE = 0
DEPLOYED_INTAKE_ANGLE = 90

funnel_output = tunable(1.0)
target_deployment_angle = RETRACTED_INTAKE_ANGLE
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deployment angle units mismatch
TalonFX.set_position() expects a position in mechanism rotations (after sensor_to_mechanism_ratio), but target_deployment_angle is being set to 0/90 degrees and passed directly at components/intake.py:85. Unless your mechanism is explicitly defined as “degrees as rotations” (it isn’t here), this will drive the deployer to 90 rotations instead of 90°.

Suggested change
RETRACTED_INTAKE_ANGLE = 0
DEPLOYED_INTAKE_ANGLE = 90
funnel_output = tunable(1.0)
target_deployment_angle = RETRACTED_INTAKE_ANGLE
RETRACTED_INTAKE_ANGLE = 0.0
DEPLOYED_INTAKE_ANGLE = 0.25 # 90 deg = 0.25 rotations

(Or rename to _ROTATIONS and convert from degrees before calling set_position().)

Prompt To Fix With AI
This is a comment left during a code review.
Path: components/intake.py
Line: 19:22

Comment:
**Deployment angle units mismatch**
`TalonFX.set_position()` expects a position in *mechanism rotations* (after `sensor_to_mechanism_ratio`), but `target_deployment_angle` is being set to `0`/`90` degrees and passed directly at `components/intake.py:85`. Unless your mechanism is explicitly defined as “degrees as rotations” (it isn’t here), this will drive the deployer to 90 rotations instead of 90°.

```suggestion
    RETRACTED_INTAKE_ANGLE = 0.0
    DEPLOYED_INTAKE_ANGLE = 0.25  # 90 deg = 0.25 rotations
```
(Or rename to `_ROTATIONS` and convert from degrees before calling `set_position()`.)

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 26 to 28
@feedback
def get_absolute_deployment_encoder_position(self):
return self.deployment_encoder.get()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DutyCycleEncoder range misuse
DutyCycleEncoder.get() returns the absolute position as a fraction of a rotation in [0.0, 1.0), not an angle/rotation value in the same units as your deployer mechanism. At components/intake.py:65-67 you seed the TalonFX integrated position with this raw fraction, which will usually mis-zero the mechanism (and it will jump at wraparound near 1.0→0.0).

You likely want to apply an offset and scale to mechanism rotations (and account for wrap) before calling set_position().

Prompt To Fix With AI
This is a comment left during a code review.
Path: components/intake.py
Line: 26:28

Comment:
**DutyCycleEncoder range misuse**
`DutyCycleEncoder.get()` returns the absolute position as a fraction of a rotation in `[0.0, 1.0)`, not an angle/rotation value in the same units as your deployer mechanism. At `components/intake.py:65-67` you seed the TalonFX integrated position with this raw fraction, which will usually mis-zero the mechanism (and it will jump at wraparound near 1.0→0.0).

You likely want to apply an offset and scale to mechanism rotations (and account for wrap) before calling `set_position()`.


How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +235 to +245
if self.gamepad.getPOV(0):
self.intake.deploy_intake()

if self.gamepad.getPOV(180):
self.intake.retract_intake()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POV check always true
XboxController.getPOV() returns an angle in degrees (0/90/180/270) or -1 when not pressed. In Python, any non-zero int (including -1) is truthy, so if self.gamepad.getPOV(0): at robot.py:235 will run when the POV is not pressed, and if self.gamepad.getPOV(180): will also run for most angles.

Compare explicitly instead:

Suggested change
if self.gamepad.getPOV(0):
self.intake.deploy_intake()
if self.gamepad.getPOV(180):
self.intake.retract_intake()
if self.gamepad.getPOV() == 0:
self.intake.deploy_intake()
if self.gamepad.getPOV() == 180:
self.intake.retract_intake()
Prompt To Fix With AI
This is a comment left during a code review.
Path: robot.py
Line: 235:239

Comment:
**POV check always true**
`XboxController.getPOV()` returns an angle in degrees (0/90/180/270) or `-1` when not pressed. In Python, any non-zero int (including `-1`) is truthy, so `if self.gamepad.getPOV(0):` at `robot.py:235` will run when the POV is *not pressed*, and `if self.gamepad.getPOV(180):` will also run for most angles.

Compare explicitly instead:
```suggestion
        if self.gamepad.getPOV() == 0:
            self.intake.deploy_intake()

        if self.gamepad.getPOV() == 180:
            self.intake.retract_intake()
```


How can I resolve this? If you propose a fix, please make it concise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@greptileai you didn't explain why passing an angle as the argument to getPOV is wrong

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - I should have explained that.

getPOV() takes a POV index (which controller POV hat to read), not an angle to check against. For a standard Xbox controller, there's only one POV hat at index 0.

So getPOV(0) returns the angle of POV hat #0, while getPOV(180) is trying to read POV hat #180 (which doesn't exist - it will return -1).

The correct approach is:

Suggested change
if self.gamepad.getPOV(0):
self.intake.deploy_intake()
if self.gamepad.getPOV(180):
self.intake.retract_intake()
pov = self.gamepad.getPOV(0)
if pov == 0:
self.intake.deploy_intake()
if pov == 180:
self.intake.retract_intake()

@LHowe-a11y LHowe-a11y force-pushed the not-rafs-deployable-intake branch from 9bd6e9c to 7f3b671 Compare February 9, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants