Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
windows/flutter/generated_plugin_registrant.cc
windows/flutter/generated_plugin_registrant.h
windows/flutter/generated_plugins.cmake

# Windows
**/windows/flutter/generated_plugin_registrant.cc
**/windows/flutter/generated_plugin_registrant.h
**/windows/flutter/generated_plugins.cmake

# Linux
**/linux/flutter/generated_plugin_registrant.cc
**/linux/flutter/generated_plugin_registrant.h
**/linux/flutter/generated_plugins.cmake
110 changes: 12 additions & 98 deletions lib/pages/nav_grid_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import 'dart:math';

import 'package:file/file.dart';
import 'package:flutter/material.dart';
import 'package:function_tree/function_tree.dart';
// import 'package:function_tree/function_tree.dart';
import 'package:path/path.dart';
import 'package:pathplanner/pathfinding/nav_grid.dart';
import 'package:pathplanner/widgets/dialogs/edit_nav_grid_dialog.dart';
import 'package:pathplanner/widgets/field_image.dart';
import 'package:pathplanner/util/path_painter_util.dart';
import 'package:pathplanner/widgets/number_text_field.dart';

class NavGridPage extends StatefulWidget {
final Directory deployDirectory;
Expand Down Expand Up @@ -148,104 +148,18 @@ class _NavGridPageState extends State<NavGridPage> {
);
}

void _showEditDialog() {
TextEditingController nodeSizeController = TextEditingController();
TextEditingController fieldLengthController = TextEditingController();
TextEditingController fieldWidthController = TextEditingController();
void _handleGridChange(NavGrid newGrid) {
setState(() {
_grid = newGrid;
});
_saveNavGrid();
}

void _showEditDialog() {
showDialog(
context: this.context,
builder: (context) {
return AlertDialog(
title: const Text('Edit Grid'),
content: SizedBox(
width: 350,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: NumberTextField(
initialText: _grid.nodeSizeMeters.toStringAsFixed(2),
label: 'Node Size (M)',
arrowKeyIncrement: 0.05,
controller: nodeSizeController,
)),
],
),
const Text(
'Larger node size = more performance, but less accuracy'),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: NumberTextField(
initialText: _grid.fieldSize.width.toStringAsFixed(2),
label: 'Field Length (M)',
arrowKeyIncrement: 0.01,
controller: fieldLengthController,
)),
const SizedBox(width: 8),
Expanded(
child: NumberTextField(
initialText: _grid.fieldSize.height.toStringAsFixed(2),
label: 'Field Width (M)',
arrowKeyIncrement: 0.01,
controller: fieldWidthController,
)),
],
),
const SizedBox(height: 32),
const Text(
'Note: Changing these attributes will clear the navgrid. This cannot be undone.'),
],
),
),
actions: [
TextButton(
onPressed: () async {
String fileContent = await DefaultAssetBundle.of(this.context)
.loadString('resources/default_navgrid.json');

setState(() {
_grid = NavGrid.fromJson(jsonDecode(fileContent));
});
_saveNavGrid();

if (mounted) {
Navigator.of(this.context).pop();
}
},
child: const Text('Restore Default'),
),
TextButton(
onPressed: () {
if (nodeSizeController.text.isNotEmpty &&
fieldLengthController.text.isNotEmpty &&
fieldWidthController.text.isNotEmpty) {
num nodeSize = nodeSizeController.text.interpret();
num fieldLength = fieldLengthController.text.interpret();
num fieldWidth = fieldWidthController.text.interpret();

setState(() {
_grid = NavGrid.blankGrid(
nodeSizeMeters: nodeSize,
fieldSize:
Size(fieldLength.toDouble(), fieldWidth.toDouble()),
);
});
_saveNavGrid();
Navigator.of(context).pop();
}
},
child: const Text('Confirm'),
),
],
);
},
);
context: this.context,
builder: (context) =>
EditNavGridDialog(grid: _grid, onGridChange: _handleGridChange));
}

double _xPixelsToMeters(double pixels) {
Expand Down
17 changes: 17 additions & 0 deletions lib/util/units.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/// The smallest allowable length which isn't zero.
const num nonZeroLength = 1e-5;

/// The smallest allowable angle which isn't zero.
const num nonZeroAngle = 0.1;

/// The smallest allowable time which isn't zero.
const num nonZeroTime = 0.001;

/// Adjusts an angle to be in the range (-180, 180].
num adjustAngle(num angle) {
num rot = angle % 360;
if (rot > 180) {
rot -= 360;
}
return rot;
}
116 changes: 116 additions & 0 deletions lib/widgets/dialogs/edit_nav_grid_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:pathplanner/pathfinding/nav_grid.dart';
import 'package:pathplanner/widgets/number_text_field.dart';

class EditNavGridDialog extends StatefulWidget {
final NavGrid grid;
final ValueChanged<NavGrid> onGridChange;

const EditNavGridDialog(
{super.key, required this.grid, required this.onGridChange});

@override
State<StatefulWidget> createState() => _EditNavGridDialogState();
}

class _EditNavGridDialogState extends State<EditNavGridDialog> {
late num _nodeSize;
late num _fieldLength;
late num _fieldWidth;

@override
void initState() {
super.initState();
_nodeSize = widget.grid.nodeSizeMeters;
// These match the UI
_fieldLength = widget.grid.fieldSize.width;
_fieldWidth = widget.grid.fieldSize.height;
}

@override
Widget build(BuildContext context) {
return AlertDialog(
title: const Text('Edit Grid'),
content: SizedBox(
width: 350,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: NumberTextField(
value: _nodeSize,
label: 'Node Size (M)',
arrowKeyIncrement: 0.05,
onSubmitted: (value) => (setState(() {
_nodeSize = value;
})),
)),
],
),
const Text(
'Larger node size = more performance, but less accuracy'),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: NumberTextField(
value: _fieldLength,
label: 'Field Length (M)',
arrowKeyIncrement: 0.01,
onSubmitted: (value) => (setState(() {
_fieldLength = value;
})),
)),
const SizedBox(width: 8),
Expanded(
child: NumberTextField(
value: _fieldWidth,
label: 'Field Width (M)',
arrowKeyIncrement: 0.01,
onSubmitted: (value) => (setState(() {
_fieldWidth = value;
})),
)),
],
),
const SizedBox(height: 32),
const Text(
'Note: Changing these attributes will clear the navgrid. This cannot be undone.'),
],
),
),
actions: [
TextButton(
onPressed: () async {
String fileContent = await DefaultAssetBundle.of(this.context)
.loadString('resources/default_navgrid.json');

NavGrid grid = NavGrid.fromJson(jsonDecode(fileContent));
widget.onGridChange(grid);

if (mounted) {
Navigator.of(this.context).pop();
}
},
child: const Text('Restore Default'),
),
TextButton(
onPressed: () {
NavGrid grid = NavGrid.blankGrid(
nodeSizeMeters: _nodeSize,
fieldSize: Size(_fieldLength.toDouble(), _fieldWidth.toDouble()),
);
widget.onGridChange(grid);
Navigator.of(context).pop();
},
child: const Text('Confirm'),
),
],
);
}
}
Loading