-
Notifications
You must be signed in to change notification settings - Fork 0
rename OICondition inner class to Condition. update example OI to use OIFragment and Conditions. #77
base: main
Are you sure you want to change the base?
rename OICondition inner class to Condition. update example OI to use OIFragment and Conditions. #77
Changes from 7 commits
e2bf787
22476ed
31007cb
bd9f4b7
56c7618
a8b0e93
a28ab66
6564a84
e38c8fe
6baa171
a4c904b
ccdf0f8
910e9b3
1bb3c54
ea53d0f
9f3b6bf
c7a7e2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.team766.robot.example; | ||
|
||
import com.team766.framework.Context; | ||
import com.team766.framework.OIFragment; | ||
import com.team766.hal.JoystickReader; | ||
import com.team766.robot.example.constants.InputConstants; | ||
import com.team766.robot.example.procedures.*; | ||
|
||
public class DriverOI extends OIFragment { | ||
private final JoystickReader joystick; | ||
private double joystickX; | ||
private double joystickY; | ||
|
||
// add any conditions (joystick inputs, etc) | ||
private Condition button1; | ||
private Condition moveJoystick; | ||
|
||
// add any mechanisms to the constructor arguments as well | ||
public DriverOI(JoystickReader joystick) { | ||
super("DriverOI"); | ||
this.joystick = joystick; | ||
|
||
button1 = new Condition(() -> joystick.getButton(InputConstants.BUTTON_TRIGGER)); | ||
moveJoystick = new Condition(() -> Math.abs(joystickX) > 0 || Math.abs(joystickY) > 0); | ||
} | ||
|
||
@Override | ||
protected void handlePre() { | ||
joystickX = joystick.getAxis(InputConstants.AXIS_X); | ||
joystickY = joystick.getAxis(InputConstants.AXIS_Y); | ||
} | ||
|
||
@Override | ||
protected void handleOI(Context context) { | ||
if (button1.isNewlyTriggering()) { | ||
// handle button press | ||
} else if (button1.isFinishedTriggering()) { | ||
// handle button release | ||
} | ||
|
||
if (moveJoystick.isTriggering()) { | ||
// handle joystick movement | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,23 +5,25 @@ | |
import com.team766.hal.JoystickReader; | ||
import com.team766.hal.RobotProvider; | ||
import com.team766.logging.Category; | ||
import com.team766.robot.example.procedures.*; | ||
|
||
/** | ||
* This class is the glue that binds the controls on the physical operator | ||
* interface to the code that allow control of the robot. | ||
*/ | ||
public class OI extends Procedure { | ||
private JoystickReader joystick0; | ||
private JoystickReader joystick1; | ||
private JoystickReader joystick2; | ||
// input devices | ||
private final JoystickReader leftJoystick; | ||
private final JoystickReader gamepad; | ||
|
||
// OIFragments (driver, boxop, etc) | ||
private final DriverOI driverOI; | ||
|
||
public OI() { | ||
loggerCategory = Category.OPERATOR_INTERFACE; | ||
|
||
joystick0 = RobotProvider.instance.getJoystick(0); | ||
joystick1 = RobotProvider.instance.getJoystick(1); | ||
joystick2 = RobotProvider.instance.getJoystick(2); | ||
leftJoystick = RobotProvider.instance.getJoystick(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should there not be a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for these examples (most frequently used with BurroBots - a competition bot would typically use Swerve drive with the I can also include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
gamepad = RobotProvider.instance.getJoystick(1); | ||
driverOI = new DriverOI(leftJoystick); | ||
} | ||
|
||
public void run(final Context context) { | ||
|
@@ -30,8 +32,8 @@ public void run(final Context context) { | |
context.waitFor(() -> RobotProvider.instance.hasNewDriverStationData()); | ||
RobotProvider.instance.refreshDriverStationData(); | ||
|
||
// Add driver controls here - make sure to take/release ownership | ||
// of mechanisms when appropriate. | ||
// call each of the OI fragment's runOI methods. | ||
driverOI.runOI(context); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.team766.robot.example.constants; | ||
|
||
public class InputConstants { | ||
// this class only contains constants - should never be instantiated | ||
private InputConstants() {} | ||
|
||
public static final int AXIS_X = 0; | ||
public static final int AXIS_Y = 1; | ||
|
||
public static final int BUTTON_TRIGGER = 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
non-blocking, because i'm not sure if i have a better way to do this, but
it seems like the code around conditions is getting pretty spread out, which hurts readability. it requires code in the constructor, in handlePre, and in handleOI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, let's discuss.
this is less about code for conditions and more about code used in the OI that's also used in conditions.
problem to solve - allow for some code to run before conditions are evaluated (since we moved that to an explicit step run by something like the
OIFragment
). we could simplify by having everything inhandleOI
, at the cost of "missing a frame".I understand the concern - open to a different approach that allows code to run before the evaluation step.
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thinking about alternatives - one could be to make this part of the Conditions - tho I don't think that would be more readable.
eg, that woud make updating variables a side effect.. and given that lambdas are supposed to be short, devs might end up moving some of the logic into helper methods called via method references.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of ideas. I'm not sure any of them is the best, though I like (2) because it doesn't require class member variables.
Condition
has aninvalidate()
method thatOIFragment
calls beforehandleOI
. Then conditions are lazily evaluated on the first call to e.g.isTriggering
Condition
has anevaluate
method that the user is required to call duringhandleOI
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, I'd be a bit uncomfortable with
2
since that feels a bit error-prone, eg if devs miss calling that, they'll wonder why their conditions aren't triggering as expected.if we wanted to avoid having a
preHandle
, we could recommend conditions be more self-contained vs depend on these intermediate member variables that store their own state. (nothing would prevent someone from doing that eg in a helper method the developer set up and called from their conditions but those calls would be more obviously visible).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i thought about requesting that conditions be more self-contained, but then I thought about what if the condition is based off of some complex code, for example processing vision output or something. I guess in that case, probably that complex processing should be moved into a Mechanism or ProcedureWithValue or something. but it still seems like something that someone might want to do, even if it was just temporary.
what if we combined (1) and (2)? the OIFragment invalidates the Condition prior to calling handleOI, and if you try to query the Condition before evaluating it, it raises an exception. we could also raise an exception if someone tries to evaluate a condition multiple times in a single frame (i.e. evaluate is called when the Condition is not invalidated)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! riffing off of this, I'm trying something simple that allows a fragment sublass to evaluate all of the conditions and checks that that call was made, throwing an exception if not.
wdyt?