Skip to content

Commit

Permalink
Release 3.0-alpha
Browse files Browse the repository at this point in the history
Initial release
  • Loading branch information
SMEZ1234 committed Jan 4, 2020
1 parent 722efcb commit 0e7e3a6
Show file tree
Hide file tree
Showing 103 changed files with 4,034 additions and 0 deletions.
163 changes: 163 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Created by https://www.gitignore.io/api/c++,java,linux,macos,gradle,windows,visualstudiocode

### C++ ###
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

### Java ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

### Windows ###
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

### Gradle ###
.gradle
/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Cache of project
.gradletasknamecache

# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties

# # VS Code Specific Java Settings
.classpath
.project
.settings/
bin/


# End of https://www.gitignore.io/api/c++,java,linux,macos,gradle,windows,visualstudiocode

*.json
*gradle*
30 changes: 30 additions & 0 deletions examples/arachne/examples/ArcadeDriveRobot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package arachne.examples;

import arachne.lib.hardware.DifferentialDrivetrain;
import arachne.lib.hardware.SimpleDifferentialDrivetrain;
import arachne.lib.pipeline.SimpleDoubleSource;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.SpeedController;
import edu.wpi.first.wpilibj.Talon;

public class ArcadeDriveRobot extends RobotBase
{
public static DifferentialDrivetrain drivetrain = new SimpleDifferentialDrivetrain(false);

@Override
@SuppressWarnings("resource")
public void startCompetition() {
Joystick controller = new Joystick(0);

SpeedController
leftMotor = new Talon(0),
rightMotor = new Talon(1);

new SimpleDoubleSource(controller::getX).attachOutput(drivetrain.arcadeSource.getRotationInput());
new SimpleDoubleSource(controller::getY).attachOutput(drivetrain.arcadeSource.getSpeedInput());

drivetrain.getLeftOutput().attachOutput(leftMotor::set);
drivetrain.getLeftOutput().attachOutput(rightMotor::set);
}
}
127 changes: 127 additions & 0 deletions src/main/java/arachne/lib/ArachneRobot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package arachne.lib;

import arachne.lib.game.GameState;
import arachne.lib.logging.ArachneLogger;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.NotifierJNI;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.RobotController;
import edu.wpi.first.wpilibj.Watchdog;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

public class ArachneRobot extends RobotBase
{
public static final double DEFAULT_PERIOD = 0.02;

protected final double loopPeriod;
protected final Watchdog watchdog;

// The C pointer to the notifier object. We don't use it directly, it is
// just passed to the JNI bindings.
protected final int notifierHandle = NotifierJNI.initializeNotifier();

protected GameState gameState;

public ArachneRobot() {
this(DEFAULT_PERIOD);
}

public ArachneRobot(double loopPeriod) {
this.loopPeriod = loopPeriod;
this.watchdog = new Watchdog(loopPeriod, this::handleLoopOverrun);
}

@Override
public void startCompetition() {
initialize();

// Tell the DS that the robot is ready to be enabled
HAL.observeUserProgramStarting();

double nextLoopTime = RobotController.getFPGATime() * 1e-6 + loopPeriod;
updateAlarm(nextLoopTime);

// Loop forever, calling Arachne's execution and state change functions
while(true) {
try {
if(NotifierJNI.waitForNotifierAlarm(notifierHandle) == 0) break;

nextLoopTime += loopPeriod;
updateAlarm(nextLoopTime);

loopFunc();
}
catch(Exception e) {
errorFallback(e);
}
}
}

/**
* Update the alarm hardware to reflect the next alarm.
*/
protected void updateAlarm(double nextLoopTime) {
NotifierJNI.updateNotifierAlarm(notifierHandle, (long) (nextLoopTime * 1e6));
}

protected void loopFunc() {
watchdog.reset();

// Determine current state
GameState newState;
if(isDisabled()) newState = GameState.DISABLED;
else if(isAutonomous()) newState = GameState.AUTO;
else if(isOperatorControl()) newState = GameState.TELEOP;
else newState = GameState.TELEOP;

// Handle state change
if(gameState != newState) {
// Only enable live window and actuator widgets in test mode
if(newState == GameState.TEST) {
LiveWindow.setEnabled(true);
Shuffleboard.enableActuatorWidgets();
}
else {
LiveWindow.setEnabled(false);
Shuffleboard.disableActuatorWidgets();
}

// Handle mode-specific state changes
onStateChange(gameState, newState);
watchdog.addEpoch("onStateChange: " + gameState + " -> " + newState);
}

// Execute periodic code for state
gameState = newState;
gameState.halObserver.run();

execute(gameState);
watchdog.addEpoch("execute: " + gameState);

watchdog.disable();

// Update displayed values
SmartDashboard.updateValues();
LiveWindow.updateValues();
Shuffleboard.update();

// Warn on loop time overruns
if(watchdog.isExpired()) watchdog.printEpochs();
}

protected void initialize() {}
protected void execute(GameState state) {}
protected void onStateChange(GameState oldState, GameState newState) {}

protected void errorFallback(Exception exception) {
ArachneLogger.getInstance().critical("Error from inside robot's loopFunc(): " + exception.getMessage());
DriverStation.reportError(exception.getMessage(), exception.getStackTrace());
}

protected void handleLoopOverrun() {
DriverStation.reportWarning("Loop time of " + loopPeriod + "s overrun\n", false);
}
}
17 changes: 17 additions & 0 deletions src/main/java/arachne/lib/BindingManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package arachne.lib;

import java.util.function.Supplier;

import edu.wpi.first.wpilibj.RobotBase;

public abstract class BindingManager<RobotT>
{
public static <BindingManagerT extends BindingManager<RobotT>, RobotT extends RobotBase> BindingManagerT create(RobotT robot, Supplier<BindingManagerT> bindingManagerSupplier) {
BindingManagerT bindingManager = bindingManagerSupplier.get();
bindingManager.createBindings(robot);

return bindingManager;
}

protected abstract void createBindings(RobotT robot);
}
15 changes: 15 additions & 0 deletions src/main/java/arachne/lib/HardwareManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package arachne.lib;

import java.util.function.Supplier;

public abstract class HardwareManager
{
public static <T extends HardwareManager> T create(Supplier<T> hardwareManagerSupplier) {
T hardwareManager = hardwareManagerSupplier.get();
hardwareManager.initializeHardware();

return hardwareManager;
}

protected abstract void initializeHardware();
}
16 changes: 16 additions & 0 deletions src/main/java/arachne/lib/function/BooleanConsumer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package arachne.lib.function;

import java.util.Objects;

import arachne.lib.io.SettableBoolean;

@FunctionalInterface
public interface BooleanConsumer
{
void accept(boolean value);

default SettableBoolean andThen(SettableBoolean after) {
Objects.requireNonNull(after);
return (value) -> { accept(value); after.accept(value); };
}
}
13 changes: 13 additions & 0 deletions src/main/java/arachne/lib/function/BooleanFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package arachne.lib.function;

@FunctionalInterface
public interface BooleanFunction<R> {

/**
* Applies this function to the given argument.
*
* @param value the function argument
* @return the function result
*/
R apply(boolean value);
}
Loading

0 comments on commit 0e7e3a6

Please sign in to comment.