9 | * This encapsulates *two* different capabilities.
10 | * 1. A ConditionalCommand with only a condition, but no commands, is a a "wait" command.
11 | * It will only finish once the condition is true.
12 | * 2. A ConditionalCommand with a condition and a true (and optionally false) command
13 | * is a generic "if/else" command: If the condition is true, execute the 'true command',
14 | * if not true, execute the 'false command' if it is supplied.
15 | *
16 | * TODO: This makes the class a little clunky. It wouldn't be terrible to break the functionality
17 | * TODO: out into multiple classes instead
18 | *
19 | * @author Alex Stedman
20 | */
21 | public class ConditionalCommand implements Command {
22 |
23 | private BooleanSupplier supplier;
24 |
25 | @Nullable
26 | private Command trueCommand, falseCommand;
27 |
28 | /**
29 | * This makes a "wait" command
30 | *
31 | * @param condition The BooleanSupplier that will be waited upon until true
32 | */
33 | public ConditionalCommand(BooleanSupplier condition) {
34 | supplier = condition;
35 | trueCommand = null;
36 | falseCommand = null;
37 | }
38 |
39 | /**
40 | * Make a conditional command
41 | *
42 | * @param condition The condition
43 | * @param command The command to run when the condition is true.
44 | */
45 | public ConditionalCommand(BooleanSupplier condition, Command command) {
46 | supplier = condition;
47 | trueCommand = command;
48 | CommandScheduler.scheduleWithOther(this, trueCommand, condition);
49 | falseCommand = null;
50 | }
51 |
52 | /**
53 | * Make a conditional command
54 | *
55 | * @param condition The condition
56 | * @param trueC The command to run when the condition is true
57 | * @param falseC The command to run when the condition is false
58 | */
59 | public ConditionalCommand(BooleanSupplier condition, Command trueC, Command falseC) {
60 | supplier = condition;
61 | trueCommand = trueC;
62 | falseCommand = falseC;
63 | CommandScheduler.scheduleWithOther(this, trueCommand, condition);
64 | CommandScheduler.scheduleWithOther(this, falseCommand, () -> !condition.getAsBoolean());
65 | }
66 |
67 | @Override
68 | public void execute() {}
69 |
70 | @Override
71 | public boolean isFinished() {
72 | if (trueCommand == null) return supplier.getAsBoolean();
73 | if (falseCommand == null) return trueCommand.justFinished();
74 | return trueCommand.justFinished() || falseCommand.justFinished();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/IterativeCommand.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import java.util.function.BooleanSupplier;
4 | import java.util.function.Function;
5 |
6 | public class IterativeCommand extends SequentialCommandGroup {
7 |
8 | /**
9 | * iterative command for anything
10 | *
11 | * TODO: Figure out what this is good for. It looks weirdly specific. I wonder what Alex was
12 | * doing with it
13 | *
14 | * @param func
15 | * @param start
16 | * @param end
17 | * @param accum
18 | * @param
19 | */
20 | public IterativeCommand(Function func, T start, T end, Function accum) {
21 | for (T t = start; !t.equals(end); t = accum.apply(t)) addCommands(func.apply(t));
22 | }
23 |
24 | public IterativeCommand(
25 | Function func,
26 | T start,
27 | T end,
28 | Function accum,
29 | BooleanSupplier stopCondition
30 | ) {
31 | for (T t = start; !t.equals(end); t = accum.apply(t)) addCommands(func.apply(t));
32 | }
33 |
34 | /**
35 | * iterative command for an int
36 | *
37 | * @param func
38 | * @param loops
39 | */
40 | public IterativeCommand(Function func, int loops) {
41 | this(func, 0, loops, i -> i + 1);
42 | }
43 |
44 | public IterativeCommand(Function func, int loops, BooleanSupplier stopCondition) {
45 | this(func, 0, loops, i -> i + 1, stopCondition);
46 | }
47 |
48 | // TODO make limitless but 10 will make sure i dont yeet to much
49 | public IterativeCommand(Function func, BooleanSupplier stopCondition) {
50 | this(func, 0, 10, i -> i + 1, stopCondition);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/ParallelCommandGroup.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | /**
4 | * Command group to run commands in parallel until all of them finish
5 | *
6 | * @author Alex Stedman
7 | */
8 | public class ParallelCommandGroup extends CommandGroup {
9 |
10 | /**
11 | * Make parallel command group
12 | *
13 | * @param commands The commands for the group
14 | */
15 | public ParallelCommandGroup(Command... commands) {
16 | super(true, commands);
17 | }
18 |
19 | @Override
20 | public void schedule(Command c) {
21 | CommandScheduler.scheduleWithOther(this, c);
22 | }
23 |
24 | /**
25 | * @return True if *all* of the commands are finished
26 | */
27 | @Override
28 | public boolean isFinished() {
29 | // if there is no unfinished commands its done
30 | return !commandMap.containsValue(false);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/ParallelDeadlineGroup.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | /**
4 | * Command group to run commands in parallel until one particular command completes
5 | *
6 | * @author Alex Stedman
7 | */
8 | public class ParallelDeadlineGroup extends CommandGroup {
9 |
10 | private Command deadline;
11 |
12 | /**
13 | * Make parallel deadline group
14 | *
15 | * @param command the deadline condition (Once this is complete, the rest are cancelled)
16 | * @param commands The other commands for the group
17 | */
18 | public ParallelDeadlineGroup(Command command, Command... commands) {
19 | super(true, commands);
20 | addCommands(command);
21 | deadline = command;
22 | }
23 |
24 | /**
25 | * Add another command to the group to be run while waiting for the 'deadline' command to finish
26 | *
27 | * @param c The command to add to the command group
28 | */
29 | @Override
30 | public void schedule(Command c) {
31 | CommandScheduler.scheduleWithOther(this, c);
32 | }
33 |
34 | /**
35 | * @return True if the 'deadline' command has finished
36 | */
37 | @Override
38 | public boolean isFinished() {
39 | return deadline.justFinished();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/ParallelRaceGroup.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | /**
4 | * Command group to run commands in parallel until *one* is finished
5 | *
6 | * @author Alex Stedman
7 | */
8 | public class ParallelRaceGroup extends CommandGroup {
9 |
10 | /**
11 | * Make parallel race group
12 | *
13 | * @param commands The commands for the group
14 | */
15 | public ParallelRaceGroup(Command... commands) {
16 | super(true, commands);
17 | }
18 |
19 | /**
20 | * Add one more command to the list of commands that will be run at the same time
21 | *
22 | * @param c The command to add to the group
23 | */
24 | @Override
25 | public void schedule(Command c) {
26 | CommandScheduler.scheduleWithOther(this, c);
27 | }
28 |
29 | /**
30 | * Is this finished?
31 | *
32 | * @return True if *any* of the commands are finished, false if *none* have finished.
33 | */
34 | @Override
35 | public boolean isFinished() {
36 | // if there is a single finished command
37 | return commandMap.containsValue(true);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/SequentialCommandGroup.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | /**
4 | * A grouping command which runs a list of commands in sequence
5 | *
6 | * @author Alex Stedman
7 | */
8 | public class SequentialCommandGroup extends CommandGroup {
9 |
10 | protected Command lastCommand;
11 |
12 | /**
13 | * Make sequential command group. By default if a command is cancelled, the next commend in
14 | * the sequence is run.
15 | *
16 | * @param commands The commands to run
17 | */
18 | public SequentialCommandGroup(Command... commands) {
19 | super(true, commands);
20 | }
21 |
22 | /**
23 | * This allows you to append another command to the Sequential Command Group
24 | *
25 | * @param c The command to add to the end of the list
26 | */
27 | @Override
28 | public void schedule(Command c) {
29 | if (lastCommand == null) {
30 | CommandScheduler.scheduleWithOther(this, c);
31 | } else {
32 | CommandScheduler.scheduleAfterOther(lastCommand, c);
33 | }
34 | lastCommand = c;
35 | }
36 |
37 | /**
38 | * Returns if all the commands are finished
39 | *
40 | * @return Is the command group finished
41 | */
42 | @Override
43 | public boolean isFinished() {
44 | return lastCommand.justFinished() || (anyCancelled && !countCancel);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/command/WaitCommand.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import java.util.function.DoubleSupplier;
4 |
5 | /**
6 | * A command to do nothing but wait for a span of time.
7 | * In an ideal world, you wouldn't need this. But the world is far from ideal...
8 | *
9 | * @author Alex Stedman
10 | */
11 | public class WaitCommand implements Command {
12 |
13 | /**
14 | * @return the number of seconds the command will wait
15 | */
16 | public double getSeconds() {
17 | return supplier.getAsDouble();
18 | }
19 |
20 | private DoubleSupplier supplier;
21 |
22 | /**
23 | * Create a wait command for a fixed number of seconds
24 | *
25 | * @param sec The number of seconds (can be non-whole numbers!)
26 | */
27 | public WaitCommand(double sec) {
28 | supplier = () -> sec;
29 | }
30 |
31 | /**
32 | * Create a wait command for a number of seconds that can be calculated when the commannd is
33 | * triggered
34 | *
35 | * @param sup The DoublerSupplier function which calculates the number of seconds to wait
36 | */
37 | public WaitCommand(DoubleSupplier sup) {
38 | supplier = sup;
39 | }
40 |
41 | @Override
42 | public void execute() {}
43 |
44 | @Override
45 | public boolean isFinished() {
46 | return supplier.getAsDouble() <= getRuntime().seconds();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/AxisBase.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import com.technototes.library.general.Periodic;
4 | import java.util.function.DoubleSupplier;
5 |
6 | /** The class to extend custom gamepad axis from
7 | * @author Alex Stedman
8 | */
9 | public class AxisBase extends ButtonBase implements DoubleSupplier, Periodic {
10 |
11 | /** The default trigger threshold
12 | *
13 | */
14 | public static final double DEFAULT_TRIGGER_THRESHOLD = 0.05;
15 |
16 | private double triggerThreshold;
17 | protected DoubleSupplier doubleSupplier;
18 |
19 | /** Make a GamepadAxis with the supplier
20 | *
21 | * @param d The supplier to make the axis around
22 | */
23 | public AxisBase(DoubleSupplier d) {
24 | this(d, DEFAULT_TRIGGER_THRESHOLD);
25 | }
26 |
27 | /** Make a GamepadAxis with the supplier and the threshold for the stick to behave as a button
28 | *
29 | * @param d The supplier to make the axis around
30 | * @param t The threshold
31 | */
32 | public AxisBase(DoubleSupplier d, double t) {
33 | super(() -> Math.abs(d.getAsDouble()) >= t);
34 | doubleSupplier = d;
35 | triggerThreshold = t;
36 | }
37 |
38 | /** Returns the double from the axis
39 | *
40 | * @return The double
41 | */
42 | @Override
43 | public double getAsDouble() {
44 | if (isDisabled()) return 0;
45 | return getInverted() ? -doubleSupplier.getAsDouble() : doubleSupplier.getAsDouble();
46 | }
47 |
48 | /** Gets the trigger threshold
49 | *
50 | * @return The threshold
51 | */
52 | public double getTriggerThreshold() {
53 | return triggerThreshold;
54 | }
55 |
56 | /** Set threshold
57 | * @param threshold the new threshold
58 | */
59 | public AxisBase setTriggerThreshold(double threshold) {
60 | triggerThreshold = threshold;
61 | return this;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/Binding.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import java.util.function.BooleanSupplier;
4 |
5 | /** Class for bindings to extend
6 | * @author Alex Stedman
7 | *
8 | */
9 | public interface Binding extends BooleanSupplier {
10 | /** Button type
11 | *
12 | */
13 | enum Type {
14 | NONE_ACTIVE,
15 | SOME_ACTIVE,
16 | ALL_ACTIVE,
17 | }
18 |
19 | T[] getSuppliers();
20 |
21 | Type getDefaultType();
22 |
23 | @Override
24 | default boolean getAsBoolean() {
25 | return get(getDefaultType());
26 | }
27 |
28 | /** Get this as boolean for the type
29 | *
30 | * @param type The type to get boolean as
31 | * @return If the binding meets the criteria
32 | */
33 | default boolean get(Type type) {
34 | boolean on = false, off = getSuppliers().length == 0;
35 | for (T s : getSuppliers()) {
36 | if (s.getAsBoolean()) {
37 | on = true;
38 | } else {
39 | off = true;
40 | }
41 | }
42 | switch (type) {
43 | case NONE_ACTIVE:
44 | return !on;
45 | case ALL_ACTIVE:
46 | return !off;
47 | default:
48 | return on;
49 | }
50 | }
51 |
52 | default boolean get() {
53 | return get(getDefaultType());
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/CommandAxis.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import com.technototes.library.command.Command;
4 | import java.util.function.DoubleSupplier;
5 | import java.util.function.Function;
6 |
7 | /**
8 | * Class for command axis for the gamepad
9 | *
10 | * @author Alex Stedman
11 | */
12 | public class CommandAxis extends AxisBase implements CommandInput {
13 |
14 | /**
15 | * Make a command axis
16 | *
17 | * @param supplier The axis supplier
18 | */
19 | public CommandAxis(DoubleSupplier supplier) {
20 | super(supplier);
21 | }
22 |
23 | /**
24 | * Make a command axis
25 | *
26 | * @param supplier The axis supplier
27 | * @param threshold The threshold to trigger to make the axis behave as a button
28 | */
29 | public CommandAxis(DoubleSupplier supplier, double threshold) {
30 | super(supplier, threshold);
31 | }
32 |
33 | @Override
34 | public CommandAxis getInstance() {
35 | return this;
36 | }
37 |
38 | @Override
39 | public CommandAxis setTriggerThreshold(double threshold) {
40 | super.setTriggerThreshold(threshold);
41 | return this;
42 | }
43 |
44 | public CommandAxis schedulePressed(Function f) {
45 | return whilePressed(f.apply(this));
46 | }
47 |
48 | public CommandAxis schedule(Function f) {
49 | return schedule(f.apply(this.getAsDouble()));
50 | }
51 |
52 | @Override
53 | public CommandAxis setInverted(boolean invert) {
54 | return (CommandAxis) super.setInverted(invert);
55 | }
56 |
57 | public CommandButton getAsButton() {
58 | return new CommandButton(this);
59 | }
60 |
61 | public CommandButton getAsButton(double threshold) {
62 | return new CommandButton(() -> (threshold >= 0) ? (getAsDouble() >= threshold) : (getAsDouble() < threshold));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/CommandBinding.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | /** Command implementation of {@link Binding}
4 | * @author Alex Stedman
5 | */
6 | public class CommandBinding extends CommandButton implements Binding {
7 |
8 | private CommandInput[] inputs;
9 | private Type defaultType;
10 |
11 | public CommandBinding(CommandInput... b) {
12 | this(Type.ALL_ACTIVE, b);
13 | }
14 |
15 | public CommandBinding(Type type, CommandInput... b) {
16 | super(null);
17 | inputs = b;
18 | defaultType = type;
19 | booleanSupplier = this::get;
20 | }
21 |
22 | @Override
23 | public CommandInput[] getSuppliers() {
24 | return inputs;
25 | }
26 |
27 | @Override
28 | public Type getDefaultType() {
29 | return defaultType;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/CommandButton.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import com.technototes.library.command.Command;
4 | import java.util.function.BooleanSupplier;
5 | import java.util.function.Consumer;
6 | import java.util.function.Function;
7 |
8 | /** Class for command buttons for gamepad
9 | * @author Alex Stedman
10 | */
11 | public class CommandButton extends ButtonBase implements CommandInput {
12 |
13 | /** Make command button
14 | *
15 | * @param supplier The supplier for the button
16 | */
17 | public CommandButton(BooleanSupplier supplier) {
18 | super(supplier);
19 | }
20 |
21 | @Override
22 | public CommandButton getInstance() {
23 | return this;
24 | }
25 |
26 | public CommandButton schedule(Function f) {
27 | return schedule(f.apply(this.getAsBoolean()));
28 | }
29 |
30 | public CommandButton schedule(Consumer f) {
31 | return schedule(() -> f.accept(this.getAsBoolean()));
32 | }
33 |
34 | @Override
35 | public CommandButton setInverted(boolean invert) {
36 | return (CommandButton) super.setInverted(invert);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/CommandGamepad.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import com.qualcomm.robotcore.hardware.Gamepad;
4 | import com.technototes.library.command.Command;
5 | import com.technototes.library.command.CommandScheduler;
6 | import java.util.function.BiConsumer;
7 | import java.util.function.BiFunction;
8 |
9 | /** Class for command gamepads that specifies class params
10 | * @author Alex Stedman
11 | */
12 | public class CommandGamepad extends GamepadBase {
13 |
14 | /** Make command gamepad
15 | *
16 | * @param gamepad The normal gamepad
17 | */
18 | public CommandGamepad(Gamepad gamepad) {
19 | super(gamepad, CommandButton.class, CommandAxis.class);
20 | }
21 |
22 | public CommandGamepad scheduleLeftStick(BiFunction f) {
23 | return scheduleStick(leftStick, f);
24 | }
25 |
26 | public CommandGamepad scheduleLeftStick(BiConsumer f) {
27 | return scheduleStick(leftStick, f);
28 | }
29 |
30 | public CommandGamepad scheduleRightStick(BiFunction f) {
31 | return scheduleStick(rightStick, f);
32 | }
33 |
34 | public CommandGamepad scheduleRightStick(BiConsumer f) {
35 | return scheduleStick(rightStick, f);
36 | }
37 |
38 | public CommandGamepad scheduleDpad(BiFunction f) {
39 | return scheduleStick(dpad, f);
40 | }
41 |
42 | public CommandGamepad scheduleDpad(BiConsumer f) {
43 | return scheduleStick(dpad, f);
44 | }
45 |
46 | public CommandGamepad scheduleStick(Stick s, BiFunction f) {
47 | CommandScheduler.scheduleJoystick(f.apply(s.getXAxis(), s.getXAxis()));
48 | return this;
49 | }
50 |
51 | public CommandGamepad scheduleStick(Stick s, BiConsumer f) {
52 | CommandScheduler.scheduleJoystick(() -> f.accept(s.getXAxis(), s.getXAxis()));
53 | return this;
54 | }
55 |
56 | @Override
57 | public CommandGamepad enable() {
58 | return (CommandGamepad) super.enable();
59 | }
60 |
61 | @Override
62 | public CommandGamepad disable() {
63 | return (CommandGamepad) super.disable();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/GamepadDpad.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | /** A class for dpads
4 | * @author Alex Stedman
5 | * @param The gamepad button class
6 | */
7 | public class GamepadDpad implements Stick {
8 |
9 | private boolean enabled = true;
10 | /** The objects for the dpad buttons
11 | *
12 | */
13 | public T up, down, left, right;
14 |
15 | /** Create dpad with 4 buttons
16 | *
17 | * @param u Up button
18 | * @param d Down button
19 | * @param l Left button
20 | * @param r Right button
21 | */
22 | public GamepadDpad(T u, T d, T l, T r) {
23 | up = u;
24 | down = d;
25 | left = l;
26 | right = r;
27 | }
28 |
29 | /** Return x axis double (treating dpad as stick)
30 | *
31 | * @return The double
32 | */
33 | @Override
34 | public double getXAxis() {
35 | return (right.getAsBoolean() ? (left.getAsBoolean() ? 0 : 1) : (left.getAsBoolean() ? -1 : 0));
36 | }
37 |
38 | /** Return y axis double (treating dpad as stick)
39 | *
40 | * @return The double
41 | */
42 | @Override
43 | public double getYAxis() {
44 | return (up.getAsBoolean() ? (down.getAsBoolean() ? 0 : 1) : (down.getAsBoolean() ? -1 : 0));
45 | }
46 |
47 | @Override
48 | public void periodic() {
49 | if (isDisabled()) return;
50 | up.periodic();
51 | down.periodic();
52 | left.periodic();
53 | right.periodic();
54 | }
55 |
56 | @Override
57 | public GamepadDpad setEnabled(boolean enable) {
58 | enabled = enable;
59 | up.setEnabled(enabled);
60 | down.setEnabled(enabled);
61 | left.setEnabled(enabled);
62 | right.setEnabled(enabled);
63 | return this;
64 | }
65 |
66 | @Override
67 | public boolean isEnabled() {
68 | return enabled;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/GamepadStick.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | /** A class for gamepad sticks
4 | * @author Alex Stedman
5 | * @param The class for the gamepad axis
6 | * @param The class for the gamepad buttons
7 | */
8 | public class GamepadStick implements Stick {
9 |
10 | private boolean enabled = true;
11 | /** The objects for the stick axis
12 | *
13 | */
14 | public T xAxis, yAxis;
15 | /** The objects for the stick button
16 | *
17 | */
18 | public U stickButton;
19 |
20 | /** Make a gamepad stick
21 | *
22 | * @param x The x joystick axis
23 | * @param y The y joystick axis
24 | * @param b The joystick button
25 | */
26 | public GamepadStick(T x, T y, U b) {
27 | xAxis = x;
28 | yAxis = y;
29 | stickButton = b;
30 | }
31 |
32 | @Override
33 | public void periodic() {
34 | if (isDisabled()) return;
35 | xAxis.periodic();
36 | yAxis.periodic();
37 | stickButton.periodic();
38 | }
39 |
40 | @Override
41 | public double getXAxis() {
42 | return xAxis.getAsDouble();
43 | }
44 |
45 | @Override
46 | public double getYAxis() {
47 | return yAxis.getAsDouble();
48 | }
49 |
50 | @Override
51 | public GamepadStick setEnabled(boolean enable) {
52 | enabled = enable;
53 | xAxis.setEnabled(enabled);
54 | yAxis.setEnabled(enabled);
55 | stickButton.setEnabled(enabled);
56 | return this;
57 | }
58 |
59 | @Override
60 | public boolean isEnabled() {
61 | return enabled;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/control/Stick.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.control;
2 |
3 | import com.technototes.library.general.CanBeEnabled;
4 | import com.technototes.library.general.Periodic;
5 | import java.util.function.DoubleSupplier;
6 |
7 | /** Interface for objects that behave as sticks
8 | * @author Alex Stedman
9 | */
10 | public interface Stick extends Periodic, CanBeEnabled {
11 | /** Return x axis double
12 | *
13 | * @return The double
14 | */
15 | double getXAxis();
16 | /** Return y axis double
17 | *
18 | * @return The double
19 | */
20 | double getYAxis();
21 |
22 | /** Return x axis supplier
23 | *
24 | * @return The double supplier
25 | */
26 | default DoubleSupplier getXSupplier() {
27 | return this::getXAxis;
28 | }
29 |
30 | /** Return y axis supplier
31 | *
32 | * @return The double supplier
33 | */
34 | default DoubleSupplier getYSupplier() {
35 | return this::getYAxis;
36 | }
37 |
38 | /** Returns the angle of the stick
39 | *
40 | * @return The angle
41 | */
42 | default double getAngle() {
43 | return -Math.atan2(getYAxis(), getXAxis());
44 | }
45 |
46 | /** Returns the stick's distance from the center
47 | *
48 | * @return The distance
49 | */
50 | default double getDistanceFromCenter() {
51 | return Math.sqrt(getXAxis() * getXAxis() + getYAxis() * getYAxis());
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/general/CanBeEnabled.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.general;
2 |
3 | /**
4 | * Interface for anything that can be enabled/disabled
5 | *
6 | *
7 | * You must have "setEnabled" and "isEnabled" functions. Everything else has
8 | * functional implementations in the interface
9 | *
10 | * @param An Enable-able interface/class type
11 | */
12 |
13 | public interface CanBeEnabled> {
14 | /**
15 | * Enable the object
16 | *
17 | * @return The object
18 | */
19 | default T enable() {
20 | return setEnabled(true);
21 | }
22 |
23 | /**
24 | * Disable the object
25 | *
26 | * @return the object
27 | */
28 | default T disable() {
29 | return setEnabled(false);
30 | }
31 |
32 | /**
33 | * Set whether or not the device is enabled
34 | *
35 | * @param enable True for enabled, false for disabled
36 | * @return The object
37 | */
38 | T setEnabled(boolean enable);
39 |
40 | /**
41 | * Toggle whether this object is enabled or not
42 | *
43 | * @return The object
44 | */
45 | default T toggleEnabled() {
46 | return setEnabled(!isEnabled());
47 | }
48 |
49 | /**
50 | * @return Is this object enabled?
51 | */
52 | boolean isEnabled();
53 |
54 | /**
55 | * @return Is this object disabled?
56 | */
57 | default boolean isDisabled() {
58 | return !isEnabled();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/general/Invertible.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.general;
2 |
3 | /**
4 | * Interface for anything that can be inverted
5 | *
6 | * @author Alex Stedman
7 | */
8 | @SuppressWarnings("unused")
9 | public interface Invertible> {
10 | /**
11 | * Set the inversion (true -> Is inverted, false -> Not inverted)
12 | *
13 | * @param invert Inversion value
14 | * @return this
15 | */
16 | T setInverted(boolean invert);
17 |
18 | /**
19 | * Toggle inversion
20 | *
21 | * @return this
22 | */
23 | default T invert() {
24 | return setInverted(!getInverted());
25 | }
26 |
27 | /**
28 | * Get current inversion
29 | *
30 | * @return Current inversion
31 | */
32 | boolean getInverted();
33 | }
34 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/general/Periodic.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.general;
2 |
3 | /** An interface for classes to have the periodic function
4 | * @author Alex Stedman
5 | */
6 | @FunctionalInterface
7 | public interface Periodic {
8 | /** The periodic function
9 | */
10 | void periodic();
11 | }
12 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/DummyDevice.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | import com.qualcomm.robotcore.hardware.HardwareDevice;
4 |
5 | /**
6 | * This isn't worth actually doing. You have to redo your configuration constantly if you create
7 | * a device that isn't part of the core runtime :(
8 | *
9 | * @param The type of the device
10 | */
11 | public class DummyDevice implements HardwareDevice {
12 |
13 | private final T internal;
14 |
15 | public DummyDevice(T inter) {
16 | internal = inter;
17 | }
18 |
19 | @Override
20 | public Manufacturer getManufacturer() {
21 | return Manufacturer.Unknown;
22 | }
23 |
24 | @Override
25 | public String getDeviceName() {
26 | return internal.toString();
27 | }
28 |
29 | @Override
30 | public String getConnectionInfo() {
31 | return "dummy device";
32 | }
33 |
34 | @Override
35 | public int getVersion() {
36 | return 0;
37 | }
38 |
39 | @Override
40 | public void resetDeviceConfigurationForOpMode() {}
41 |
42 | @Override
43 | public void close() {}
44 |
45 | public T get() {
46 | return internal;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/FailedDevice.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | public class FailedDevice implements com.qualcomm.robotcore.hardware.HardwareDevice {
4 |
5 | protected String name;
6 |
7 | protected FailedDevice(String deviceName) {
8 | name = deviceName;
9 | }
10 |
11 | @Override
12 | public Manufacturer getManufacturer() {
13 | return Manufacturer.Other;
14 | }
15 |
16 | @Override
17 | public String getDeviceName() {
18 | return name;
19 | }
20 |
21 | @Override
22 | public String getConnectionInfo() {
23 | return "NC";
24 | }
25 |
26 | @Override
27 | public int getVersion() {
28 | return 0;
29 | }
30 |
31 | @Override
32 | public void resetDeviceConfigurationForOpMode() {}
33 |
34 | @Override
35 | public void close() {}
36 | }
37 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/HardwareDevice.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | import android.util.Log;
4 | import com.qualcomm.robotcore.hardware.HardwareMap;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.Set;
8 |
9 | /**
10 | * Class for hardware devices
11 | * This just adds an extra layer of indirection that doesn't feel like it's worth the hassle.
12 | *
13 | * @param The class for the default device (ones found in ftcsdk)
14 | * @author Alex Stedman
15 | */
16 | @SuppressWarnings("unused")
17 | public abstract class HardwareDevice {
18 |
19 | /**
20 | * Hardware map object for stuff
21 | */
22 | public static HardwareMap hardwareMap = null;
23 | protected static Map> names = new HashMap<>();
24 |
25 | public static void initMap(HardwareMap h) {
26 | hardwareMap = h;
27 | }
28 |
29 | public static Set> devices = null;
30 |
31 | private T device;
32 |
33 | /**
34 | * The name of the hardware used for logging & hardware creation
35 | */
36 | protected String name;
37 |
38 | public String getName() {
39 | return name;
40 | }
41 |
42 | /**
43 | * Make a hardware device
44 | *
45 | * @param device The default device
46 | */
47 | public HardwareDevice(T device, String deviceName) {
48 | this.device = device;
49 | name = deviceName;
50 | names.put(deviceName, this);
51 | }
52 |
53 | /**
54 | * Make a hardware device with the string to get from hardwaremap
55 | *
56 | * @param deviceName The device name
57 | */
58 | @SuppressWarnings("unchecked cast")
59 | protected HardwareDevice(String deviceName) {
60 | device = hardwareMap.tryGet(
61 | (Class) com.qualcomm.robotcore.hardware.HardwareDevice.class/*T.class*/,
62 | deviceName
63 | );
64 | name = deviceName;
65 | names.put(name, this);
66 | /* if (device == null) {
67 | Log.e("DEVICE FAILURE", deviceName);
68 | } */
69 | }
70 |
71 | /**
72 | * Get encapsulated device
73 | *
74 | * @return The device
75 | */
76 | protected T getRawDevice() {
77 | // TODO: Assert that we've got a device, yeah?
78 | return device;
79 | }
80 |
81 | protected boolean realHardware() {
82 | return device != null;
83 | }
84 |
85 | /**
86 | * Get the logging expression
87 | */
88 | protected String logData(String info) {
89 | return String.format("%s: %s", name, info);
90 | }
91 |
92 | /**
93 | * This is used for logging stuff by name and/or device type
94 | * @return
95 | */
96 | public abstract String LogLine();
97 | }
98 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/Sensored.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | import java.util.function.DoubleSupplier;
4 |
5 | /**
6 | * Class for hardware devices with a sensor value
7 | *
8 | * This name is just bad. I'd also like to add normalization to it, so we could scale input values
9 | * to consistent ranges (triggers, joystick axes, distance sensors, servo ranges, etc...)
10 | *
11 | * @author Alex Stedman
12 | */
13 | @SuppressWarnings("unused")
14 | public interface Sensored extends DoubleSupplier {
15 | /**
16 | * Get the sensor value
17 | *
18 | * @return The value
19 | */
20 | double getSensorValue();
21 |
22 | @Override
23 | default double getAsDouble() {
24 | return getSensorValue();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/AnalogSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import com.qualcomm.robotcore.hardware.AnalogInput;
4 |
5 | /** Class for analog sensors
6 | * @author Alex Stedman
7 | */
8 | @SuppressWarnings("unused")
9 | public class AnalogSensor extends Sensor {
10 |
11 | private double val;
12 |
13 | /** Make an analog sensor
14 | *
15 | * @param device The analog device
16 | */
17 | public AnalogSensor(AnalogInput device, String nm) {
18 | super(device, nm);
19 | }
20 |
21 | /** Make an analog sensor
22 | *
23 | * @param deviceName The device name in hardware map
24 | */
25 | public AnalogSensor(String deviceName) {
26 | super(deviceName);
27 | }
28 |
29 | @Override
30 | public String LogLine() {
31 | return logData(String.format("%f1.4", val));
32 | }
33 |
34 | public double getSensorValue() {
35 | AnalogInput device = getRawDevice();
36 | if (device != null) {
37 | val = device.getMaxVoltage();
38 | }
39 | return val;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ColorDistanceSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import com.qualcomm.robotcore.hardware.ColorRangeSensor;
4 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit;
5 |
6 | public class ColorDistanceSensor extends Sensor implements IDistanceSensor, IColorSensor {
7 |
8 | private DistanceUnit distanceUnit;
9 | private double dist;
10 | private double light;
11 | private int color;
12 |
13 | public ColorDistanceSensor(String name) {
14 | super(name);
15 | distanceUnit = DistanceUnit.CM;
16 | }
17 |
18 | @Override
19 | public String LogLine() {
20 | int alpha = (color >> 24) & 0xFF;
21 | if (alpha != 0 && alpha != 0xFF) {
22 | return logData(
23 | String.format(
24 | "d:%f1.2%s A(%d)R(%d)G(%d)B(%d) [%f1.3]",
25 | dist,
26 | distanceUnit,
27 | alpha,
28 | (color >> 16) & 0xFF,
29 | (color >> 8) & 0xFF,
30 | color & 0xFF,
31 | light
32 | )
33 | );
34 | } else {
35 | return logData(
36 | String.format(
37 | "d:%f1.2%s R(%d)G(%d)B(%d) [%f1.3]",
38 | dist,
39 | distanceUnit,
40 | (color >> 16) & 0xFF,
41 | (color >> 8) & 0xFF,
42 | color & 0xFF,
43 | light
44 | )
45 | );
46 | }
47 | }
48 |
49 | public ColorDistanceSensor(ColorRangeSensor device, String nm) {
50 | super(device, nm);
51 | }
52 |
53 | @Override
54 | public double getDistance(DistanceUnit unit) {
55 | ColorRangeSensor device = getRawDevice();
56 | double val = dist;
57 | if (device != null) {
58 | val = device.getDistance(unit);
59 | dist = distanceUnit.fromUnit(unit, val);
60 | }
61 | return val;
62 | }
63 |
64 | @Override
65 | public ColorDistanceSensor onUnit(DistanceUnit unit) {
66 | distanceUnit = unit;
67 | return this;
68 | }
69 |
70 | @Override
71 | public DistanceUnit getUnit() {
72 | return distanceUnit;
73 | }
74 |
75 | @Override
76 | public int argb() {
77 | ColorRangeSensor device = getRawDevice();
78 | if (device != null) {
79 | color = device.argb();
80 | }
81 | return color;
82 | }
83 |
84 | public double getLight() {
85 | ColorRangeSensor device = getRawDevice();
86 | if (device != null) {
87 | light = device.getRawLightDetected();
88 | }
89 | return light;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ColorSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | /** Class for color sensors
4 | * @author Alex Stedman
5 | */
6 | @SuppressWarnings("unused")
7 | public class ColorSensor extends Sensor implements IColorSensor {
8 |
9 | public int val;
10 |
11 | /** Make a color Sensor
12 | *
13 | * @param device The hardware device
14 | */
15 | public ColorSensor(com.qualcomm.robotcore.hardware.ColorSensor device, String nm) {
16 | super(device, nm);
17 | }
18 |
19 | /** Make a color sensor
20 | *
21 | * @param deviceName The device name in hardware map
22 | */
23 | public ColorSensor(String deviceName) {
24 | super(deviceName);
25 | }
26 |
27 | @Override
28 | public String LogLine() {
29 | int alpha = (val >> 24) & 0xFF;
30 | if (alpha != 0 && alpha != 0xFF) {
31 | return logData(
32 | String.format("A(%d)R(%d)G(%d)B(%d)", alpha, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)
33 | );
34 | } else {
35 | return logData(String.format("R(%d)G(%d)B(%d)", (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF));
36 | }
37 | }
38 |
39 | @Override
40 | public int argb() {
41 | com.qualcomm.robotcore.hardware.ColorSensor device = getRawDevice();
42 | if (device != null) {
43 | val = device.argb();
44 | }
45 | return val;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/DigitalSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import com.qualcomm.robotcore.hardware.DigitalChannel;
4 |
5 | /** Class for digital sensors
6 | * @author Alex Stedman
7 | */
8 | @SuppressWarnings("unused")
9 | public class DigitalSensor extends Sensor {
10 |
11 | private boolean val;
12 |
13 | /** Make a digital sensor
14 | *
15 | * @param device The device
16 | */
17 | public DigitalSensor(DigitalChannel device, String nm) {
18 | super(device, nm);
19 | val = false;
20 | }
21 |
22 | /** Make a digital sensor
23 | *
24 | * @param deviceName The device name in hardware map
25 | */
26 | public DigitalSensor(String deviceName) {
27 | super(deviceName);
28 | }
29 |
30 | @Override
31 | public String LogLine() {
32 | return logData(val ? "T" : "F");
33 | }
34 |
35 | /** Get the sensor value as a boolean
36 | *
37 | * @return Sensor value as boolean
38 | */
39 | public boolean getValue() {
40 | DigitalChannel device = getRawDevice();
41 | if (device != null) {
42 | val = device.getState();
43 | }
44 | return val;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IColorSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import android.graphics.Color;
4 | import androidx.annotation.ColorInt;
5 |
6 | public interface IColorSensor {
7 | /** Get the RGB red of the sensor
8 | *
9 | * @return Red
10 | */
11 | default int red() {
12 | return (argb() >> 16) & 0xff;
13 | }
14 |
15 | /** Get the RGB green of the sensor
16 | *
17 | * @return Green
18 | */
19 | default int green() {
20 | return (argb() >> 8) & 0xff;
21 | }
22 |
23 | /** Get the RGB blue of the sensor
24 | *
25 | * @return Blue
26 | */
27 | default int blue() {
28 | return (argb()) & 0xff;
29 | }
30 |
31 | /** Get the alpha (transparency) of the color
32 | *
33 | * @return Alpha
34 | */
35 | default int alpha() {
36 | return (argb() >> 24) & 0xff;
37 | }
38 |
39 | /** Get HSV as an int
40 | *
41 | * @return HSV
42 | */
43 | default int hsv() {
44 | float[] f = this.hsvArray();
45 | return ((int) f[0] << 16) | ((int) f[1] << 8) | (int) f[2];
46 | }
47 |
48 | default int rgb() {
49 | return (argb()) & 0x00ffffff;
50 | }
51 |
52 | @ColorInt
53 | int argb();
54 |
55 | default float[] hsvArray() {
56 | float[] f = new float[3];
57 |
58 | Color.RGBToHSV(red(), green(), blue(), f);
59 | return f;
60 | }
61 |
62 | /** Get HSV hue
63 | *
64 | * @return Hue
65 | */
66 | default int hue() {
67 | return (int) this.hsvArray()[0];
68 | }
69 |
70 | /** Get HSV saturation
71 | *
72 | * @return Saturation
73 | */
74 | default int saturation() {
75 | return (int) this.hsvArray()[1];
76 | }
77 |
78 | /** Get HSV value (not entire HSV, just 'V')
79 | *
80 | * @return Value
81 | */
82 | default int value() {
83 | return (int) this.hsvArray()[2];
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IDistanceSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit;
4 |
5 | public interface IDistanceSensor {
6 | default double getDistance() {
7 | return getDistance(getUnit());
8 | }
9 |
10 | double getDistance(DistanceUnit unit);
11 |
12 | IDistanceSensor onUnit(DistanceUnit distanceUnit);
13 |
14 | DistanceUnit getUnit();
15 | }
16 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/IGyro.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit;
4 |
5 | /**
6 | * An interface for a single-angle gyroscope
7 | */
8 | public interface IGyro {
9 | /**
10 | * Set the units for the various values
11 | */
12 | void setUnits(AngleUnit u);
13 |
14 | /**
15 | * Get the units the gyroscope is set to
16 | */
17 | AngleUnit getUnits();
18 |
19 | /**
20 | * Get the heading (in specified units)
21 | */
22 | double getHeading(AngleUnit u);
23 |
24 | /**
25 | * Sets the current heading (in default units)
26 | *
27 | * @param newHeading The new heading (in default units)
28 | * @param u The angle units of the new heading
29 | */
30 | void setHeading(double newHeading, AngleUnit u);
31 |
32 | /**
33 | * Gets the current angular velocity (in specified units)
34 | */
35 | double getVelocity(AngleUnit u);
36 |
37 | default void degrees() {
38 | setUnits(AngleUnit.DEGREES);
39 | }
40 |
41 | default void radians() {
42 | setUnits(AngleUnit.RADIANS);
43 | }
44 |
45 | /**
46 | * Zeroes the current heading (in default units)
47 | */
48 | default void zero() {
49 | setHeading(0, getUnits());
50 | }
51 |
52 | /**
53 | * Get the heading (in default units)
54 | */
55 | default double getHeading() {
56 | return getHeading(getUnits());
57 | }
58 |
59 | /**
60 | * Get the heading (in degrees)
61 | */
62 | default double getHeadingInDegrees() {
63 | return getHeading(AngleUnit.DEGREES);
64 | }
65 |
66 | /**
67 | * Get the heading (in radians)
68 | */
69 | default double getHeadingInRadians() {
70 | return getHeading(AngleUnit.RADIANS);
71 | }
72 |
73 | /**
74 | * Gets the current angular velocity (in default units)
75 | */
76 | default double getVelocity() {
77 | return getVelocity(getUnits());
78 | }
79 |
80 | /**
81 | * Gets the current angular velocity (in radians)
82 | */
83 | default double getVelocityInDegrees() {
84 | return getVelocity(AngleUnit.DEGREES);
85 | }
86 |
87 | /**
88 | * Gets the current angular velocity (in degrees)
89 | */
90 | default double getVelocityInRadians() {
91 | return getVelocity(AngleUnit.RADIANS);
92 | }
93 |
94 | /**
95 | * Sets the current heading (in default units)
96 | *
97 | * @param newHeading The new heading (in default units)
98 | */
99 | default void setHeading(double newHeading) {
100 | setHeading(newHeading, getUnits());
101 | }
102 |
103 | /**
104 | * Sets the current heading (in default units)
105 | *
106 | * @param newHeading The new heading (in default units)
107 | */
108 | default void setHeadingInDegrees(double newHeading) {
109 | setHeading(newHeading, AngleUnit.DEGREES);
110 | }
111 |
112 | /**
113 | * Sets the current heading (in default units)
114 | *
115 | * @param newHeading The new heading (in default units)
116 | */
117 | default void setHeadingInRadians(double newHeading) {
118 | setHeading(newHeading, AngleUnit.RADIANS);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/ILightSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | public interface ILightSensor {}
4 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/Rev2MDistanceSensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import com.qualcomm.robotcore.hardware.DistanceSensor;
4 | import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit;
5 |
6 | /**
7 | * Class for the Rev '2m' range sensors
8 | * Note for users: The Rev 2m range sensor is actually only useful at about 1.1 - 1.2m :/
9 | *
10 | * @author Alex Stedman
11 | */
12 | @SuppressWarnings("unused")
13 | public class Rev2MDistanceSensor extends Sensor implements IDistanceSensor {
14 |
15 | private DistanceUnit distanceUnit;
16 | private double dist;
17 |
18 | /**
19 | * Create a range sensor
20 | *
21 | * @param device The sensor device
22 | */
23 | public Rev2MDistanceSensor(DistanceSensor device, String nm) {
24 | super(device, nm);
25 | }
26 |
27 | /**
28 | * Create a range sensor
29 | *
30 | * @param deviceName The device name
31 | */
32 | public Rev2MDistanceSensor(String deviceName) {
33 | super(deviceName);
34 | }
35 |
36 | @Override
37 | public String LogLine() {
38 | return logData(String.format("%f1.3%s", this.dist, this.distanceUnit));
39 | }
40 |
41 | /**
42 | * Get the value with a specified distance Unit
43 | *
44 | * @param distanceUnit The unit
45 | * @return The distance
46 | */
47 | @Override
48 | public double getDistance(DistanceUnit distanceUnit) {
49 | DistanceSensor device = getRawDevice();
50 | if (device != null) {
51 | dist = device.getDistance(distanceUnit);
52 | }
53 | return dist;
54 | }
55 |
56 | /**
57 | * Get the current distance unit
58 | *
59 | * @return The distance unit
60 | */
61 | @Override
62 | public DistanceUnit getUnit() {
63 | return distanceUnit;
64 | }
65 |
66 | /**
67 | * Set the distance unit
68 | *
69 | * @param distanceUnit The unit
70 | * @return This
71 | */
72 | @Override
73 | public Rev2MDistanceSensor onUnit(DistanceUnit distanceUnit) {
74 | this.distanceUnit = distanceUnit;
75 | return this;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/Sensor.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor;
2 |
3 | import com.technototes.library.hardware.HardwareDevice;
4 |
5 | /**
6 | * Root class for sensors
7 | *
8 | * @param The Sensor hardware device
9 | * @author Alex Stedman
10 | */
11 | @SuppressWarnings("unused")
12 | public abstract class Sensor extends HardwareDevice {
13 |
14 | /**
15 | * Create a sensor
16 | *
17 | * @param device The device
18 | */
19 | public Sensor(T device, String nm) {
20 | super(device, nm);
21 | }
22 |
23 | /**
24 | * Create sensor
25 | *
26 | * @param deviceName The device name in hardware map
27 | */
28 | public Sensor(String deviceName) {
29 | super(deviceName);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/encoder/Encoder.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor.encoder;
2 |
3 | import com.technototes.library.hardware.Sensored;
4 |
5 | /** Interfaces for encoders to use
6 | * @author Alex Stedman
7 | */
8 | public interface Encoder extends Sensored {
9 | /** zero the encoder
10 | *
11 | */
12 | void zeroEncoder();
13 |
14 | default double getPosition() {
15 | return getSensorValue();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/sensor/encoder/ExternalEncoder.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.sensor.encoder;
2 |
3 | import com.qualcomm.robotcore.hardware.AnalogInput;
4 | import com.technototes.library.hardware.sensor.Sensor;
5 |
6 | /**
7 | * A wrapper around an AnalogInput that enables "zeroing" for usefulness
8 | */
9 | public class ExternalEncoder extends Sensor implements Encoder {
10 |
11 | private double zero = 0;
12 | private double val = 0;
13 |
14 | /**
15 | * Create an ExternalEncoder from an arbitrary AnalogInput
16 | *
17 | * @param device the AnalogInput device
18 | */
19 | public ExternalEncoder(AnalogInput device, String nm) {
20 | super(device, nm);
21 | }
22 |
23 | /**
24 | * Create an ExternalEncoder from an arbitrary AnalogInput device
25 | *
26 | * @param deviceName the name of the AnalogInput device
27 | */
28 | public ExternalEncoder(String deviceName) {
29 | super(deviceName);
30 | }
31 |
32 | @Override
33 | public String LogLine() {
34 | return logData(String.format("%f1.3 (raw: %f1.3)", val - zero, val));
35 | }
36 |
37 | /**
38 | * Set the current device value as "zero"
39 | */
40 | @Override
41 | public void zeroEncoder() {
42 | AnalogInput device = getRawDevice();
43 | if (device != null) {
44 | zero = device.getVoltage();
45 | }
46 | }
47 |
48 | /**
49 | * Get the sensor value (relative to the assigned zero)
50 | *
51 | * @return the value of the input
52 | */
53 | @Override
54 | public double getSensorValue() {
55 | AnalogInput device = getRawDevice();
56 | if (device != null) {
57 | val = device.getVoltage();
58 | }
59 | return val - zero;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/hardware/servo/MotorAsServo.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware.servo;
2 |
3 | import com.qualcomm.robotcore.hardware.DcMotor;
4 | import com.qualcomm.robotcore.hardware.DcMotorEx;
5 | import com.technototes.library.hardware.HardwareDevice;
6 | import com.technototes.library.hardware.Sensored;
7 | import java.io.InvalidClassException;
8 |
9 | /**
10 | * This is to use a motor as a servo using the built-in capabilities (instead of doing it manually)
11 | *
12 | * One rather important feature would be to hand control back & forth between a normal encoded
13 | * motor. The alternative would be to extend EncodedMotor to just "do" this stuff automatically.
14 | * Honestly, that probably makes more sense, but requires some thought about state transitions.
15 | *
16 | * @param
17 | * Not Yet Implemented!
18 | * TODO: Implement this
19 | *
20 | */
21 | public class MotorAsServo extends HardwareDevice implements Sensored {
22 |
23 | public MotorAsServo(T device, String deviceName) throws InvalidClassException {
24 | super(device, deviceName);
25 | throw new InvalidClassException("com.technototes.library.hardware.servo.MotorAsServo", "Not Yet Implemented");
26 | }
27 |
28 | protected MotorAsServo(String deviceName) throws InvalidClassException {
29 | super(deviceName);
30 | throw new InvalidClassException("com.technototes.library.hardware.servo.MotorAsServo", "Not Yet Implemented");
31 | }
32 |
33 | /**
34 | * @return
35 | */
36 | @Override
37 | public String LogLine() {
38 | return null;
39 | }
40 |
41 | /**
42 | * @return
43 | */
44 | @Override
45 | public double getSensorValue() {
46 | return 0;
47 | }
48 |
49 | /**
50 | * @return
51 | */
52 | @Override
53 | public double getAsDouble() {
54 | return getSensorValue();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/Log.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger;
2 |
3 | import static java.lang.annotation.ElementType.FIELD;
4 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
5 | import static java.lang.annotation.ElementType.METHOD;
6 |
7 | import java.lang.annotation.Documented;
8 | import java.lang.annotation.ElementType;
9 | import java.lang.annotation.Repeatable;
10 | import java.lang.annotation.Retention;
11 | import java.lang.annotation.RetentionPolicy;
12 | import java.lang.annotation.Target;
13 |
14 | /** The root annotation for annotation logging, also doubles as a basic string log
15 | * @author Alex Stedman
16 | */
17 | @Documented
18 | @Repeatable(Log.Logs.class)
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
21 | public @interface Log {
22 | /** Store index for this annotation (position in telemetry)
23 | *
24 | * @return The index
25 | */
26 | int index() default -1;
27 |
28 | /** Store priority for this log entry (to pick the most wanted entry over others with same index)
29 | *
30 | * @return The priority
31 | */
32 | int priority() default -1;
33 |
34 | /** Store the name for this annotation to be be beside
35 | *
36 | * @return The name as a string
37 | */
38 | String name() default "";
39 |
40 | /** The format for the logged String
41 | *
42 | * @return The format
43 | */
44 | String format() default "%s";
45 |
46 | @Documented
47 | @Retention(RetentionPolicy.RUNTIME)
48 | @Target({ ElementType.FIELD, ElementType.METHOD })
49 | @interface Logs {
50 | Log[] value();
51 | }
52 |
53 | /** Log a number
54 | *
55 | */
56 | @Retention(RetentionPolicy.RUNTIME)
57 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
58 | @interface Number {
59 | /** Store index for this annotation (position in telemetry)
60 | *
61 | * @return The index
62 | */
63 | int index() default -1;
64 |
65 | /** Store priority for this log entry (to pick the most wanted entry over others with same index)
66 | *
67 | * @return The priority
68 | */
69 | int priority() default -1;
70 |
71 | /** Store the name for this annotation to be be beside
72 | *
73 | * @return The name as a string
74 | */
75 | String name() default "";
76 | }
77 |
78 | @Retention(RetentionPolicy.RUNTIME)
79 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
80 | @interface Boolean {
81 | /** Store index for this annotation (position in telemetry)
82 | *
83 | * @return The index
84 | */
85 | int index() default -1;
86 |
87 | /** Store priority for this log entry (to pick the most wanted entry over others with same index)
88 | *
89 | * @return The priority
90 | */
91 | int priority() default -1;
92 |
93 | /** Store the string when the annotated method returns true
94 | *
95 | * @return The string
96 | */
97 | String trueValue() default "true";
98 |
99 | /** Store the string when the annotated method returns false
100 | *
101 | * @return The string
102 | */
103 | String falseValue() default "false";
104 |
105 | /** Store the name for this annotation to be be beside
106 | *
107 | * @return The name as a string
108 | */
109 | String name() default "";
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/LogConfig.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger;
2 |
3 | import static java.lang.annotation.ElementType.FIELD;
4 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
5 | import static java.lang.annotation.ElementType.METHOD;
6 |
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.lang.annotation.Target;
10 |
11 | /** Annotations for configuring Logs
12 | * @author Alex Stedman
13 | */
14 | @Retention(RetentionPolicy.RUNTIME)
15 | public @interface LogConfig {
16 | /** Annotation for determining when logged item will be sent to Telemetry
17 | *
18 | */
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
21 | @interface Run {
22 | /** Run the log during the teleop Period
23 | *
24 | * @return The above condition
25 | */
26 | boolean duringRun() default true;
27 |
28 | /** Run the log during the init Period
29 | *
30 | * @return The above condition
31 | */
32 | boolean duringInit() default false;
33 | }
34 |
35 | /** Annotation for allowing Opmodes to log this item
36 | *
37 | */
38 | @Retention(RetentionPolicy.RUNTIME)
39 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
40 | @interface AllowList {
41 | /** The allowed opmodes
42 | *
43 | * @return Opmode Classes
44 | */
45 | Class>[] value();
46 | }
47 |
48 | /** Annotation for denying Opmodes to log this item
49 | *
50 | */
51 | @Retention(RetentionPolicy.RUNTIME)
52 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
53 | @interface DenyList {
54 | /** The denied opmodes
55 | *
56 | * @return Opmode Classes
57 | */
58 | Class>[] value();
59 | }
60 |
61 | /** Annotation to completely disable the entry
62 | *
63 | */
64 | @Retention(RetentionPolicy.RUNTIME)
65 | @Target(value = { FIELD, LOCAL_VARIABLE, METHOD })
66 | @interface Disabled {
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/Loggable.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger;
2 |
3 | /** All classes with annotations for logging must extend this all the way up the hierarchy up to the op mode
4 | * @author Alex Stedman
5 | */
6 | public interface Loggable {}
7 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/entry/BooleanEntry.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger.entry;
2 |
3 | import com.technototes.library.util.Color;
4 | import java.util.function.Supplier;
5 |
6 | public class BooleanEntry extends Entry {
7 |
8 | private String trueEntry, falseEntry;
9 |
10 | public BooleanEntry(String n, Supplier s, int index, String wt, String wf) {
11 | super(n, s, index);
12 | trueEntry = wt;
13 | falseEntry = wf;
14 | }
15 |
16 | @Override
17 | public String toString() {
18 | return (get() ? trueEntry : falseEntry);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/entry/Entry.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger.entry;
2 |
3 | import java.util.function.Supplier;
4 |
5 | /**
6 | * The root class for logging entries
7 | *
8 | * @param The type of value being stored by the entry
9 | * @author Alex Stedman
10 | */
11 | public abstract class Entry implements Supplier {
12 |
13 | /**
14 | * The index (in the list) of the entry
15 | */
16 | protected int x;
17 | /**
18 | * The priority (in the telemetry list) of the entry
19 | */
20 | protected int priority;
21 | /**
22 | * The function called to get the value to display
23 | */
24 | protected Supplier supplier;
25 | /**
26 | * The name of the Entry
27 | */
28 | protected String name;
29 |
30 | /**
31 | * Create an entry with name, value, index
32 | *
33 | * @param n Name of the entry
34 | * @param s Value function to display
35 | * @param index Index of the entry
36 | */
37 | public Entry(String n, Supplier s, int index) {
38 | x = index;
39 | supplier = s;
40 | name = n;
41 | }
42 |
43 | /**
44 | * Set's the priority for this log line (handy for telemetry overflow)
45 | *
46 | * @param p The priority
47 | * @return Self (for chaining)
48 | */
49 | public Entry setPriority(int p) {
50 | priority = p;
51 | return this;
52 | }
53 |
54 | @Override
55 | public T get() {
56 | return supplier.get();
57 | }
58 |
59 | /**
60 | * The String for the logged item
61 | *
62 | * @return The String
63 | */
64 | @Override
65 | public String toString() {
66 | return supplier.get().toString();
67 | }
68 |
69 | /**
70 | * Get the name
71 | *
72 | * @return The name
73 | */
74 | public String getName() {
75 | return name;
76 | }
77 |
78 | /**
79 | * Get the index for the entry
80 | *
81 | * @return The index
82 | */
83 | public int getIndex() {
84 | return x;
85 | }
86 |
87 | /**
88 | * Set index
89 | *
90 | * @param i New index
91 | * @return this
92 | */
93 | public Entry setIndex(int i) {
94 | x = i;
95 | return this;
96 | }
97 |
98 | /**
99 | * Get Priority for the entry
100 | *
101 | * @return The priority
102 | */
103 | public int getPriority() {
104 | return priority;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/entry/NumberEntry.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger.entry;
2 |
3 | import com.technototes.library.util.Color;
4 | import java.util.function.Supplier;
5 |
6 | public class NumberEntry extends Entry {
7 |
8 | protected Color numberColor;
9 |
10 | public NumberEntry(String n, Supplier s, int x) {
11 | super(n, s, x);
12 | }
13 |
14 | @Override
15 | public String toString() {
16 | return numberColor.format(get());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/logger/entry/StringEntry.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.logger.entry;
2 |
3 | import java.util.function.Supplier;
4 |
5 | public class StringEntry extends Entry {
6 |
7 | private String format;
8 |
9 | public StringEntry(String n, Supplier s, int x, String f) {
10 | super(n, s, x);
11 | format = f;
12 | }
13 |
14 | @Override
15 | public String toString() {
16 | return String.format(format, get());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/subsystem/Subsystem.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.subsystem;
2 |
3 | import com.technototes.library.command.Command;
4 | import com.technototes.library.command.CommandScheduler;
5 | import com.technototes.library.general.Periodic;
6 |
7 | public interface Subsystem extends Periodic {
8 | default void register() {
9 | CommandScheduler.register(this);
10 | }
11 |
12 | default Subsystem setDefaultCommand(Command c) {
13 | CommandScheduler.scheduleDefault(c, this);
14 | return this;
15 | }
16 |
17 | default Command getDefaultCommand() {
18 | return CommandScheduler.getDefault(this);
19 | }
20 |
21 | @Override
22 | default void periodic() {}
23 | }
24 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/subsystem/drivebase/DrivebaseSubsystem.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.subsystem.drivebase;
2 |
3 | import com.qualcomm.robotcore.hardware.DcMotorSimple;
4 | import com.technototes.library.hardware.motor.Motor;
5 | import com.technototes.library.subsystem.Subsystem;
6 | import java.util.function.DoubleSupplier;
7 |
8 | /**
9 | * Class for DriveBase subsystems
10 | *
11 | * @param The type of motors for the drivebase
12 | * @author Alex Stedman The motors for the drivebase
13 | */
14 | public abstract class DrivebaseSubsystem implements Subsystem {
15 |
16 | protected Motor[] motors;
17 |
18 | /**
19 | * Override this to get the gyroscope heading.
20 | * Or pass it in to the constructor. Which ever works best for your drivebase implementation.
21 | */
22 | protected DoubleSupplier gyroSupplier = () -> 0;
23 |
24 | /**
25 | * Create a drivebase subsystem
26 | *
27 | * @param motors The drive motors
28 | */
29 | public DrivebaseSubsystem(Motor... motors) {
30 | this.motors = motors;
31 | }
32 |
33 | /**
34 | * Create a drivebase subsystem
35 | *
36 | * @param gyro The gyro supplier
37 | * @param motors The drive motors
38 | */
39 | public DrivebaseSubsystem(DoubleSupplier gyro, Motor... motors) {
40 | this.motors = motors;
41 | gyroSupplier = gyro;
42 | }
43 |
44 | /**
45 | * This will give you a *positive* value to scale the value to such that
46 | * the largest value of the list will be |1| (negative or positive).
47 | *
48 | * This is helpful for an X-Drive drivebase, as the algorithm for calucating
49 | * motor power will often give a collection of values, all of which are smaller than 1.
50 | *
51 | * @param powers The list of values you're setting
52 | * @return The number to divide the values by to set the largest to 1/-1
53 | */
54 | public double getScale(double... powers) {
55 | double max = 0;
56 | for (double d : powers) {
57 | max = Math.max(Math.abs(d), max);
58 | }
59 | return max;
60 | }
61 |
62 | /**
63 | * Get the Gyro angle
64 | *
65 | * @return Gyro angle from supplier
66 | */
67 | public double getGyro() {
68 | return gyroSupplier.getAsDouble();
69 | }
70 |
71 | /**
72 | * Override this one, I guess? Not sure how useful it is.
73 | *
74 | * @return the speed?
75 | */
76 | public double getSpeed() {
77 | return 1;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/subsystem/drivebase/TankDrivebaseSubsystem.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.subsystem.drivebase;
2 |
3 | import com.qualcomm.robotcore.hardware.DcMotorSimple;
4 | import com.qualcomm.robotcore.util.Range;
5 | import com.technototes.library.hardware.motor.Motor;
6 |
7 | /**
8 | * Class for drivebase subsystems
9 | *
10 | * @param The type of motor for the drivebase
11 | * @author Alex Stedman
12 | */
13 | public class TankDrivebaseSubsystem extends DrivebaseSubsystem {
14 |
15 | /**
16 | * Drive motors
17 | */
18 | protected Motor leftSide() {
19 | return motors[0];
20 | }
21 |
22 | protected Motor rightSide() {
23 | return motors[1];
24 | }
25 |
26 | /**
27 | * Create tank drivebase
28 | *
29 | * @param leftMotor The motor/motorgroup for the left side of the drivebase
30 | * @param rightMotor The motor/motorgroup for the right side of the drivebase
31 | */
32 | public TankDrivebaseSubsystem(Motor leftMotor, Motor rightMotor) {
33 | super(leftMotor, rightMotor);
34 | }
35 |
36 | public void arcadeDrive(double y, double x) {
37 | double lp = y + x;
38 | double rp = -y + x;
39 | double scale = getScale(lp, rp);
40 | double speed = Range.clip(Math.abs(y) + Math.abs(x), 0, 1);
41 | scale = scale == 0 ? 0 : speed / scale;
42 | drive(lp * scale, rp * scale);
43 | }
44 |
45 | public void stop() {
46 | drive(0, 0);
47 | }
48 |
49 | public void drive(double l, double r) {
50 | motors[0].setPower(l * getSpeed());
51 | motors[1].setPower(r * getSpeed());
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/Characters.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | public class Characters {
4 |
5 | public static final String BLUE_CIRCLE = "\uD83D\uDD35";
6 | public static final String RED_SQUARE = "\uD83D\uDFE5";
7 | public static final String DUCK = "\uD83E\uDD86";
8 | public static final String CYCLE = "♻️";
9 | public static final String GAMEPAD = "\uD83C\uDFAE";
10 | }
11 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/Color.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | /** Enum for Colors and some formatting
4 | * @author Alex Stedman
5 | */
6 | public enum Color {
7 | RED("FF2222"),
8 | ORANGE("EA5D00"),
9 | YELLOW("FFBF00"),
10 | LIME("69FF00"),
11 | GREEN("00D318"),
12 | CYAN("00E5E5"),
13 | BLUE("1E39CE"),
14 | PURPLE("5A00E2"),
15 | MAGENTA("BE00FF"),
16 | PINK("FF3ADC"),
17 | BLACK("000000"),
18 | WHITE("FFFFFF"),
19 | LIGHT_GRAY("808080"),
20 | DARK_GRAY("404040"),
21 | NO_COLOR("FFFFFF");
22 |
23 | String hexValue;
24 |
25 | Color(String hex) {
26 | hexValue = hex;
27 | }
28 |
29 | /** Get the hex value
30 | *
31 | * @return The hex for the color
32 | */
33 | public String getHexValue() {
34 | return hexValue;
35 | }
36 |
37 | /** Format the supplied object with the HTML to become this color
38 | *
39 | * @param object The object
40 | * @return The formatted String
41 | */
42 | public String format(Object object) {
43 | return ("" + object + "");
44 | }
45 |
46 | /** Format the supplied object with the HTML and a format String to become this color
47 | *
48 | * @param objects The objects
49 | * @param format The format for the supplied String
50 | * @return The formatted String
51 | */
52 | public String format(String format, Object... objects) {
53 | return format(String.format(format, objects));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/Integral.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | import com.qualcomm.robotcore.util.ElapsedTime;
4 |
5 | /**
6 | * A simple Observation-based integral calculator over time
7 | */
8 | public class Integral {
9 |
10 | private double accumulator;
11 | private ElapsedTime deltaTime;
12 |
13 | /**
14 | * Initialize it with the value c
15 | *
16 | * @param c Initial value
17 | */
18 | public Integral(double c) {
19 | accumulator = c;
20 | deltaTime = new ElapsedTime();
21 | }
22 |
23 | /**
24 | * Initialize it with a value of 0
25 | */
26 | public Integral() {
27 | this(0);
28 | }
29 |
30 | /**
31 | * Set the value to C
32 | *
33 | * @param c the value
34 | * @return this
35 | */
36 | public Integral set(double c) {
37 | accumulator = c;
38 | return this;
39 | }
40 |
41 | /**
42 | * Set the value to zero
43 | *
44 | * @return this
45 | */
46 | public Integral zero() {
47 | return set(0);
48 | }
49 |
50 | /**
51 | * Update the accumulated value for the number of seconds since last update
52 | *
53 | * @param change the value that was observed since last integration
54 | * @return the current accumulations
55 | */
56 | public double update(double change) {
57 | accumulator += change * deltaTime.seconds();
58 | deltaTime.reset();
59 | return accumulator;
60 | }
61 |
62 | /**
63 | * Get the current accumulation
64 | *
65 | * @return the current accumulation
66 | */
67 | public double getValue() {
68 | return accumulator;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/MapUtils.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | import android.util.Pair;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 |
7 | public class MapUtils {
8 |
9 | @SafeVarargs
10 | public static Map of(Pair... entries) {
11 | Map map = new HashMap<>();
12 | for (Pair e : entries) {
13 | map.put(e.first, e.second);
14 | }
15 | return map;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/Range.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | /**
4 | * Helper class for tracking a range
5 | *
6 | * Adds minimal value over com.qualcomm.robotcore.util.Range, which is the reason for deprecation
7 | */
8 | @Deprecated
9 | public class Range {
10 |
11 | /**
12 | * The minimum value of the range
13 | */
14 | public double min;
15 |
16 | /**
17 | * The maximum value of the range
18 | */
19 | public double max;
20 |
21 | /**
22 | * Create a range with the given minimum and maximum
23 | *
24 | * @param mi Min value
25 | * @param ma Max value
26 | */
27 | public Range(double mi, double ma) {
28 | min = mi;
29 | max = ma;
30 | if (mi > ma) {
31 | throw new IllegalArgumentException("Minimum is greater than maximum");
32 | }
33 | }
34 |
35 | /**
36 | * Check if the value is in the range
37 | *
38 | * @param val The value to check
39 | * @return True if in (inclusive) range, false otherwise
40 | */
41 | public boolean inRange(double val) {
42 | return val >= min && val <= max;
43 | }
44 |
45 | /**
46 | * Scale the range by a given value
47 | *
48 | * @param scalar The amount to scale the range by
49 | */
50 | public void scale(double scalar) {
51 | min *= scalar;
52 | max *= scalar;
53 | if (min > max) {
54 | double tmp = min;
55 | min = max;
56 | max = tmp;
57 | }
58 | }
59 |
60 | /**
61 | * Get the 'middle' of the range
62 | *
63 | * @return the average of min & max
64 | */
65 | public double middle() {
66 | return (min + max) / 2;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/java/com/technototes/library/util/SmartConsumer.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | /**
7 | * This is a functional interface, when 'accept' is invoked, will only invoke the 'consume' method
8 | * when a different value is provided. It basically removed duplicates.
9 | *
10 | * TODO: This seems like the HashMap is completely unnecessary. Maybe I'm not following the java
11 | * TODO: object model, but I don't see how map ever has more than a single value in it...
12 | *
13 | * @param The type of the value to be accepted/consumed
14 | */
15 | @FunctionalInterface
16 | public interface SmartConsumer {
17 | /**
18 | * The map of values that have been consumed.
19 | */
20 | Map, Object> map = new HashMap<>();
21 |
22 | /**
23 | * The 'consume' function
24 | */
25 | void consume(T t);
26 |
27 | /** The public interface for a SmartConsumer: accept should be invoked, not consume :)
28 | *
29 | * @param t The value being consumed/accepted
30 | * @return
31 | */
32 | default SmartConsumer accept(T t) {
33 | if (!t.equals(getLast())) {
34 | consume(t);
35 | map.put(this, t);
36 | }
37 | return this;
38 | }
39 |
40 | default T getLast() {
41 | return (T) map.get(this);
42 | }
43 |
44 | static void reset() {
45 | map.clear();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/RobotLibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/TestTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | public class TestTest {
6 |
7 | @Test
8 | public void test() {
9 | System.out.println("test");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/command/CancelCommandTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 |
5 | import com.qualcomm.robotcore.util.ElapsedTime;
6 | import org.junit.jupiter.api.BeforeEach;
7 | import org.junit.jupiter.api.Test;
8 |
9 | public class CancelCommandTest {
10 |
11 | class cmd implements Command {
12 |
13 | @Override
14 | public void execute() {
15 | // System.out.println(getRuntime().seconds());
16 | }
17 |
18 | @Override
19 | public boolean isFinished() {
20 | return false;
21 | }
22 | }
23 |
24 | @BeforeEach
25 | public void setup() {
26 | CommandScheduler.resetScheduler();
27 | }
28 |
29 | @Test
30 | public void scheduleCommand() {
31 | Command c = new cmd();
32 | ElapsedTime t = new ElapsedTime();
33 | t.reset();
34 | CommandScheduler.scheduleOnce(c.cancelUpon(() -> c.getRuntime().seconds() > 1));
35 | int finCount = 0;
36 | while (t.seconds() < 5.5) {
37 | CommandScheduler.run();
38 | if (c.justFinished()) finCount++; //System.out.println("finish");
39 | // System.out.println(e++);
40 | }
41 | assertEquals(5, finCount);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/command/CommandForTesting.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | public class CommandForTesting implements Command {
4 |
5 | public int initialized = 0;
6 | public int executed = 0;
7 | public int ended = 0;
8 | public int canceled = 0;
9 |
10 | @Override
11 | public void initialize() {
12 | initialized++;
13 | }
14 |
15 | @Override
16 | public void execute() {
17 | executed++;
18 | }
19 |
20 | @Override
21 | public void end(boolean cancel) {
22 | ended++;
23 | if (cancel) {
24 | canceled++;
25 | }
26 | }
27 |
28 | /*
29 | RESET,
30 | STARTED,
31 | INITIALIZING,
32 | EXECUTING,
33 | FINISHED,
34 | INTERRUPTED,
35 | CANCELLED,
36 | */
37 | private int lastRes = 0;
38 |
39 | public int check(int i, int x, int e, int c) {
40 | int iCheck = (initialized == i) ? 0 : 1000;
41 | int xCheck = (executed == x) ? 0 : 100;
42 | int eCheck = (ended == e) ? 0 : 10;
43 | int cCheck = (canceled == c) ? 0 : 1;
44 | lastRes = iCheck + xCheck + eCheck + cCheck;
45 | return lastRes;
46 | }
47 |
48 | public String lastResult() {
49 | return String.format("%d %d %d %d", initialized, executed, ended, canceled);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/command/CommandGroupTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import org.junit.jupiter.api.BeforeEach;
4 | import org.junit.jupiter.api.Test;
5 |
6 | public class CommandGroupTest {
7 |
8 | Command c1 = () -> print(1), c2 = () -> print(2), c3 = () -> print(3), c4 = () -> print(4), c5 = () -> print(5);
9 |
10 | @BeforeEach
11 | public void setup() {
12 | CommandScheduler.resetScheduler();
13 | }
14 |
15 | @Test
16 | public void scheduleCommand() {
17 | CommandGroup g = new SequentialCommandGroup(c1, c2, c3, c4, c5);
18 | CommandScheduler.schedule(g);
19 | for (int i = 0; i < 100; i++) {
20 | CommandScheduler.run();
21 | // System.out.println(e++);'
22 | }
23 | }
24 |
25 | public void print(int i) {
26 | System.out.println(i);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/command/CommandTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import org.junit.jupiter.api.BeforeEach;
4 | import org.junit.jupiter.api.Test;
5 |
6 | public class CommandTest {
7 |
8 | Command c = this::act;
9 |
10 | public void act() {
11 | System.out.println("it do");
12 | }
13 |
14 | @BeforeEach
15 | public void setup() {
16 | CommandScheduler.resetScheduler();
17 | }
18 |
19 | @Test
20 | public void scheduleCommand() {
21 | long i = System.currentTimeMillis();
22 | int e = 0;
23 | CommandScheduler.schedule(c.sleep(1));
24 | while (System.currentTimeMillis() - i < 10500) {
25 | CommandScheduler.run();
26 | if (c.justFinished()) System.out.println("finish");
27 | // System.out.println(e++);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/command/RequirementCommandTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.command;
2 |
3 | import com.technototes.library.subsystem.Subsystem;
4 | import org.junit.jupiter.api.BeforeEach;
5 | import org.junit.jupiter.api.Test;
6 |
7 | public class RequirementCommandTest {
8 |
9 | public static class DummySubsystem implements Subsystem {
10 |
11 | public void method1() {
12 | System.out.print(1);
13 | }
14 |
15 | public void method2() {
16 | System.out.print(2);
17 | }
18 |
19 | public void method3() {
20 | System.out.print(3);
21 | }
22 | }
23 |
24 | public DummySubsystem subsystem;
25 | public Command command1, command2, command3;
26 |
27 | @BeforeEach
28 | public void setup() {
29 | subsystem = new DummySubsystem();
30 | CommandScheduler.resetScheduler();
31 | command1 = Command.create(subsystem::method1, subsystem);
32 | command2 = Command.create(subsystem::method2, subsystem);
33 | command3 = Command.create(subsystem::method3, subsystem);
34 | }
35 |
36 | @Test
37 | public void run() {
38 | int[] i = new int[1];
39 | CommandScheduler.schedule(command1, () -> i[0] == 0);
40 | CommandScheduler.schedule(command2, () -> i[0] == 1);
41 | CommandScheduler.schedule(command3, () -> i[0] == 2);
42 |
43 | for (i[0] = 0; i[0] < 100; i[0]++) {
44 | CommandScheduler.run();
45 | System.out.println(" - " + command1.getState() + " - " + command2.getState() + " - " + command3.getState());
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/gamepad/GamepadTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.gamepad;
2 |
3 | import com.qualcomm.robotcore.hardware.Gamepad;
4 | import com.technototes.library.control.CommandButton;
5 | import com.technototes.library.control.CommandGamepad;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.BeforeEach;
8 | import org.junit.jupiter.api.Test;
9 |
10 | public class GamepadTest {
11 |
12 | private Gamepad gamepad;
13 | private CommandGamepad commandGamepad;
14 |
15 | @BeforeEach
16 | public void setup() {
17 | gamepad = new Gamepad();
18 | commandGamepad = new CommandGamepad(gamepad);
19 | }
20 |
21 | @Test
22 | public void buttonTest() {
23 | CommandButton commandButton = commandGamepad.xbox_a;
24 | gamepad.a = false;
25 | commandButton.periodic();
26 | gamepad.a = true;
27 | commandButton.periodic();
28 | Assertions.assertTrue(commandButton.isPressed());
29 | Assertions.assertTrue(commandButton.isJustPressed());
30 | Assertions.assertTrue(commandButton.isToggled());
31 | Assertions.assertTrue(commandButton.isJustToggled());
32 | commandButton.periodic();
33 | Assertions.assertTrue(commandButton.isPressed());
34 | Assertions.assertFalse(commandButton.isJustPressed());
35 | Assertions.assertTrue(commandButton.isToggled());
36 | Assertions.assertFalse(commandButton.isJustToggled());
37 | gamepad.a = false;
38 | commandButton.periodic();
39 | gamepad.a = true;
40 | commandButton.periodic();
41 | Assertions.assertTrue(commandButton.isInverseToggled());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/hardware/MockServo.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | import com.qualcomm.robotcore.hardware.Servo;
4 | import com.qualcomm.robotcore.hardware.ServoController;
5 |
6 | public class MockServo implements Servo {
7 |
8 | public MockServo() {}
9 |
10 | @Override
11 | public ServoController getController() {
12 | return null;
13 | }
14 |
15 | @Override
16 | public int getPortNumber() {
17 | return 0;
18 | }
19 |
20 | @Override
21 | public void setDirection(Direction direction) {}
22 |
23 | @Override
24 | public Direction getDirection() {
25 | return null;
26 | }
27 |
28 | double pos;
29 |
30 | @Override
31 | public void setPosition(double position) {
32 | pos = position;
33 | }
34 |
35 | @Override
36 | public double getPosition() {
37 | return pos;
38 | }
39 |
40 | @Override
41 | public void scaleRange(double min, double max) {}
42 |
43 | @Override
44 | public Manufacturer getManufacturer() {
45 | return null;
46 | }
47 |
48 | @Override
49 | public String getDeviceName() {
50 | return null;
51 | }
52 |
53 | @Override
54 | public String getConnectionInfo() {
55 | return null;
56 | }
57 |
58 | @Override
59 | public int getVersion() {
60 | return 0;
61 | }
62 |
63 | @Override
64 | public void resetDeviceConfigurationForOpMode() {}
65 |
66 | @Override
67 | public void close() {}
68 | }
69 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/hardware/ServoProfilerTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.hardware;
2 |
3 | import com.qualcomm.robotcore.util.ElapsedTime;
4 | import com.technototes.library.hardware.servo.Servo;
5 | import com.technototes.library.hardware.servo.ServoProfiler;
6 | import org.junit.jupiter.api.Test;
7 |
8 | public class ServoProfilerTest {
9 |
10 | public ServoProfiler servoController;
11 | public Servo servo;
12 | public ElapsedTime time;
13 |
14 | @Test
15 | public void test() {
16 | servo = new Servo(new MockServo(), "mockServo").startAt(0);
17 | servoController = new ServoProfiler(servo).setConstraints(1, 0.4, 1);
18 | time = new ElapsedTime();
19 | time.reset();
20 | servoController.setTargetPosition(0.7);
21 | while (!servoController.isAtTarget()) {
22 | System.out.println(time.seconds() + ": " + servoController.update().getCurrentPosition());
23 | try {
24 | Thread.sleep(100);
25 | } catch (InterruptedException e) {
26 | e.printStackTrace();
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/opmode/OpModeTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.opmode;
2 |
3 | import com.qualcomm.robotcore.eventloop.opmode.OpMode;
4 | import com.qualcomm.robotcore.hardware.Gamepad;
5 | import com.technototes.library.structure.CommandOpMode;
6 |
7 | public class OpModeTest {
8 |
9 | private OpMode opMode;
10 | // SDK 8.1.1 doesn't let us make a hardware map with a null appContext
11 | // private HardwareMap hardwareMap;
12 | private Gamepad g1, g2;
13 |
14 | public void setup() {
15 | opMode = new TestOpMode();
16 | g1 = new Gamepad();
17 | g2 = new Gamepad();
18 | opMode.gamepad1 = g1;
19 | opMode.gamepad2 = g2;
20 | opMode.hardwareMap = null;
21 | }
22 |
23 | public void run() {}
24 |
25 | public class TestOpMode extends CommandOpMode {
26 |
27 | @Override
28 | public void universalLoop() {
29 | System.out.println(getOpModeState());
30 | }
31 | }
32 |
33 | public boolean callToInitNeeded = false, callToStartNeeded = false, looping = false;
34 |
35 | public void runActiveOpMode() {
36 | //
37 | // opMode.time = opMode.getRuntime();
38 | //
39 | //
40 | //
41 | // if (callToInitNeeded) {
42 | //
43 | // // The point about resetting the hardware is to have it in the same state
44 | // // every time for the *user's* code so that they can simplify their initialization
45 | // // logic. There's no point in bothering / spending the time for the default opmode.
46 | //
47 | // opMode.resetStartTime();
48 | // opMode.internalPreInit();
49 | // opMode.init();
50 | // looping = false;
51 | // callToInitNeeded = false;
52 | // }
53 | //
54 | // /*
55 | // * NOTE: it's important that we use else if here, to avoid more than one user method
56 | // * being called during any one iteration. That, in turn, is important to make sure
57 | // * that if the force-stop logic manages to capture rogue user code, we can cleanly
58 | // * terminate the opmode immediately, without any other user methods being called.
59 | // */
60 | //
61 | // else if (callToStartNeeded) {
62 | // opMode.inter
63 | // opMode.start();
64 | // looping = true;
65 | // callToStartNeeded = false;
66 | // }
67 | //
68 | // else if (!looping) {
69 | // opMode.init_loop();
70 | // } else if (looping) {
71 | // opMode.loop();
72 | // }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/RobotLibrary/src/test/java/com/technototes/library/util/DifferentialTest.java:
--------------------------------------------------------------------------------
1 | package com.technototes.library.util;
2 |
3 | import java.util.function.DoubleConsumer;
4 | import org.junit.jupiter.api.BeforeEach;
5 | import org.junit.jupiter.api.Test;
6 |
7 | public class DifferentialTest {
8 |
9 | public Differential differential;
10 |
11 | public double d1, d2;
12 | public DoubleConsumer i1 = d -> d1 = d;
13 | public DoubleConsumer i2 = d -> d2 = d;
14 |
15 | @BeforeEach
16 | public void setup() {
17 | differential = new Differential(i1, i2);
18 | }
19 |
20 | @Test
21 | public void test() {
22 | check(0, 0);
23 | differential.setOutputs(0.2, 0.2);
24 | check(0.4, 0);
25 | differential.setAverageOutput(0.9);
26 | check(1, 0.7);
27 |
28 | differential.setPriority(Differential.DifferentialPriority.AVERAGE);
29 | check(1, 0.8);
30 |
31 | differential.setPriority(Differential.DifferentialPriority.DIFFERENCE);
32 | check(1, 0.6);
33 |
34 | differential.setOutputs(-0.4, -0.7);
35 | differential.setPriority(Differential.DifferentialPriority.NEUTRAL);
36 | check(-1, 0.3);
37 |
38 | differential.setPriority(Differential.DifferentialPriority.AVERAGE);
39 | check(-1, 0.2);
40 |
41 | differential.setPriority(Differential.DifferentialPriority.DIFFERENCE);
42 | check(-1, 0.4);
43 |
44 | differential.setLimits(0, 1);
45 | differential.setPriority(Differential.DifferentialPriority.NEUTRAL);
46 | check(0, 0.3);
47 | }
48 |
49 | public void check(double a1, double a2) {
50 | assert Math.abs(d1 - a1) + Math.abs(d2 - a2) < 0.00001;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Vision/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Vision/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | namespace = 'com.technototes.vision'
5 |
6 | lint {
7 | disable 'ExpiredTargetSdkVersion'
8 | }
9 |
10 | defaultConfig {
11 | minSdkVersion 24
12 | targetSdkVersion 28
13 | }
14 |
15 | compileSdkVersion 29
16 |
17 | compileOptions {
18 | sourceCompatibility JavaVersion.VERSION_1_8
19 | targetCompatibility JavaVersion.VERSION_1_8
20 | }
21 | }
22 |
23 | dependencies {
24 |
25 | implementation project(':RobotLibrary')
26 |
27 | implementation fileTree(dir: 'libs', include: ['*.jar'])
28 | implementation('org.ejml:ejml-simple:0.39') {
29 | exclude group: 'org.ejml', module: 'ejml-all'
30 | }
31 |
32 | implementation 'org.openftc:easyopencv:1.7.3'
33 |
34 | testImplementation(platform('org.junit:junit-bom:5.7.0'))
35 | testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.0')
36 | testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.0')
37 | testImplementation('org.mockito:mockito-core:3.5.11')
38 | testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.0"
39 |
40 | }
41 |
42 | task javadoc(type: Javadoc) {
43 | source = android.sourceSets.main.java.srcDirs
44 | classpath = project.files(android.getBootClasspath().join(File.pathSeparator))
45 | failOnError false
46 | destinationDir = file("../docs/Vision/")
47 | options {
48 | linkSource true
49 | encoding = 'utf-8'
50 | }
51 | }
52 |
53 | afterEvaluate {
54 | javadoc.classpath += files(android.libraryVariants.collect { variant ->
55 | variant.javaCompileProvider.get().classpath.files
56 | })
57 | }
58 |
59 | apply from: '../build.dependencies.gradle'
60 |
--------------------------------------------------------------------------------
/Vision/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Vision/src/main/java/com/technototes/vision/HSVRange.java:
--------------------------------------------------------------------------------
1 | package com.technototes.vision;
2 |
3 | import org.opencv.core.Scalar;
4 |
5 | /**
6 | * This is used to detect colors in a particular HSV 'range'
7 | */
8 | /**
9 | * This is used to detect colors in a particular HSV 'range'
10 | */
11 | public class HSVRange {
12 |
13 | int hueLow, hueHigh;
14 | int satLow, satHigh;
15 | int valLow, valHigh;
16 |
17 | // Private constructor for wrap around/truncation stuff
18 | private HSVRange(int hLo, int hHi, HSVRange copyFrom) {
19 | hueLow = hLo;
20 | hueHigh = hHi;
21 | satLow = copyFrom.satLow;
22 | satHigh = copyFrom.satHigh;
23 | valLow = copyFrom.valLow;
24 | valHigh = copyFrom.valHigh;
25 | }
26 |
27 | /**
28 | * Create an HSV color range, around 'hue' (0-180, 2 degrees)
29 | *
30 | * @param hue The hue (0-179): each unit is *2* degrees!
31 | * @param hRange The +/- on the hue for detection
32 | * @param sLo The low saturation range
33 | * @param sHi The high saturation range
34 | * @param vLo The low value range
35 | * @param vHi The high value range
36 | */
37 | public HSVRange(int hue, int hRange, int sLo, int sHi, int vLo, int vHi) {
38 | while (hue > 180) {
39 | hue -= 180;
40 | }
41 | while (hue < 0) {
42 | hue += 180;
43 | }
44 | hueLow = hue - Math.min(Math.abs(hRange), 89);
45 | hueHigh = hue + Math.min(Math.abs(hRange), 89);
46 | satLow = Math.min(sLo, sHi);
47 | satHigh = Math.max(sLo, sHi);
48 | valLow = Math.min(vLo, vHi);
49 | valHigh = Math.max(vLo, vHi);
50 | }
51 |
52 | /**
53 | * @return An HSVRange for the 'low end' of the hue range, if it's below 0, null otherwise
54 | */
55 | public HSVRange makeWrapAround() {
56 | if (hueLow >= 0) {
57 | return null;
58 | }
59 | return new HSVRange(180 + hueLow, 180, this);
60 | }
61 |
62 | /**
63 | * @return An HSVRange for the positive part of a hue range if it spans across 0, null otherwise
64 | */
65 | public HSVRange truncateRange() {
66 | if (hueLow < 0) {
67 | return new HSVRange(0, hueHigh, this);
68 | }
69 | return null;
70 | }
71 |
72 | /**
73 | * @param newHue The new hue for an existing HSVrange
74 | * @param hRange The new range for an existing HSVRange
75 | * @return A new HSVRange using the current Saturation and Values, with a new hue & hue range
76 | */
77 | public HSVRange newHue(int newHue, int hRange) {
78 | return new HSVRange(newHue, hRange, satLow, satHigh, valLow, valHigh);
79 | }
80 |
81 | /**
82 | * @return A Scalar for OpenCV use for color detection for the low end
83 | */
84 | public Scalar lowEdge() {
85 | return new Scalar(hueLow, satLow, valLow);
86 | }
87 |
88 | /**
89 | * @return A Scalar for OpenCV use for color detection for the high end
90 | */
91 | public Scalar highEdge() {
92 | return new Scalar(hueHigh, satHigh, valHigh);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/Vision/src/main/java/com/technototes/vision/hardware/InternalCamera.java:
--------------------------------------------------------------------------------
1 | package com.technototes.vision.hardware;
2 |
3 | import com.technototes.library.hardware.DummyDevice;
4 | import org.openftc.easyopencv.OpenCvCameraFactory;
5 | import org.openftc.easyopencv.OpenCvInternalCamera;
6 |
7 | /**
8 | * This is a Camera for use with a phone's internal camera
9 | */
10 | @SuppressWarnings("unused")
11 | public class InternalCamera extends Camera> {
12 |
13 | /**
14 | * Create the front-facing internal camera
15 | */
16 | public InternalCamera() {
17 | this(OpenCvInternalCamera.CameraDirection.FRONT);
18 | }
19 |
20 | /**
21 | * Create a camera (using the one on the phone for the CameraDirection)
22 | *
23 | * @param dir The direction (FRONT or REAR, probably)
24 | */
25 | public InternalCamera(OpenCvInternalCamera.CameraDirection dir) {
26 | super(new DummyDevice<>(dir));
27 | createCamera();
28 | }
29 |
30 | /**
31 | * Get which internal camera is being used
32 | *
33 | * @return FRONT or REAR, probably (TODO)
34 | */
35 | public OpenCvInternalCamera.CameraDirection getCameraDirection() {
36 | return getRawDevice().get();
37 | }
38 |
39 | /**
40 | * Create an OpenCvInternalCamera from this Camera
41 | *
42 | * @return the OpenCvInternalCamera device
43 | */
44 | @Override
45 | public OpenCvInternalCamera createCamera() {
46 | return OpenCvCameraFactory.getInstance()
47 | .createInternalCamera(
48 | getCameraDirection(),
49 | hardwareMap.appContext
50 | .getResources()
51 | .getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName())
52 | );
53 | }
54 |
55 | // TODO: Should we log something?
56 | @Override
57 | public String LogLine() {
58 | return null;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Vision/src/main/java/com/technototes/vision/hardware/Webcam.java:
--------------------------------------------------------------------------------
1 | package com.technototes.vision.hardware;
2 |
3 | import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName;
4 | import org.openftc.easyopencv.OpenCvCameraFactory;
5 | import org.openftc.easyopencv.OpenCvWebcam;
6 |
7 | /**
8 | * Acquire webcamera is just a quit constructor away :)
9 | */
10 | public class Webcam extends Camera {
11 |
12 | /**
13 | * TODO: I'm not sure where WebcamName comes from. I should read up.
14 | *
15 | * @param device The WebcamName for the camera?
16 | */
17 | public Webcam(WebcamName device) {
18 | super(device);
19 | }
20 |
21 | /**
22 | * Create a webcam device configured on the device with the given name
23 | *
24 | * @param device The name of the device as configured in "Robot Configuration"
25 | */
26 | public Webcam(String device) {
27 | super(device);
28 | }
29 |
30 | // TODO: Should we log something?
31 | @Override
32 | public String LogLine() {
33 | return null;
34 | }
35 |
36 | /**
37 | * Create an OpenCvWebcam, which can then be used in your vision pipeline
38 | *
39 | * @return The OpenCvWebcam to use
40 | */
41 | @Override
42 | public OpenCvWebcam createCamera() {
43 | return OpenCvCameraFactory.getInstance()
44 | .createWebcam(
45 | getRawDevice(),
46 | hardwareMap.appContext
47 | .getResources()
48 | .getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName())
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Vision/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/build.dependencies.gradle:
--------------------------------------------------------------------------------
1 | repositories {
2 | mavenCentral()
3 | google() // Needed for androidx
4 | maven { url = 'https://maven.brott.dev/' }
5 | maven { url 'https://jitpack.io' }
6 | }
7 |
8 | dependencies {
9 | implementation 'org.firstinspires.ftc:RobotCore:10.1.0'
10 | implementation 'org.firstinspires.ftc:RobotServer:10.1.0'
11 | implementation 'org.firstinspires.ftc:Hardware:10.1.0'
12 | implementation 'org.firstinspires.ftc:FtcCommon:10.1.0'
13 | implementation 'androidx.appcompat:appcompat:1.3.1'
14 | }
15 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | mavenCentral()
7 | google()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:7.2.0'
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | mavenCentral()
19 | google()
20 | }
21 | }
22 |
23 | repositories {
24 | mavenCentral()
25 | }
26 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/bun.lockb
--------------------------------------------------------------------------------
/docs/TechnoLib/copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
34 |
--------------------------------------------------------------------------------
/docs/TechnoLib/element-list:
--------------------------------------------------------------------------------
1 | com.technototes.library
2 | com.technototes.library.command
3 | com.technototes.library.control
4 | com.technototes.library.general
5 | com.technototes.library.hardware
6 | com.technototes.library.hardware.motor
7 | com.technototes.library.hardware.sensor
8 | com.technototes.library.hardware.sensor.encoder
9 | com.technototes.library.hardware.servo
10 | com.technototes.library.logger
11 | com.technototes.library.logger.entry
12 | com.technototes.library.structure
13 | com.technototes.library.subsystem
14 | com.technototes.library.subsystem.drivebase
15 | com.technototes.library.util
16 |
--------------------------------------------------------------------------------
/docs/TechnoLib/jquery-ui.overrides.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 | *
5 | * This code is free software; you can redistribute it and/or modify it
6 | * under the terms of the GNU General Public License version 2 only, as
7 | * published by the Free Software Foundation. Oracle designates this
8 | * particular file as subject to the "Classpath" exception as provided
9 | * by Oracle in the LICENSE file that accompanied this code.
10 | *
11 | * This code is distributed in the hope that it will be useful, but WITHOUT
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 | * version 2 for more details (a copy is included in the LICENSE file that
15 | * accompanied this code).
16 | *
17 | * You should have received a copy of the GNU General Public License version
18 | * 2 along with this work; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 | *
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 | * or visit www.oracle.com if you need additional information or have any
23 | * questions.
24 | */
25 |
26 | .ui-state-active,
27 | .ui-widget-content .ui-state-active,
28 | .ui-widget-header .ui-state-active,
29 | a.ui-button:active,
30 | .ui-button:active,
31 | .ui-button.ui-state-active:hover {
32 | /* Overrides the color of selection used in jQuery UI */
33 | background: #f8981d;
34 | }
35 |
--------------------------------------------------------------------------------
/docs/TechnoLib/legal/ADDITIONAL_LICENSE_INFO:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\ADDITIONAL_LICENSE_INFO
2 |
--------------------------------------------------------------------------------
/docs/TechnoLib/legal/ASSEMBLY_EXCEPTION:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\ASSEMBLY_EXCEPTION
2 |
--------------------------------------------------------------------------------
/docs/TechnoLib/legal/LICENSE:
--------------------------------------------------------------------------------
1 | Please see ..\java.base\LICENSE
2 |
--------------------------------------------------------------------------------
/docs/TechnoLib/legal/jquery.md:
--------------------------------------------------------------------------------
1 | ## jQuery v3.5.1
2 |
3 | ### jQuery License
4 |
5 | ```
6 | jQuery v 3.5.1
7 | Copyright JS Foundation and other contributors, https://js.foundation/
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining
10 | a copy of this software and associated documentation files (the
11 | "Software"), to deal in the Software without restriction, including
12 | without limitation the rights to use, copy, modify, merge, publish,
13 | distribute, sublicense, and/or sell copies of the Software, and to
14 | permit persons to whom the Software is furnished to do so, subject to
15 | the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be
18 | included in all copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 |
28 | ******************************************
29 |
30 | The jQuery JavaScript Library v3.5.1 also includes Sizzle.js
31 |
32 | Sizzle.js includes the following license:
33 |
34 | Copyright JS Foundation and other contributors, https://js.foundation/
35 |
36 | This software consists of voluntary contributions made by many
37 | individuals. For exact contribution history, see the revision history
38 | available at https://github.com/jquery/sizzle
39 |
40 | The following license applies to all parts of this software except as
41 | documented below:
42 |
43 | ====
44 |
45 | Permission is hereby granted, free of charge, to any person obtaining
46 | a copy of this software and associated documentation files (the
47 | "Software"), to deal in the Software without restriction, including
48 | without limitation the rights to use, copy, modify, merge, publish,
49 | distribute, sublicense, and/or sell copies of the Software, and to
50 | permit persons to whom the Software is furnished to do so, subject to
51 | the following conditions:
52 |
53 | The above copyright notice and this permission notice shall be
54 | included in all copies or substantial portions of the Software.
55 |
56 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
57 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
59 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
60 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
61 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
62 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63 |
64 | ====
65 |
66 | All files located in the node_modules and external directories are
67 | externally maintained libraries used by this software which have their
68 | own licenses; we recommend you read them, as their terms may differ from
69 | the terms above.
70 |
71 | *********************
72 |
73 | ```
74 |
--------------------------------------------------------------------------------
/docs/TechnoLib/legal/jqueryUI.md:
--------------------------------------------------------------------------------
1 | ## jQuery UI v1.12.1
2 |
3 | ### jQuery UI License
4 | ```
5 | Copyright jQuery Foundation and other contributors, https://jquery.org/
6 |
7 | This software consists of voluntary contributions made by many
8 | individuals. For exact contribution history, see the revision history
9 | available at https://github.com/jquery/jquery-ui
10 |
11 | The following license applies to all parts of this software except as
12 | documented below:
13 |
14 | ====
15 |
16 | Permission is hereby granted, free of charge, to any person obtaining
17 | a copy of this software and associated documentation files (the
18 | "Software"), to deal in the Software without restriction, including
19 | without limitation the rights to use, copy, modify, merge, publish,
20 | distribute, sublicense, and/or sell copies of the Software, and to
21 | permit persons to whom the Software is furnished to do so, subject to
22 | the following conditions:
23 |
24 | The above copyright notice and this permission notice shall be
25 | included in all copies or substantial portions of the Software.
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 |
35 | ====
36 |
37 | Copyright and related rights for sample code are waived via CC0. Sample
38 | code is defined as all source code contained within the demos directory.
39 |
40 | CC0: http://creativecommons.org/publicdomain/zero/1.0/
41 |
42 | ====
43 |
44 | All files located in the node_modules and external directories are
45 | externally maintained libraries used by this software which have their
46 | own licenses; we recommend you read them, as their terms may differ from
47 | the terms above.
48 |
49 | ```
50 |
--------------------------------------------------------------------------------
/docs/TechnoLib/module-search-index.js:
--------------------------------------------------------------------------------
1 | moduleSearchIndex = [];
2 | updateSearchResults();
3 |
--------------------------------------------------------------------------------
/docs/TechnoLib/overview-summary.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | RobotLibrary API
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
18 |
19 |
20 |
21 |
24 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/docs/TechnoLib/tag-search-index.js:
--------------------------------------------------------------------------------
1 | tagSearchIndex = [{ l: 'Constant Field Values', h: '', u: 'constant-values.html' }];
2 | updateSearchResults();
3 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # TechnoLib documentation
2 |
3 | - [TechnoLib](https://technototes.github.io/TechnoLib/TechnoLib)
4 | - [Path](https://technototes.github.io/TechnoLib/Path)
5 | - [Vision](https://technototes.github.io/TechnoLib/Vision)
6 | - [Source Code](https://github.com/technototes/TechnoLib/)
7 |
8 | > TechnoLib is an FTC Library for everyone:
9 |
10 | - WPILib inspired command structure
11 | - Tons of simple implementations to provide abstractions, and teach you the basics
12 | - EasyOpenCV integration for vision
13 | - RoadRunner integration for path-following
14 | - Annotation based Telemetry
15 |
16 | **The goal of TechnoLib is not only to provide versatile resources that assist in software
17 | development and strengthen code structure, but to also abstract out redundancy.**
18 |
19 | ## Installation
20 |
21 | But if this library is so good, it must be hard to install right? wrong:
22 |
23 | - Add this right before the dependencies{} block in TeamCode/build.gradle:
24 | ```
25 | repositories{
26 | ` maven { url = 'https://maven.brott.dev/' }
27 | maven { url 'https://jitpack.io' }
28 | }
29 | ```
30 | - And add this to the dependencies block in TeamCode/build.gradle:
31 | `implementation 'com.github.technototes:TechnoLib:1.1.2'`
32 | **(replace 1.1.2 with the latest release)**
33 | - Build the code and you are good to go
34 |
35 | ## Ease of Use
36 |
37 | But if this library is so powerful, won't it be hard to use? Nope, in fact its easier than without
38 | the library
39 |
40 | - Complex subsystems have already been written for you
41 | - Plenty of simple things to make your life easier
42 | - Test implementation so you can see how to make this work
43 |
44 | ## Documentation
45 |
46 | There are not currently any good 'stand alone' examples. The best place for you to get an idea of
47 | how this stuff works is in our robot code. It's all public on github: idea of how this stuff works
48 | is in our robot code. It's all public on github:
49 |
50 | - Freight Frenzy (2021-2022)' s
51 | [16750 robot source code](https://github.com/technototes/FreightFrenzy2021/tree/master/OspreyCode/src/main/java/org/firstinspires/ftc/teamcode)
52 | ( this is a more advanced usage, written by the library's primary autho)
53 | - Freight Frenzy (2021-2022)' s
54 | [20403 robot source code](https://github.com/technototes/FreightFrenzy2021/tree/master/SeagullCode/src/main/java/org/firstinspires/ftc/teamcode)
55 | ( This is a simpler usage, written by students who mostly learned by example)
56 | - And here's a PowerPlay (2022-2023) based example
57 | ["learning" bot](https://github.com/technototes/PowerPlay2022/tree/main/ForTeaching/src/main/java/org/firstinspires/ftc/forteaching/TechnoBot)
58 | ( This is a very basic example of a few concepts, include vision)
59 |
60 | Good luck!
61 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | android.enableJetifier=true
13 | android.useAndroidX=true
14 | org.gradle.jvmargs=-Xmx1536m
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/technototes/TechnoLib/4b6e7e8cbcf8d92d7c414125758d6d0915d995ad/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Sep 27 22:08:26 PDT 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
4 | distributionPath=wrapper/dists
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TechnoLib Documentation
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | # Notes for Kevin
2 |
3 | (I'm the software mentor for 16750/20403 and have picked up ownership of TechnLib from Alex Stedman,
4 | the original author, as he's doing silly things like "attending college")
5 |
6 | ## Hardware details to keep in mind
7 |
8 | The analog sticks are vertically inverted: When you push the stick up/away, the Y value decreases.
9 |
10 | The shoulder triggers' range is from 0 to 1, not -1 to 1.
11 |
12 | I'm not currently sure what orientation the SDK 8.1+ IMU calls 0 degrees.
13 |
14 | ## Simulation
15 |
16 | This has been in my head since my first year (2019, SkyStone)
17 |
18 | There ought to be a simulator for this stuff. It would let programmers work more independently to
19 | validate basic stuff. I've never built a simulator, but I'm a semi competent developer, so (famous
20 | last words) how hard can it be? ftcsim and vrs both lack some amount of flexibility, why doing a lot
21 | more than what I really need/want for a team who's building a real bot.
22 |
23 | The core things that would need simulated:
24 |
25 | - Motors (with encoders)
26 | - Servos (in both CR and Servo mode)
27 | - Sensors (pick the order to get them going)
28 | - IMU
29 | - Bump
30 | - Color
31 | - 2M range
32 | - Range
33 |
34 | Probably not worth simulating:
35 |
36 | - Vision. I could support connecting a webcam so the students could use an actual webcam, but I'm
37 | not about to deal with AprilTags and TFOD. ML sucks. It doesn't work at level level of determinism
38 | that makes me thing I could do anything useful with it. It's quantum physics, if the probability
39 | of weird stuff happening is 10^-2 instead of 10^-20000000. Thanks, but no thanks.
40 | - Controllers. Just wire them up from the computer
41 |
42 | Where do things get messy? I'd need some mechanism to translate rotational motion. I don't have the
43 | interest to do a full physics simulator, so I could potentially make this pretty rudimentary.
44 |
45 | ### What's next?
46 |
47 | Get through this season, then maybe start horsing around with this? Maybe learn Kotlin, since it
48 | looks _much_ less verbose than Java (Seriously, Java, you've had almost 30 years. Why do you still
49 | hate developers so much?)
50 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "technolib",
3 | "version": "1.3.1",
4 | "description": "TechnoLib automation scripts",
5 | "main": "build/automation.js",
6 | "repository": "https://github.com/technototes/TechnoLib.git",
7 | "author": "Kevin Frei ",
8 | "license": "MIT",
9 | "scripts": {
10 | "build": "bun run gradle build",
11 | "fulldoc": "bun run doc && bun run format",
12 | "docs": "bun run gradle javadoc",
13 | "doc": "bun run gradle javadoc",
14 | "format": "tools format bun",
15 | "gradle": "bun run os gradle",
16 | "gradle:win": ".\\\\gradlew",
17 | "gradle:def": "./gradlew",
18 | "os": "bun run scripts/os.ts"
19 | },
20 | "devDependencies": {
21 | "@freik/workspace": "^0.6.4",
22 | "prettier": "3.3.3",
23 | "prettier-plugin-java": "2.6.4"
24 | },
25 | "packageManager": "bun@1.1.27"
26 | }
27 |
--------------------------------------------------------------------------------
/scripts/os.ts:
--------------------------------------------------------------------------------
1 | // This is a bun-specific replacement for the run-script-os NodeJS thing
2 | // It takes a script, and invokes the "script:os" command
3 | // if the script:win/mac/lin command doesn't exist, it falls back to the script:def command
4 | import path from 'path';
5 | import fs from 'fs/promises';
6 | import os from 'os';
7 | import { chkObjectOf, hasFieldType, hasStrField, isString } from '@freik/typechk';
8 | import Bun from 'bun';
9 |
10 | const osmap = new Map([
11 | ['win32', 'win'],
12 | ['darwin', 'mac'],
13 | ['linux', 'lin'],
14 | ]);
15 |
16 | async function main() {
17 | // argv[1] is this script's name, so find the package.json file from there
18 | const pkg = path.resolve(path.join(path.dirname(Bun.argv[1]), '..', 'package.json'));
19 | const args = Bun.argv.slice(2);
20 | const pkgj = JSON.parse(await fs.readFile(pkg, 'utf8'));
21 | if (!hasFieldType(pkgj, 'scripts', chkObjectOf(isString))) {
22 | throw new Error('No scripts field in package.json');
23 | }
24 | const scriptName = args[0];
25 | const suffix = osmap.get(os.platform()) || 'def';
26 | const script = `${scriptName}:${suffix}`;
27 | const scriptdef = `${scriptName}:def`;
28 | const theScript = hasStrField(pkgj.scripts, script)
29 | ? script
30 | : hasStrField(pkgj.scripts, scriptdef)
31 | ? scriptdef
32 | : undefined;
33 | if (!isString(theScript)) {
34 | throw new Error(`No script found for ${scriptName} for ${os.platform()}`);
35 | }
36 | const cmds = args
37 | .slice(1)
38 | .map((v) => Bun.$.escape(v))
39 | .join(' ');
40 | await Bun.$`bun run ${theScript} ${{ raw: cmds }}`;
41 | }
42 |
43 | main().catch((err) => console.error(err));
44 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':RobotLibrary'
2 | include ':Path'
3 | include ':Vision'
4 |
--------------------------------------------------------------------------------