Initial release: FTC Project Generator

Generate clean, testable FTC robot projects with proper separation from SDK bloat.

Features:
- Composite build setup - one shared SDK, multiple clean projects
- Subsystem pattern with hardware interfaces for easy testing
- JUnit scaffolding - tests run on PC without robot
- Minimal project structure (~50KB vs 200MB SDK)
- Support for multiple FTC SDK versions

Philosophy: Your code should be YOUR code. SDK is just a dependency.

Built by Nexus Workshops for FTC teams tired of fighting the standard structure.

License: MIT
This commit is contained in:
Eric Ratliff
2026-01-13 23:58:43 -06:00
commit 81452a8670
10 changed files with 2350 additions and 0 deletions

34
.dockerignore Normal file
View File

@@ -0,0 +1,34 @@
# Git
.git
.gitignore
.gitattributes
# CI/CD
.github
# Documentation
README.md
LICENSE
*.md
# Build artifacts
build/
*/build/
.gradle/
*.apk
*.aab
# IDE
.idea/
*.iml
.vscode/
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
# Local config
local.properties

58
.editorconfig Normal file
View File

@@ -0,0 +1,58 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
# Java files
[*.java]
indent_style = space
indent_size = 4
continuation_indent_size = 8
# Gradle files
[*.gradle]
indent_style = space
indent_size = 4
[*.kts]
indent_style = space
indent_size = 4
# XML files
[*.xml]
indent_style = space
indent_size = 4
# Properties files
[*.properties]
indent_style = space
indent_size = 4
# Shell scripts
[*.sh]
indent_style = space
indent_size = 4
end_of_line = lf
# Markdown
[*.md]
trim_trailing_whitespace = false
indent_style = space
indent_size = 2
# YAML
[*.{yml,yaml}]
indent_style = space
indent_size = 2
# JSON
[*.json]
indent_style = space
indent_size = 2

76
.gitattributes vendored Normal file
View File

@@ -0,0 +1,76 @@
# Auto detect text files and perform LF normalization
* text=auto
# Java sources
*.java text diff=java
*.gradle text diff=java
*.gradle.kts text diff=java
# These files are text and should be normalized (Convert crlf => lf)
*.css text
*.df text
*.htm text
*.html text
*.js text
*.json text
*.jsp text
*.jspf text
*.jspx text
*.properties text
*.sh text
*.svg text
*.tld text
*.txt text
*.tag text
*.tagx text
*.xml text
*.yml text
*.yaml text
# These files are binary and should be left untouched
# (binary is a macro for -text -diff)
*.class binary
*.dll binary
*.ear binary
*.jar binary
*.so binary
*.war binary
*.jks binary
*.keystore binary
*.aar binary
*.apk binary
*.ap_ binary
*.aab binary
*.dex binary
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
*.flv binary
*.fla binary
*.swf binary
*.gz binary
*.zip binary
*.7z binary
*.ttf binary
*.eot binary
*.woff binary
*.woff2 binary
*.pyc binary
*.pdf binary
*.ez binary
*.bz2 binary
*.swp binary
*.bin binary
# Gradle wrapper scripts should always use LF
gradlew text eol=lf
*.sh text eol=lf
# Windows batch files should use CRLF
*.bat text eol=crlf
*.cmd text eol=crlf

114
.gitignore vendored Normal file
View File

@@ -0,0 +1,114 @@
# Built application files
*.apk
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
release/
# Gradle files
.gradle/
build/
**/build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
.externalNativeBuild
.cxx
# IntelliJ
*.iml
.idea/
misc.xml
deploymentTargetDropDown.xml
render.experimental.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
*.jks
*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# Google Services (e.g. APIs or Firebase)
google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
*.lint
# Android Profiling
*.hprof
# OS-specific files
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# Linux
*~
# IDE-specific
*.swp
*.swo
*~
# Node modules (if using any JS tooling)
node_modules/
# Backup files
*.bak
*.orig
# FTC specific
libs/*.aar
# TeamCode build outputs that shouldn't be committed
TeamCode/build/
FtcRobotController/build/

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Nexus Workshops LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

295
README.md Normal file
View File

@@ -0,0 +1,295 @@
# FTC Project Generator
Generate clean, testable FTC robot projects. Keep YOUR code separate from the FTC SDK bloat.
## Philosophy
**Normal FTC Way:** Clone their repo, modify their code
**This Way:** Your code is clean, FTC SDK is just a dependency
One shared SDK, multiple clean projects. Test on PC, deploy when ready.
## Quick Start
```bash
# Create your first project
./ftc-new-project my-robot
# Create another project (reuses same SDK!)
./ftc-new-project another-bot
# Use specific FTC version
./ftc-new-project test-bot --version v10.0.0
```
## What It Does
1. **Checks/clones FTC SDK** (once, shared across projects)
2. **Creates YOUR clean project** with:
- Minimal structure
- Test scaffolding
- Example subsystem
- Composite build to SDK
3. **Ready to code** - tests run immediately
## Generated Project Structure
```
my-robot/
├── build.gradle.kts # Your build (references SDK)
├── settings.gradle.kts # Composite build setup
├── gradlew # Gradle wrapper
├── README.md # Project-specific docs
└── src/
├── main/java/robot/
│ ├── Pose2d.java # Utility classes
│ ├── subsystems/
│ │ └── Drive.java # Example subsystem
│ ├── hardware/
│ │ └── MecanumDrive.java # Hardware impl stub
│ └── opmodes/
│ └── TeleOp.java # FTC OpMode
└── test/java/robot/
└── subsystems/
└── DriveTest.java # Unit test
Separate (shared):
~/ftc-sdk/ # FTC SDK (one copy for all projects)
```
## Usage
### Development (Day-to-Day)
```bash
cd my-robot
# Run tests
./gradlew test
# Watch mode (auto-rerun on save)
./gradlew test --continuous
# Write code, tests pass → you're good!
```
### Deployment (When Ready for Robot)
```bash
# 1. Deploy your code to SDK
./gradlew deployToSDK
# 2. Build APK
cd ~/ftc-sdk
./gradlew build
# 3. Install to robot
# Use Android Studio's deploy button, or:
adb install FtcRobotController/build/outputs/apk/debug/FtcRobotController-debug.apk
```
## Multiple Projects
The beauty: **one SDK, many projects**
```bash
# Create project 1
./ftc-new-project swerve-bot
# Create project 2 (reuses SDK!)
./ftc-new-project mecanum-bot
# Create project 3 (still same SDK!)
./ftc-new-project test-chassis
```
Each project:
- Has its own git repo
- Tests independently
- Deploys to shared SDK
- Can have different license
- Is YOUR code, not FTC's
## Commands Reference
```bash
# Basic usage
./ftc-new-project <name>
# Specify FTC version
./ftc-new-project <name> --version v10.1.1
# Custom SDK location
./ftc-new-project <name> --sdk-dir ~/my-ftc
# Get help
./ftc-new-project --help
```
## Environment Variables
```bash
# Set default SDK location
export FTC_SDK_DIR=~/ftc-sdk
# Now just:
./ftc-new-project my-robot
```
## Pattern: Subsystems
Every generated project follows this pattern:
```java
// Your subsystem
public class MySubsystem {
private final Hardware hardware;
public MySubsystem(Hardware hardware) {
this.hardware = hardware;
}
// Business logic here - tests on PC
public void doSomething() {
hardware.doThing();
}
// Inner interface - implement for robot
public interface Hardware {
void doThing();
}
}
// Test (inline mock)
class MySubsystemTest {
static class MockHardware implements MySubsystem.Hardware {
boolean didThing = false;
public void doThing() { didThing = true; }
}
@Test
void test() {
MockHardware mock = new MockHardware();
MySubsystem sys = new MySubsystem(mock);
sys.doSomething();
assertTrue(mock.didThing);
}
}
// Hardware impl (for robot)
public class RealHardware implements MySubsystem.Hardware {
private DcMotor motor;
public RealHardware(HardwareMap map) {
motor = map.get(DcMotor.class, "motor");
}
public void doThing() {
motor.setPower(1.0);
}
}
```
## Why This Is Better
**Traditional FTC:**
- Clone 200MB repo
- Your code mixed with SDK
- Hard to test
- Hard to share
- Stuck with their structure
**This Way:**
- Your project: ~50KB
- SDK: shared, separate
- Easy to test (runs on PC)
- Easy to share (just your code)
- Your structure, your license
## FAQ
**Q: Can I use multiple FTC versions?**
A: Yes! Different projects can reference different SDK dirs.
**Q: What if I want to update the SDK?**
A: `cd ~/ftc-sdk && git pull && git checkout v10.2.0`
Or specify new version when creating project.
**Q: Does this work with Android Studio?**
A: For deployment, yes. For development, use whatever you want (Sublime, vim, etc).
**Q: Can I put my project on GitHub with a different license?**
A: Yes! Your code is separate. Just don't include SDK files.
**Q: What about Control Hub having multiple programs?**
A: Each project creates OpModes. Deploy multiple projects to SDK, build once, all show up on Control Hub.
## Installation
```bash
# Extract the generator
tar xzf ftc-project-generator.tar.gz
cd ftc-project-gen
# Option 1: Run install script (recommended)
./install.sh # Shows options
sudo ./install.sh # System-wide install
# Option 2: Manual symlink
sudo ln -s $(pwd)/ftc-new-project /usr/local/bin/
# Option 3: Add to PATH
echo "export PATH=\$PATH:$(pwd)" >> ~/.bashrc
source ~/.bashrc
# Verify installation
ftc-new-project --help
```
## The Magic
When you run tests, your code uses **interfaces** and **mocks** - no FTC SDK needed.
When you deploy, your code gets copied to SDK's TeamCode and built with the real FTC libraries.
Your code stays clean. SDK is just a build tool.
## Example Session
```bash
# Create project
$ ./ftc-new-project my-bot
>>> Checking FTC SDK...
SDK directory exists, checking version...
✓ SDK already at version v10.1.1
>>> Creating project: my-bot
✓ Project created: my-bot
# Develop
$ cd my-bot
$ ./gradlew test
BUILD SUCCESSFUL
2 tests passed
# Add code, tests pass...
# Ready to deploy
$ ./gradlew deployToSDK
Code deployed to TeamCode - ready to build APK
$ cd ~/ftc-sdk
$ ./gradlew build
BUILD SUCCESSFUL
# Install to robot...
```
Clean, simple, modular. As it should be.
## Credits
Built by frustrated mentors who think the standard FTC setup is backwards.
## License
MIT - do whatever you want. Unlike FTC's forced BSD license nonsense.

108
TROUBLESHOOTING.md Normal file
View File

@@ -0,0 +1,108 @@
# Troubleshooting
## Error: "Project with path ':RobotCore' not found"
**Symptom:**
```
FAILURE: Build failed with an exception.
* What went wrong:
Project with path ':RobotCore' not found in build ':ftc-sdk'.
```
**Cause:** FTC SDK was not cloned or is at wrong location.
**Solution:**
1. Check if SDK exists:
```bash
ls ~/ftc-sdk
# Should show: FtcRobotController, RobotCore, Hardware, etc.
```
2. If SDK doesn't exist, clone it:
```bash
git clone --depth 1 --branch v10.1.1 \
https://github.com/FIRST-Tech-Challenge/FtcRobotController.git \
~/ftc-sdk
```
3. Check your project's `gradle.properties`:
```bash
cat gradle.properties
# Should show: ftcSdkDir=/home/yourusername/ftc-sdk
```
4. Update if path is wrong:
```bash
echo "ftcSdkDir=$HOME/ftc-sdk" > gradle.properties
```
5. Try again:
```bash
./gradlew test
```
## Error: Can't find SDK at specified path
**Solution:** Set environment variable:
```bash
export FTC_SDK_DIR=~/ftc-sdk
./gradlew test
```
Or edit `gradle.properties` in your project.
## SDK exists but wrong version
**Solution:** Update SDK to correct version:
```bash
cd ~/ftc-sdk
git fetch --tags
git checkout v10.1.1 # or whatever version you need
```
## Fresh Start
If all else fails:
```bash
# Remove old SDK
rm -rf ~/ftc-sdk
# Remove old project
rm -rf my-project
# Start fresh
ftc-new-project my-project
# Verify SDK was cloned
ls ~/ftc-sdk
# Test
cd my-project
./gradlew test
```
## Verify Setup
Run this diagnostic:
```bash
#!/bin/bash
echo "=== FTC Setup Diagnostic ==="
echo ""
echo "1. SDK Directory:"
ls -la ~/ftc-sdk 2>/dev/null || echo " ✗ SDK not found at ~/ftc-sdk"
echo ""
echo "2. SDK Modules:"
ls ~/ftc-sdk/RobotCore 2>/dev/null && echo " ✓ RobotCore found" || echo " ✗ RobotCore missing"
ls ~/ftc-sdk/Hardware 2>/dev/null && echo " ✓ Hardware found" || echo " ✗ Hardware missing"
echo ""
echo "3. Project gradle.properties:"
cat gradle.properties 2>/dev/null || echo " ✗ No gradle.properties in current dir"
echo ""
echo "4. Environment:"
echo " FTC_SDK_DIR=$FTC_SDK_DIR"
```
Save as `check-setup.sh` and run it in your project directory.

64
build.gradle.kts.simple Normal file
View File

@@ -0,0 +1,64 @@
plugins {
java
}
repositories {
mavenCentral()
google()
}
dependencies {
// Testing (runs on PC without SDK) - THIS IS WHAT YOU USE FOR DEVELOPMENT
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation("org.mockito:mockito-core:5.5.0")
// FTC SDK - ONLY needed when you uncomment FTC code for deployment
// These will be compile errors until you uncomment, that's OK!
// compileOnly(files("${System.getenv("HOME")}/ftc-sdk/RobotCore/build/libs/RobotCore-release.aar"))
// compileOnly(files("${System.getenv("HOME")}/ftc-sdk/Hardware/build/libs/Hardware-release.aar"))
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
showStandardStreams = false
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}
// Task to deploy to FTC SDK
tasks.register<Copy>("deployToSDK") {
group = "ftc"
description = "Copy code to FTC SDK TeamCode for deployment"
val sdkDir = System.getenv("HOME") + "/ftc-sdk"
from("src/main/java")
into("$sdkDir/TeamCode/src/main/java")
doLast {
println("✓ Code deployed to $sdkDir/TeamCode")
println("")
println("Next steps:")
println(" cd $sdkDir")
println(" ./gradlew build")
}
}
tasks.register<Exec>("ftcBuild") {
group = "ftc"
description = "Deploy code and build FTC APK"
dependsOn("deployToSDK")
val sdkDir = System.getenv("HOME") + "/ftc-sdk"
workingDir(file(sdkDir))
commandLine("./gradlew", "build")
}

1547
ftc-new-project Executable file

File diff suppressed because it is too large Load Diff

33
install.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
# Install FTC project generator
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="/usr/local/bin"
echo "FTC Project Generator - Installation"
echo ""
# Check if running as root for system install
if [ -w "$INSTALL_DIR" ]; then
echo "Installing to $INSTALL_DIR (system-wide)..."
ln -sf "$SCRIPT_DIR/ftc-new-project" "$INSTALL_DIR/ftc-new-project"
echo "✓ Installed! Use 'ftc-new-project' from anywhere."
else
echo "No write access to $INSTALL_DIR"
echo ""
echo "Choose installation method:"
echo ""
echo "1. System-wide (requires sudo):"
echo " sudo $0"
echo ""
echo "2. User-only (no sudo needed):"
echo " mkdir -p ~/bin"
echo " ln -sf $SCRIPT_DIR/ftc-new-project ~/bin/ftc-new-project"
echo " echo 'export PATH=\$PATH:~/bin' >> ~/.bashrc"
echo " source ~/.bashrc"
echo ""
echo "3. Add this directory to PATH:"
echo " echo 'export PATH=\$PATH:$SCRIPT_DIR' >> ~/.bashrc"
echo " source ~/.bashrc"
exit 1
fi