Skip to content

Commit 50b6f87

Browse files
committed
Add KeepIn and KeepOut geofence boxes
## Why is this being changed? This is being changed because of Northrop's requirement of having a KeepIn and KeepOut box for all vehicles. The KeepIn area is an area that all vehicles must stay inside of, and will be about the size of the mission field/runway. The KeepOut area is an area that all vehicles must stay outside of, and will be the location of all student/Northrop observers. ## What was changed to address this problem? In order to address the problem, two geofence buttons were created inside of the missionWindow UI tah tallows the GCS operator to dynamically create the two boxes individually, separating them by color. ## How was this change tested? This change was tested with npm test.
1 parent 3ae665c commit 50b6f87

File tree

7 files changed

+179
-94
lines changed

7 files changed

+179
-94
lines changed

src/common/struct/Vehicle.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,6 @@ export default class Vehicle {
260260
this.sendMessage({
261261
type: 'start',
262262
jobType,
263-
geofence: {
264-
topLeft: [0, 0],
265-
botRight: [0, 0],
266-
keepOut: true,
267-
},
268263
});
269264

270265
this.updateEventHandler.addHandler<VehicleStatus>('status', (value): boolean => {

src/renderer/mainWindow/map/MapContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ export default class MapContainer extends Component<ThemeProps, State> {
318318
boundingBoxes.forEach((boundingBox): void => {
319319
if (!newBoundingBoxes[boundingBox.name]) {
320320
newBoundingBoxes[boundingBox.name] = {
321-
color: boundingBox.color || 'red',
321+
color: boundingBox.color || 'black',
322322
bounds: boundingBox.bounds || (viewport.center && {
323323
top: viewport.center[0],
324324
bottom: viewport.center[0],

src/renderer/missionWindow/MissionWindow.tsx

Lines changed: 122 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,22 @@ const title: { [missionName in MissionInformation.MissionName]: string } = {
5454
uuvRescue: 'UUV Rescue',
5555
};
5656

57-
type GeofenceChecklistType = 'geofenceTop' | 'geofenceLeft' | 'geofenceRight' | 'geofenceBottom';
57+
type GeofenceChecklistType = 'geofenceKeepInTop' | 'geofenceKeepInLeft' | 'geofenceKeepInRight' | 'geofenceKeepInBottom' | 'geofenceKeepOutTop' | 'geofenceKeepOutLeft' | 'geofenceKeepOutRight' | 'geofenceKeepOutBottom';
5858

5959
const checklistCache: { [check in GeofenceChecklistType ]: number | undefined} = {
60-
geofenceTop: undefined,
61-
geofenceLeft: undefined,
62-
geofenceRight: undefined,
63-
geofenceBottom: undefined,
60+
geofenceKeepInTop: undefined,
61+
geofenceKeepInLeft: undefined,
62+
geofenceKeepInRight: undefined,
63+
geofenceKeepInBottom: undefined,
64+
geofenceKeepOutTop: undefined,
65+
geofenceKeepOutLeft: undefined,
66+
geofenceKeepOutRight: undefined,
67+
geofenceKeepOutBottom: undefined,
6468
};
6569

66-
type Locked = {
67-
geofence: boolean;
68-
};
69-
70-
const lockedCache: Locked = {
71-
geofence: true,
72-
};
70+
type Locked = { geofenceKeepIn: boolean, geofenceKeepOut: boolean };
7371

72+
const lockedCache: Locked = { geofenceKeepIn: true, geofenceKeepOut: true };
7473

7574
interface State {
7675
/**
@@ -223,50 +222,98 @@ export default class MissionWindow extends Component<ThemeProps, State> {
223222
const name = event.target.name as GeofenceChecklistType;
224223
const value = parseInt(event.target.value, 10) || 0;
225224
switch (name) {
226-
case 'geofenceTop':
225+
case 'geofenceKeepInTop':
226+
ipc.postUpdateBoundingBoxes(true, {
227+
name: 'Geofence Keep In',
228+
bounds: {
229+
top: value,
230+
bottom: checklist.geofenceKeepInBottom as number,
231+
left: checklist.geofenceKeepInLeft as number,
232+
right: checklist.geofenceKeepInRight as number,
233+
},
234+
});
235+
break;
236+
237+
case 'geofenceKeepInLeft':
238+
ipc.postUpdateBoundingBoxes(true, {
239+
name: 'Geofence Keep In',
240+
bounds: {
241+
top: checklist.geofenceKeepInTop as number,
242+
bottom: checklist.geofenceKeepInBottom as number,
243+
left: value,
244+
right: checklist.geofenceKeepInRight as number,
245+
},
246+
});
247+
break;
248+
249+
case 'geofenceKeepInRight':
250+
ipc.postUpdateBoundingBoxes(true, {
251+
name: 'Geofence Keep In',
252+
bounds: {
253+
top: checklist.geofenceKeepInTop as number,
254+
bottom: checklist.geofenceKeepInBottom as number,
255+
left: checklist.geofenceKeepInLeft as number,
256+
right: value,
257+
},
258+
});
259+
break;
260+
261+
case 'geofenceKeepInBottom':
227262
ipc.postUpdateBoundingBoxes(true, {
228-
name: 'Geofencing',
263+
name: 'Geofence Keep In',
264+
bounds: {
265+
top: checklist.geofenceKeepInTop as number,
266+
bottom: value,
267+
left: checklist.geofenceKeepInLeft as number,
268+
right: checklist.geofenceKeepInRight as number,
269+
},
270+
});
271+
break;
272+
273+
case 'geofenceKeepOutTop':
274+
ipc.postUpdateBoundingBoxes(true, {
275+
name: 'Geofence Keep Out',
229276
bounds: {
230277
top: value,
231-
bottom: checklist.geofenceBottom as number,
232-
left: checklist.geofenceLeft as number,
233-
right: checklist.geofenceRight as number,
278+
bottom: checklist.geofenceKeepOutBottom as number,
279+
left: checklist.geofenceKeepOutLeft as number,
280+
right: checklist.geofenceKeepOutRight as number,
234281
},
235282
});
236283
break;
237284

238-
case 'geofenceLeft':
285+
case 'geofenceKeepOutLeft':
239286
ipc.postUpdateBoundingBoxes(true, {
240-
name: 'Geofencing',
287+
name: 'Geofence Keep Out',
241288
bounds: {
242-
top: checklist.geofenceTop as number,
243-
bottom: checklist.geofenceBottom as number,
289+
top: checklist.geofenceKeepOutTop as number,
290+
bottom: checklist.geofenceKeepOutBottom as number,
244291
left: value,
245-
right: checklist.geofenceRight as number,
292+
right: checklist.geofenceKeepOutRight as number,
246293
},
247294
});
248295
break;
249296

250-
case 'geofenceRight':
297+
case 'geofenceKeepOutRight':
251298
ipc.postUpdateBoundingBoxes(true, {
252-
name: 'Geofencing',
299+
name: 'Geofence Keep Out',
253300
bounds: {
254-
top: checklist.geofenceTop as number,
255-
bottom: checklist.geofenceBottom as number,
256-
left: checklist.geofenceLeft as number,
301+
top: checklist.geofenceKeepOutTop as number,
302+
bottom: checklist.geofenceKeepOutBottom as number,
303+
left: checklist.geofenceKeepOutLeft as number,
257304
right: value,
258305
},
259306
});
260307
break;
261308

262-
case 'geofenceBottom':
309+
case 'geofenceKeepOutBottom':
263310
ipc.postUpdateBoundingBoxes(true, {
264-
name: 'Geofencing',
311+
name: 'Geofence Keep Out',
265312
bounds: {
266-
top: checklist.geofenceTop as number,
313+
top: checklist.geofenceKeepOutTop as number,
267314
bottom: value,
268-
left: checklist.geofenceLeft as number,
269-
right: checklist.geofenceRight as number,
315+
left: checklist.geofenceKeepOutLeft as number,
316+
right: checklist.geofenceKeepOutRight as number,
270317
},
271318
});
272319
break;
@@ -368,11 +415,18 @@ export default class MissionWindow extends Component<ThemeProps, State> {
368415

369416
boundingBoxes.forEach((boxpoint): void => {
370417
switch (boxpoint.name) {
371-
case 'Geofencing':
372-
checks.geofenceTop = boxpoint.bounds.top;
373-
checks.geofenceRight = boxpoint.bounds.right;
374-
checks.geofenceLeft = boxpoint.bounds.left;
375-
checks.geofenceBottom = boxpoint.bounds.bottom;
418+
case 'Geofence Keep In':
419+
checks.geofenceKeepInTop = boxpoint.bounds.top;
420+
checks.geofenceKeepInRight = boxpoint.bounds.right;
421+
checks.geofenceKeepInLeft = boxpoint.bounds.left;
422+
checks.geofenceKeepInBottom = boxpoint.bounds.bottom;
423+
break;
424+
425+
case 'Geofence Keep Out':
426+
checks.geofenceKeepOutTop = boxpoint.bounds.top;
427+
checks.geofenceKeepOutRight = boxpoint.bounds.right;
428+
checks.geofenceKeepOutLeft = boxpoint.bounds.left;
429+
checks.geofenceKeepOutBottom = boxpoint.bounds.bottom;
376430
break;
377431

378432
default: break;
@@ -447,8 +501,11 @@ export default class MissionWindow extends Component<ThemeProps, State> {
447501
private unlockParameterInputs(waypointType: string): void {
448502
const { locked: newLocked } = this.state;
449503

450-
if (waypointType === 'geofence') {
451-
newLocked.geofence = false;
504+
if (waypointType === 'geofenceKeepIn') {
505+
newLocked.geofenceKeepIn = false;
506+
}
507+
if (waypointType === 'geofenceKeepOut') {
508+
newLocked.geofenceKeepOut = false;
452509
}
453510

454511
this.setState({ locked: newLocked });
@@ -486,10 +543,14 @@ export default class MissionWindow extends Component<ThemeProps, State> {
486543
*/
487544

488545
const unlockStartMissionButton = information[missionName].parameters !== undefined
489-
&& checklist.geofenceTop !== undefined
490-
&& checklist.geofenceBottom !== undefined
491-
&& checklist.geofenceLeft !== undefined
492-
&& checklist.geofenceRight !== undefined;
546+
&& checklist.geofenceKeepInTop !== undefined
547+
&& checklist.geofenceKeepInBottom !== undefined
548+
&& checklist.geofenceKeepInLeft !== undefined
549+
&& checklist.geofenceKeepInRight !== undefined
550+
&& checklist.geofenceKeepOutTop !== undefined
551+
&& checklist.geofenceKeepOutBottom !== undefined
552+
&& checklist.geofenceKeepOutLeft !== undefined
553+
&& checklist.geofenceKeepOutRight !== undefined;
493554

494555
return (
495556
<div className={`missionWrapper${theme === 'dark' ? '_dark' : ''}`}>
@@ -516,16 +577,27 @@ export default class MissionWindow extends Component<ThemeProps, State> {
516577
<h1 style={{ marginTop: 0 }}>Options</h1>
517578
<MissionOptions title={title} missionNames={missionNames} options={options} />
518579
</div>
519-
<div className="geofenceContainer">
520-
<h1>Geofencing</h1>
521-
<input className="inputFields" type="number" name="geofenceScanTop" value={checklist.geofenceTop || ''} disabled={locked.geofence} onChange={this.onChange} placeholder="Top" />
580+
<div className="geofenceKeepInContainer">
581+
<h1>Geofence Keep In</h1>
582+
<input className="inputFields" type="number" name="geofenceKeepInTop" value={checklist.geofenceKeepInTop || ''} disabled={locked.geofenceKeepIn} onChange={this.onChange} placeholder="Top" />
583+
<br />
584+
<input className="inputFields" type="number" name="geofenceKeepInBottom" value={checklist.geofenceKeepInBottom || ''} disabled={locked.geofenceKeepIn} onChange={this.onChange} placeholder="Bottom" />
585+
<br />
586+
<input className="inputFields" type="number" name="geofenceKeepInLeft" value={checklist.geofenceKeepInLeft || ''} disabled={locked.geofenceKeepIn} onChange={this.onChange} placeholder="Left" />
587+
<br />
588+
<input className="inputFields" type="number" name="geofenceKeepInRight" value={checklist.geofenceKeepInRight || ''} disabled={locked.geofenceKeepIn} onChange={this.onChange} placeholder="Right" />
589+
<CreateBoundingBoxButton theme={theme} name="geofenceKeepIn" value="Geofence Keep In" color="green" />
590+
</div>
591+
<div className="geofenceKeepOutContainer">
592+
<h1>Geofence Keep Out</h1>
593+
<input className="inputFields" type="number" name="geofenceKeepOutTop" value={checklist.geofenceKeepOutTop || ''} disabled={locked.geofenceKeepOut} onChange={this.onChange} placeholder="Top" />
522594
<br />
523-
<input className="inputFields" type="number" name="geofenceBottom" value={checklist.geofenceBottom || ''} disabled={locked.geofence} onChange={this.onChange} placeholder="Bottom" />
595+
<input className="inputFields" type="number" name="geofenceKeepOutBottom" value={checklist.geofenceKeepOutBottom || ''} disabled={locked.geofenceKeepOut} onChange={this.onChange} placeholder="Bottom" />
524596
<br />
525-
<input className="inputFields" type="number" name="geofenceLeft" value={checklist.geofenceLeft || ''} disabled={locked.geofence} onChange={this.onChange} placeholder="Left" />
597+
<input className="inputFields" type="number" name="geofenceKeepOutLeft" value={checklist.geofenceKeepOutLeft || ''} disabled={locked.geofenceKeepOut} onChange={this.onChange} placeholder="Left" />
526598
<br />
527-
<input className="inputFields" type="number" name="geofenceRight" value={checklist.geofenceRight || ''} disabled={locked.geofence} onChange={this.onChange} placeholder="Right" />
528-
<CreateBoundingBoxButton theme={theme} name="geofence" value="Geofencing" />
599+
<input className="inputFields" type="number" name="geofenceKeepOutRight" value={checklist.geofenceKeepOutRight || ''} disabled={locked.geofenceKeepOut} onChange={this.onChange} placeholder="Right" />
600+
<CreateBoundingBoxButton theme={theme} name="geofenceKeepOut" value="Geofence Keep Out" color="red" />
529601
</div>
530602
<div className="buttonContainer">
531603
{status === 'ready' && <button type="button" disabled={!unlockStartMissionButton} onClick={this.postStartMissions}>Start Missions</button>}

src/renderer/missionWindow/extra/CreateBoundingBoxButton.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export interface CreateBoundingBoxButtonProps extends ThemeProps{
1313
* Name of the box itself, when it shows up on the map.
1414
*/
1515
value: string;
16+
17+
/**
18+
* Color of the box as it appears on the map.
19+
*/
20+
color: string;
1621
}
1722

1823
export default class CreateBoundingBoxButton extends PureComponent<CreateBoundingBoxButtonProps> {
@@ -23,9 +28,9 @@ export default class CreateBoundingBoxButton extends PureComponent<CreateBoundin
2328
}
2429

2530
private onClick(): void {
26-
const { name, value } = this.props;
31+
const { name, value, color } = this.props;
2732
ipc.postUnlockParameterInputs(name);
28-
ipc.postCreateBoundingBoxes({ name: value });
33+
ipc.postCreateBoundingBoxes({ name: value, color });
2934
}
3035

3136
public render(): ReactNode {

src/renderer/missionWindow/mission.css

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
height: 100%;
77
width: 100;
88
grid-template-areas:
9-
'selector selector selector mapping'
10-
'parameter parameter parameter mapping'
11-
'parameter parameter parameter mapping'
12-
'parameter parameter parameter mapping'
13-
'geofence geofence geofence options'
14-
'geofence geofence geofence options'
15-
'button button button options';
16-
grid-template-rows: 25px 1fr 1fr 0.8fr 1fr 0.3fr 25px;
9+
'selector selector selector mapping'
10+
'parameter parameter parameter mapping'
11+
'parameter parameter parameter mapping'
12+
'parameter parameter parameter mapping'
13+
'geofenceKeepIn geofenceKeepIn geofenceKeepOut options'
14+
'geofenceKeepIn geofenceKeepIn geofenceKeepOut options'
15+
'button button button options';
16+
grid-template-rows: 25px 1fr 1fr 1fr 1fr 0.3fr 25px;
1717
grid-template-columns: repeat(4, 1fr);
1818
}
1919

@@ -27,8 +27,13 @@
2727
padding-left: 20px;
2828
}
2929

30-
.geofenceContainer {
31-
grid-area: geofence;
30+
.geofenceKeepInContainer {
31+
grid-area: geofenceKeepIn;
32+
padding-left: 20px;
33+
}
34+
35+
.geofenceKeepOutContainer {
36+
grid-area: geofenceKeepOut;
3237
padding-left: 20px;
3338
}
3439

src/renderer/missionWindow/parameter/VTOLSearch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ export class VTOLSearch extends Component<VTOLSearchProps, State> {
233233
<input className="inputFields" type="number" name="quickScanLeft" value={checklist.quickScanLeft || ''} disabled={locked.quickScan} onChange={this.onChange} placeholder="Left" />
234234
<br />
235235
<input className="inputFields" type="number" name="quickScanRight" value={checklist.quickScanRight || ''} disabled={locked.quickScan} onChange={this.onChange} placeholder="Right" />
236-
<CreateBoundingBoxButton theme={theme} name="quickScan" value="Bounding Box" />
236+
<CreateBoundingBoxButton theme={theme} name="quickScan" value="Bounding Box" color="red" />
237237
</div>
238238
);
239239
}

0 commit comments

Comments
 (0)