Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
type='number'
[formGroup]='this.settingsForm'
_formControl='speed'
tooltip='The speed that the animation will run at. (rpm - I think)'
tooltip='The speed that the animation will run at rpm'
>Input Speed
</input-block>
</collapsible-subseciton>
Expand Down
86 changes: 61 additions & 25 deletions src/app/component/settings-panel/settings-panel.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { Component } from '@angular/core';
import { SettingsService } from 'src/app/services/settings.service';
import { LengthUnit, AngleUnit, ForceUnit, GlobalUnit } from 'src/app/model/utils';
import { AngAccUnit, AngleUnit, AngVelUnit, ForceUnit, GlobalUnit, LengthUnit } from 'src/app/model/utils';
import { FormBuilder, Validators } from '@angular/forms';
import { NewGridComponent } from '../new-grid/new-grid.component';
import { MechanismService } from '../../services/mechanism.service';
import { Link, RealLink } from '../../model/link';
import { SvgGridService } from '../../services/svg-grid.service';
import { AnimationBarComponent } from '../animation-bar/animation-bar.component';
import { ToolbarComponent } from '../toolbar/toolbar.component';
import { NumberUnitParserService } from '../../services/number-unit-parser.service';
import { Coord } from '../../model/coord';
import { MatDialog } from '@angular/material/dialog';
Expand Down Expand Up @@ -35,6 +33,8 @@ export class SettingsPanelComponent {
currentAngleUnit!: AngleUnit;
// currentTorqueUnit!: TorqueUnit;
currentGlobalUnit!: GlobalUnit;
currentAngVelUnit!: AngVelUnit;
currentAngAccUnit!: AngAccUnit;
rotateDirection!: boolean;
currentSpeedSetting!: number;
currentObjectScaleSetting!: number;
Expand All @@ -43,6 +43,8 @@ export class SettingsPanelComponent {
this.currentLengthUnit = this.settingsService.lengthUnit.value;
this.currentAngleUnit = this.settingsService.angleUnit.value;
this.currentGlobalUnit = this.settingsService.globalUnit.value;
this.currentAngVelUnit = this.settingsService.angVelUnit.value;
this.currentAngAccUnit = this.settingsService.angAccUnit.value;
this.rotateDirection = this.settingsService.isInputCW.value;
this.currentSpeedSetting = this.settingsService.inputSpeed.value;
this.currentObjectScaleSetting = SettingsService.objectScale;
Expand All @@ -65,7 +67,10 @@ export class SettingsPanelComponent {
this.currentObjectScaleSetting = val;
this.settingsForm.patchValue(
{ objectScale: this.currentObjectScaleSetting.toString() },
{ emitEvent: false }
{ emitEvent: false },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like we are resetting the input speed when the object scale is changed? Do we want to reset the input speed back to 20?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need to reset the input speed back to 20. I can make sure that when we change the grid, the inputVal stays the same value as assigned.

@KohmeiK I have a question on this part. For this objectScale, shouldn't we get rid of this emitEvent? I imagine we want to update the graph, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bunch of these emitEvent: false is true so that we don't cause a circular loop and therefore a stack overflow. Updating the value will cause the onChange to emit, which will cause the value to change and the onChange to emit and so on.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense!

);
this.settingsForm.patchValue(
{ speed: this.nup.formatValueAndUnit(this.currentSpeedSetting, this.settingsService.angVelUnit.getValue()) }
);

//Werid place to put this but
Expand All @@ -79,20 +84,51 @@ export class SettingsPanelComponent {
this.onChanges();
}

numRegex = '^-?[0-9]+(.[0-9]{0,10})?$';
settingsForm = this.fb.group(
{
speed: ['', [Validators.required]],
objectScale: ['', [Validators.required, Validators.pattern(this.numRegex)]],
rotation: ['', { updateOn: 'change' }],
lengthunit: ['', { updateOn: 'change' }],
angleunit: ['', { updateOn: 'change' }],
torqueunit: ['', { updateOn: 'change' }],
globalunit: ['', { updateOn: 'change' }],
showMinorGrid: [true, { updateOn: 'change' }],
showMajorGrid: [true, { updateOn: 'change' }],
},
{ updateOn: 'blur' }
);

onChanges(): void {
this.settingsForm.controls['rotation'].valueChanges.subscribe((val) => {
this.rotateDirection = String(val) === '0';
this.settingsService.isInputCW.next(this.rotateDirection);
this.mechanismSrv.updateMechanism();
});
this.settingsForm.controls['speed'].valueChanges.subscribe((val) => {
if (this.settingsForm.controls['speed'].invalid) {
this.settingsForm.patchValue({ speed: this.currentSpeedSetting.toString() });
} else {
this.currentSpeedSetting = Number(val);
this.settingsService.inputSpeed.next(this.currentSpeedSetting);
if (val?.includes('-')) {
this.sendNotification("Input Speed is a magnitude. Change cw or ccw from Input Direction");
}
const [success, value] = this.nup.parseAngVelString(
val!,
this.settingsService.angVelUnit.getValue()
);
if (!success) {
this.settingsForm.patchValue(
{ speed: this.nup.formatValueAndUnit(this.currentSpeedSetting, this.settingsService.angVelUnit.getValue()) },
{ emitEvent: false },
);
} else {
this.currentSpeedSetting = value;
this.settingsService.inputSpeed.next(value);
this.settingsForm.patchValue(
{speed: this.nup.formatValueAndUnit(value, this.settingsService.angVelUnit.getValue())},
{ emitEvent: false },
);
}
this.mechanismSrv.updateMechanism();
this.mechanismSrv.onMechUpdateState.next(2);
});
this.settingsForm.controls['objectScale'].valueChanges.subscribe((val) => {
if (this.settingsForm.controls['objectScale'].invalid) {
Expand All @@ -106,7 +142,19 @@ export class SettingsPanelComponent {
this.settingsForm.controls['angleunit'].valueChanges.subscribe((val) => {
this.currentAngleUnit = ParseAngleUnit(String(val));
this.settingsService.angleUnit.next(this.currentAngleUnit);
if (this.settingsService.angVelUnit.value === AngVelUnit.DPS) {
this.currentAngleUnit = AngleUnit.DEGREE;
this.currentAngVelUnit = AngVelUnit.DPS;
this.currentAngAccUnit = AngAccUnit.DPS_square;
} else {
this.currentAngleUnit = AngleUnit.RADIAN;
this.currentAngVelUnit = AngVelUnit.RPS;
this.currentAngAccUnit = AngAccUnit.RPS_square;
}

this.mechanismSrv.updateMechanism();

this.mechanismSrv.onMechUpdateState.next(2);
});
this.settingsForm.controls['globalunit'].valueChanges.subscribe((val) => {
this.currentGlobalUnit = ParseGlobalUnit(val);
Expand Down Expand Up @@ -213,26 +261,14 @@ export class SettingsPanelComponent {
}
}

numRegex = '^-?[0-9]+(.[0-9]{0,10})?$';
settingsForm = this.fb.group(
{
speed: ['', [Validators.required, Validators.pattern(this.numRegex)]],
objectScale: ['', [Validators.required, Validators.pattern(this.numRegex)]],
rotation: ['', { updateOn: 'change' }],
lengthunit: ['', { updateOn: 'change' }],
angleunit: ['', { updateOn: 'change' }],
torqueunit: ['', { updateOn: 'change' }],
globalunit: ['', { updateOn: 'change' }],
showMinorGrid: [true, { updateOn: 'change' }],
showMajorGrid: [true, { updateOn: 'change' }],
},
{ updateOn: 'blur' }
);

sendComingSoon(): void {
NewGridComponent.sendNotification('This feature is coming soon!');
}

sendNotification(message: string): void {
NewGridComponent.sendNotification(message);
}

updateObjectScale() {
this.svgGrid.updateObjectScale();
}
Expand Down
11 changes: 11 additions & 0 deletions src/app/model/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ export enum AngleUnit {
NULL = 12,
}

export enum AngVelUnit {
RPM = 15, // revolutions per minute
DPS = 16, // degrees per second
RPS = 17, // Radians per second
}

export enum AngAccUnit {
RPS_square = 18, // rad per second square (rad/s^2)
DPS_square = 19, // degrees per second square (deg/s^2)
}

export enum ForceUnit {
LBF = 20,
NEWTON = 21,
Expand Down
4 changes: 2 additions & 2 deletions src/app/services/mechanism.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export class MechanismService {
}

updateLinkageUnits(fromUnits: LengthUnit, toUnits: LengthUnit) {
//Scale the linkage based on teh units
//Scale the linkage based on the units
// For each joint, move the joint
this.joints.forEach((joint) => {
//If joint is of type Rev joint only, move the joint
Expand All @@ -179,7 +179,7 @@ export class MechanismService {
);
}
});
this.updateMechanism();
// this.updateMechanism();
// this.settingsService.lengthUnit.subscribe((val) => {
//For each jo
// let unit = this.settingsService.lengthUnit.value;
Expand Down
77 changes: 75 additions & 2 deletions src/app/services/number-unit-parser.service.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { LengthUnit, AngleUnit, ForceUnit } from '../model/utils';
import { AngleUnit, AngVelUnit, ForceUnit, LengthUnit } from '../model/utils';

@Injectable({
providedIn: 'root',
})
export class NumberUnitParserService {
constructor() {}

public formatValueAndUnit(value: number, units: LengthUnit | AngleUnit | ForceUnit): string {
public formatValueAndUnit(value: number, units: LengthUnit | AngleUnit | ForceUnit | AngVelUnit): string {
switch (units) {
case LengthUnit.CM:
return value.toFixed(2) + ' cm';
Expand All @@ -23,6 +23,12 @@ export class NumberUnitParserService {
return value.toFixed(2) + ' lbf';
case ForceUnit.NEWTON:
return value.toFixed(2) + ' N';
case AngVelUnit.RPM:
return value.toFixed(2) + ' rpm';
case AngVelUnit.RPS:
return value.toFixed(2) + ' rev/s';
case AngVelUnit.DPS:
return value.toFixed(2) + ' deg/s';
}
return 'Error in formatValueAndUnit()';
}
Expand Down Expand Up @@ -109,6 +115,36 @@ export class NumberUnitParserService {
}
}

public parseAngVelString(input: string, desiredUnits: AngVelUnit): [boolean, number] {
let [value, unit] = this.preProcessInput(input);

if (isNaN(value)) return [false, 0]; //If the value is not a number, return fail
if (unit.length == 0) return [true, value]; //No units means imply that we have the desired units

let givenUnits: AngVelUnit;

switch (unit) {
case 'rad/s':
case 'rps':
givenUnits = AngVelUnit.RPS;
break;
case 'rpm':
case 'rev/min':
givenUnits = AngVelUnit.RPM;
break;
case 'degree/second':
case 'degree/s':
case 'dps':
givenUnits = AngVelUnit.DPS;
break;
default:
return [false, value];
}
if (givenUnits == desiredUnits) return [true, value];
value = this.convertAngVel(value, givenUnits, desiredUnits);
return [true, value];
}

public parseLengthString(input: string, desiredUnits: LengthUnit): [boolean, number] {
let [value, unit] = this.preProcessInput(input);

Expand Down Expand Up @@ -231,6 +267,43 @@ export class NumberUnitParserService {
return value;
}

private convertAngVel(value: number, givenUnits: AngVelUnit, desiredUnits: AngVelUnit) {
if (givenUnits == desiredUnits) return value;
switch (givenUnits) {
case AngVelUnit.DPS:
switch (desiredUnits) {
case AngVelUnit.RPM:
return (value / 360) * 60;
case AngVelUnit.RPS:
return value * (Math.PI / 180);
}
break;
case AngVelUnit.RPM:
switch (desiredUnits) {
case AngVelUnit.DPS:
return (value * 360) / 60;
case AngVelUnit.RPS:
return value * (2 * Math.PI) / 60;
}
break;
case AngVelUnit.RPS:
switch (desiredUnits) {
case AngVelUnit.RPM:
return value * (60 / ( 2 * Math.PI));
case AngVelUnit.DPS:
return value * (180 / Math.PI);
}
break;
}
console.error(
'Error in NumberUnitParserService.convertAngVel(): No valid conversion found between ' +
AngVelUnit[givenUnits] +
' and ' +
AngVelUnit[desiredUnits]
);
return value;
}

private convertForce(value: number, givenUnits: ForceUnit, desiredUnits: ForceUnit): number {
if (givenUnits == desiredUnits) return value;
switch (givenUnits) {
Expand Down
4 changes: 3 additions & 1 deletion src/app/services/settings.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { LengthUnit, AngleUnit, GlobalUnit, ForceUnit } from '../model/utils';
import { LengthUnit, AngleUnit, GlobalUnit, ForceUnit, AngVelUnit, AngAccUnit } from '../model/utils';

@Injectable({
providedIn: 'root',
Expand All @@ -9,6 +9,8 @@ export class SettingsService {
lengthUnit = new BehaviorSubject(LengthUnit.CM);
angleUnit = new BehaviorSubject(AngleUnit.DEGREE);
forceUnit = new BehaviorSubject(ForceUnit.NEWTON);
angVelUnit = new BehaviorSubject(AngVelUnit.RPM);
angAccUnit = new BehaviorSubject(AngAccUnit.RPS_square);
// inputTorque = new BehaviorSubject(TorqueUnit.CM_N);
globalUnit = new BehaviorSubject(GlobalUnit.METRIC);
isInputCW = new BehaviorSubject(true);
Expand Down