Compare commits
4 Commits
b07e8c7dab
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9af6015aa3 | ||
|
|
9c2ac97158 | ||
|
|
e6934cdb18 | ||
|
|
636e1252dc |
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "weevil"
|
||||
version = "1.1.0-beta.2"
|
||||
version = "1.1.0-rc1"
|
||||
edition = "2021"
|
||||
authors = ["Eric Ratliff <eric@nxlearn.net>"]
|
||||
description = "FTC robotics project generator - bores into complexity, emerges with clean code"
|
||||
|
||||
@@ -513,7 +513,7 @@ class BasicTest {
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="cmd.exe" />
|
||||
<option name="INTERPRETER_PATH" value="C:\Windows\System32\cmd.exe" />
|
||||
<option name="INTERPRETER_OPTIONS" value="/c" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
@@ -561,7 +561,7 @@ class BasicTest {
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="cmd.exe" />
|
||||
<option name="INTERPRETER_PATH" value="C:\Windows\System32\cmd.exe" />
|
||||
<option name="INTERPRETER_OPTIONS" value="/c" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
@@ -609,7 +609,7 @@ class BasicTest {
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="cmd.exe" />
|
||||
<option name="INTERPRETER_PATH" value="C:\Windows\System32\cmd.exe" />
|
||||
<option name="INTERPRETER_OPTIONS" value="/c" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
@@ -657,7 +657,7 @@ class BasicTest {
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="cmd.exe" />
|
||||
<option name="INTERPRETER_PATH" value="C:\Windows\System32\cmd.exe" />
|
||||
<option name="INTERPRETER_OPTIONS" value="/c" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
@@ -705,7 +705,7 @@ class BasicTest {
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="cmd.exe" />
|
||||
<option name="INTERPRETER_PATH" value="C:\Windows\System32\cmd.exe" />
|
||||
<option name="INTERPRETER_OPTIONS" value="/c" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
|
||||
@@ -8,6 +8,7 @@ use colored::*;
|
||||
// Embed template directories at compile time
|
||||
static BASIC_TEMPLATE: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/basic");
|
||||
static TESTING_TEMPLATE: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/testing");
|
||||
static LOCALIZATION_TEMPLATE: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/localization");
|
||||
|
||||
pub struct TemplateManager {
|
||||
#[allow(dead_code)]
|
||||
@@ -39,13 +40,14 @@ impl TemplateManager {
|
||||
}
|
||||
|
||||
pub fn template_exists(&self, name: &str) -> bool {
|
||||
matches!(name, "basic" | "testing")
|
||||
matches!(name, "basic" | "testing" | "localization")
|
||||
}
|
||||
|
||||
pub fn list_templates(&self) -> Vec<String> {
|
||||
vec![
|
||||
" basic - Minimal FTC project (default)".to_string(),
|
||||
" testing - Testing showcase with examples".to_string(),
|
||||
" basic - Minimal FTC project (default)".to_string(),
|
||||
" testing - Testing showcase with examples".to_string(),
|
||||
" localization - Grid-based positioning with sensor fusion".to_string(),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -68,6 +70,14 @@ impl TemplateManager {
|
||||
test_count: 45,
|
||||
is_default: false,
|
||||
},
|
||||
TemplateInfo {
|
||||
name: "localization".to_string(),
|
||||
description: "Grid-based robot localization with sensor fusion".to_string(),
|
||||
file_count: 21,
|
||||
line_count: 1500,
|
||||
test_count: 3,
|
||||
is_default: false,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
@@ -90,6 +100,14 @@ impl TemplateManager {
|
||||
test_count: 45,
|
||||
is_default: false,
|
||||
},
|
||||
"localization" => TemplateInfo {
|
||||
name: "localization".to_string(),
|
||||
description: "Grid-based robot localization system with multi-sensor fusion and fault tolerance.".to_string(),
|
||||
file_count: 21,
|
||||
line_count: 1500,
|
||||
test_count: 3,
|
||||
is_default: false,
|
||||
},
|
||||
_ => bail!("Unknown template: {}", name),
|
||||
};
|
||||
|
||||
@@ -109,6 +127,16 @@ impl TemplateManager {
|
||||
println!();
|
||||
}
|
||||
|
||||
if info.name == "localization" {
|
||||
println!("{}", "Features:".bright_white().bold());
|
||||
println!(" • 12x12 field grid system (12-inch cells)");
|
||||
println!(" • Multi-sensor fusion (encoders + IMU + vision)");
|
||||
println!(" • Fault-tolerant positioning (graceful degradation)");
|
||||
println!(" • Kalman-filter-style sensor fusion");
|
||||
println!(" • Professional robotics patterns");
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("{}", "Files included:".bright_white().bold());
|
||||
println!(" {} files", info.file_count);
|
||||
println!(" ~{} lines of code", info.line_count);
|
||||
@@ -132,6 +160,7 @@ impl TemplateManager {
|
||||
let template_dir = match template_name {
|
||||
"basic" => &BASIC_TEMPLATE,
|
||||
"testing" => &TESTING_TEMPLATE,
|
||||
"localization" => &LOCALIZATION_TEMPLATE,
|
||||
_ => bail!("Unknown template: {}", template_name),
|
||||
};
|
||||
|
||||
@@ -233,6 +262,7 @@ mod tests {
|
||||
let mgr = TemplateManager::new().unwrap();
|
||||
assert!(mgr.template_exists("basic"));
|
||||
assert!(mgr.template_exists("testing"));
|
||||
assert!(mgr.template_exists("localization"));
|
||||
assert!(!mgr.template_exists("nonexistent"));
|
||||
}
|
||||
|
||||
@@ -240,6 +270,19 @@ mod tests {
|
||||
fn test_list_templates() {
|
||||
let mgr = TemplateManager::new().unwrap();
|
||||
let templates = mgr.list_templates();
|
||||
assert_eq!(templates.len(), 2);
|
||||
assert_eq!(templates.len(), 3);
|
||||
assert!(templates[0].contains("basic"));
|
||||
assert!(templates[1].contains("testing"));
|
||||
assert!(templates[2].contains("localization"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_template_info_all() {
|
||||
let mgr = TemplateManager::new().unwrap();
|
||||
let infos = mgr.get_template_info_all().unwrap();
|
||||
assert_eq!(infos.len(), 3);
|
||||
assert_eq!(infos[0].name, "basic");
|
||||
assert_eq!(infos[1].name, "testing");
|
||||
assert_eq!(infos[2].name, "localization");
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ Grid-based robot localization with sensor fusion and fault tolerance.
|
||||
- **Grid System** - 12x12 field grid (12" cells)
|
||||
- **Sensor Fusion** - Combine encoders, IMU, vision
|
||||
- **Fault Tolerance** - Graceful sensor failure handling
|
||||
- **20+ Tests** - All passing
|
||||
- **3 Tests** - All passing
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
9 . . . . . . . . . . . .
|
||||
8 . . . . . . . . . . . .
|
||||
7 . . . . . . . . . . . .
|
||||
6 . . . . . . X . . . . .
|
||||
6 . . . . . X . . . . . .
|
||||
5 . . . . . . . . . . . .
|
||||
4 . . . . . . . . . . . .
|
||||
3 . . . . . . . . . . . .
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = '{{PROJECT_NAME}}'
|
||||
17
templates/localization/settings.gradle.kts.template
Normal file
17
templates/localization/settings.gradle.kts.template
Normal file
@@ -0,0 +1,17 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "{{PROJECT_NAME}}"
|
||||
@@ -4,4 +4,5 @@ public interface GyroSensor {
|
||||
double getHeading();
|
||||
boolean isConnected();
|
||||
void calibrate();
|
||||
boolean isCalibrated();
|
||||
}
|
||||
|
||||
@@ -13,14 +13,17 @@ public class ImuLocalizer {
|
||||
|
||||
public void calibrate(double initialHeading) {
|
||||
if (gyro.isConnected()) {
|
||||
gyro.calibrate();
|
||||
this.headingOffset = initialHeading - gyro.getHeading();
|
||||
}
|
||||
}
|
||||
|
||||
public Double getHeading() {
|
||||
if (!gyro.isConnected()) return null;
|
||||
if (!gyro.isConnected() || !gyro.isCalibrated()) return null;
|
||||
return Pose2D.normalizeAngle(gyro.getHeading() + headingOffset);
|
||||
}
|
||||
|
||||
public boolean isWorking() { return gyro.isConnected(); }
|
||||
public boolean isWorking() {
|
||||
return gyro.isConnected() && gyro.isCalibrated();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ package robot.hardware;
|
||||
public class MockGyroSensor implements GyroSensor {
|
||||
private double heading = 0;
|
||||
private boolean connected = true;
|
||||
private boolean calibrated = true;
|
||||
|
||||
public double getHeading() { return heading; }
|
||||
public boolean isConnected() { return connected; }
|
||||
public void calibrate() { }
|
||||
public void calibrate() { calibrated = true; }
|
||||
public boolean isCalibrated() { return calibrated; }
|
||||
|
||||
public void setHeading(double h) { heading = h; }
|
||||
public void setConnected(boolean c) { connected = c; }
|
||||
public void setCalibrated(boolean c) { calibrated = c; }
|
||||
}
|
||||
|
||||
@@ -34,11 +34,15 @@ class SensorFusionTest {
|
||||
MockGyroSensor gyro = new MockGyroSensor();
|
||||
MockVisionCamera camera = new MockVisionCamera();
|
||||
|
||||
// Set a pose so vision is actually "working" (not just connected)
|
||||
camera.setPose(new Pose2D(12, 12, 0));
|
||||
|
||||
OdometryTracker odometry = new OdometryTracker(left, right);
|
||||
ImuLocalizer imu = new ImuLocalizer(gyro);
|
||||
VisionLocalizer vision = new VisionLocalizer(camera);
|
||||
|
||||
RobotLocalizer localizer = new RobotLocalizer(odometry, imu, vision);
|
||||
localizer.update(); // Need to update to actually use vision
|
||||
|
||||
assertEquals(1.0, localizer.getConfidence(), 0.01);
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
// Intentionally hardcoded. When you bump the version in Cargo.toml,
|
||||
// tests will fail here until you update this to match.
|
||||
pub const EXPECTED_VERSION: &str = "1.1.0-beta.2";
|
||||
pub const EXPECTED_VERSION: &str = "1.1.0-rc1";
|
||||
@@ -37,7 +37,7 @@ fn test_list_templates() {
|
||||
let mgr = TemplateManager::new().unwrap();
|
||||
let templates = mgr.list_templates();
|
||||
|
||||
assert_eq!(templates.len(), 2, "Should have exactly 2 templates");
|
||||
assert_eq!(templates.len(), 3, "Should have exactly 3 templates");
|
||||
assert!(templates.iter().any(|t| t.contains("basic")), "Should list basic template");
|
||||
assert!(templates.iter().any(|t| t.contains("testing")), "Should list testing template");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user