forked from FIRST-Tech-Challenge/FtcRobotController
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
85f036a
commit e1b1306
Showing
6 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/Hardware.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.firstinspires.ftc.teamcode; | ||
|
||
import com.qualcomm.robotcore.hardware.DcMotor; | ||
import com.qualcomm.robotcore.hardware.HardwareMap; | ||
|
||
import org.firstinspires.ftc.teamcode.hardware.AutoClearEncoder; | ||
import org.firstinspires.ftc.teamcode.hardware.HardwareMapper; | ||
import org.firstinspires.ftc.teamcode.hardware.HardwareName; | ||
import org.firstinspires.ftc.teamcode.hardware.Reversed; | ||
import org.firstinspires.ftc.teamcode.hardware.ZeroPower; | ||
|
||
public class Hardware extends HardwareMapper { | ||
// left = left motor = exp 0 frontLeft | ||
// right = right motor = ctr 0 frontRight | ||
// center = ctr 3 intake | ||
|
||
@HardwareName("frontLeft") | ||
@Reversed | ||
@ZeroPower(DcMotor.ZeroPowerBehavior.BRAKE) | ||
public DcMotor frontLeft; | ||
|
||
@HardwareName("frontRight") | ||
@ZeroPower(DcMotor.ZeroPowerBehavior.BRAKE) | ||
public DcMotor frontRight; | ||
|
||
@HardwareName("backLeft") | ||
@ZeroPower(DcMotor.ZeroPowerBehavior.BRAKE) | ||
@Reversed | ||
public DcMotor backLeft; | ||
|
||
@HardwareName("backRight") | ||
@ZeroPower(DcMotor.ZeroPowerBehavior.BRAKE) | ||
public DcMotor backRight; | ||
|
||
@HardwareName("frontLeft") | ||
@AutoClearEncoder | ||
public DcMotor encoderLeft; | ||
|
||
@HardwareName("intake") | ||
@AutoClearEncoder | ||
public DcMotor encoderCenter; | ||
|
||
@HardwareName("frontRight") | ||
@AutoClearEncoder | ||
public DcMotor encoderRight; | ||
|
||
public Hardware(HardwareMap hwMap) { | ||
super(hwMap); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/hardware/AutoClearEncoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.firstinspires.ftc.teamcode.hardware; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Specifies that an encoder should be cleared when the robot is initialized. | ||
*/ | ||
@Documented | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
public @interface AutoClearEncoder { } |
111 changes: 111 additions & 0 deletions
111
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/hardware/HardwareMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package org.firstinspires.ftc.teamcode.hardware; | ||
|
||
import com.qualcomm.robotcore.hardware.DcMotor; | ||
import com.qualcomm.robotcore.hardware.DcMotorSimple; | ||
import com.qualcomm.robotcore.hardware.HardwareMap; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Field; | ||
|
||
/** | ||
* Annotation processor for hardware map things. | ||
*/ | ||
public abstract class HardwareMapper { | ||
/** | ||
* Represents an annotation processor for hardware devices. | ||
* Internals are a bit of a mess right now. | ||
* <p> </p> | ||
* HardwareName is hardcoded because it provides the value of the field. | ||
*/ | ||
static final class DeviceAnnotation<AnnotationT extends Annotation, TargetT> { | ||
private final Class<AnnotationT> annotationClass; | ||
private final Class<TargetT> targetClass; | ||
private final Action<AnnotationT, TargetT> action; | ||
|
||
@FunctionalInterface | ||
interface Action<AnnotationT extends Annotation, TargetType> { | ||
void use(AnnotationT annotation, TargetType target); | ||
} | ||
|
||
DeviceAnnotation(Class<AnnotationT> annotationClass, Class<TargetT> targetClass, Action<AnnotationT, TargetT> action) { | ||
this.annotationClass = annotationClass; | ||
this.targetClass = targetClass; | ||
this.action = action; | ||
} | ||
|
||
private boolean check(Field t, Object value) { | ||
if (!t.isAnnotationPresent(annotationClass)) return false; | ||
AnnotationT annotation = t.getAnnotation(annotationClass); | ||
if (annotation == null) | ||
throw new NullPointerException("Annotation is null! (isAnnotationPresent is true but getAnnotation returned null)"); | ||
if (!targetClass.isAssignableFrom(value.getClass())) | ||
throw new ClassCastException("Annotation " + annotationClass.getName() + " can only be used on " + targetClass.getName() + " (or subclasses)"); | ||
return true; | ||
} | ||
|
||
void use(Field t, Object value) { | ||
if (!check(t, value)) return; | ||
AnnotationT annotation = t.getAnnotation(annotationClass); | ||
if (annotation == null) | ||
throw new NullPointerException("Annotation disappeared between check and use"); | ||
action.use(annotation, targetClass.cast(value)); | ||
} | ||
} | ||
|
||
static final DeviceAnnotation<Reversed, DcMotorSimple> reversed = | ||
new DeviceAnnotation<>( | ||
Reversed.class, | ||
DcMotorSimple.class, | ||
(annotation, target) -> target.setDirection(DcMotorSimple.Direction.REVERSE) | ||
); | ||
|
||
static final DeviceAnnotation<ZeroPower, DcMotor> zeroPower = | ||
new DeviceAnnotation<>( | ||
ZeroPower.class, | ||
DcMotor.class, | ||
(annotation, target) -> target.setZeroPowerBehavior(annotation.value()) | ||
); | ||
|
||
static final DeviceAnnotation<AutoClearEncoder, DcMotor> autoClearEncoder = | ||
new DeviceAnnotation<>( | ||
AutoClearEncoder.class, | ||
DcMotor.class, | ||
(annotation, target) -> { | ||
DcMotor.RunMode current = target.getMode(); | ||
target.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); | ||
target.setMode(current); | ||
} | ||
); | ||
|
||
public HardwareMapper(HardwareMap map) { | ||
Field[] fields = this.getClass().getDeclaredFields(); | ||
for (Field field : fields) { | ||
boolean accessible = field.isAccessible(); | ||
if (!accessible) field.setAccessible(true); | ||
try { | ||
Class<?> targetType = field.getType(); | ||
HardwareName annotation = field.getAnnotation(HardwareName.class); | ||
if (annotation == null) continue; | ||
Object result = map.tryGet(targetType, annotation.value()); | ||
|
||
if (result == null) { | ||
throw new RuntimeException("Hardware: '" + field.getName() + "' not found, expected type " + targetType.getName() + " for field " + field.getName() + " in " + this.getClass().getName()); | ||
} | ||
try { | ||
field.set(this, result); | ||
} catch (IllegalAccessException e) { | ||
throw new RuntimeException("Field " + field.getName() + " assign failed: " + result.getClass().getName() + " to " + field.getType().getName()); | ||
} | ||
|
||
reversed.use(field, result); | ||
zeroPower.use(field, result); | ||
autoClearEncoder.use(field, result); | ||
} catch (IllegalArgumentException e) { | ||
throw new RuntimeException("Field " + field.getName() + " typecast failed"); | ||
} finally { | ||
// lock the field back if it was locked | ||
field.setAccessible(accessible); | ||
} | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/hardware/HardwareName.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.firstinspires.ftc.teamcode.hardware; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
@Documented | ||
public @interface HardwareName { | ||
String value(); | ||
} |
16 changes: 16 additions & 0 deletions
16
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/hardware/Reversed.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.firstinspires.ftc.teamcode.hardware; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Specifies that a motor should start with its direction reversed. | ||
* The annotated field must be a DcMotorSimple or subclass. | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
@Documented | ||
public @interface Reversed {} |
19 changes: 19 additions & 0 deletions
19
TeamCode/src/main/java/org/firstinspires/ftc/teamcode/hardware/ZeroPower.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.firstinspires.ftc.teamcode.hardware; | ||
|
||
import com.qualcomm.robotcore.hardware.DcMotor; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Defiles the zero power behavior of a motor. | ||
*/ | ||
@Documented | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
public @interface ZeroPower { | ||
DcMotor.ZeroPowerBehavior value(); | ||
} |