Compare commits

...

24 Commits

Author SHA1 Message Date
280963d1eb 0.0.67 2018-01-15 23:58:31 -08:00
9fadf49b0e Support for multiple motors in "used" logic. (#238)
* handle registerion of dual / single motors

* updated puppy
2018-01-15 23:57:21 -08:00
3c2be25384 some core set adapted codes 2018-01-15 21:27:19 -08:00
e1f623a94d Added description to timers 2018-01-15 03:41:14 -08:00
cb5f9648f5 fixed sound name 2018-01-14 19:49:40 -08:00
9158cfe4f6 0.0.66 2018-01-13 08:31:38 -08:00
0b763978f2 gyro boy improvements (#236)
gyro boy improvements
2018-01-13 08:31:10 -08:00
25fded6afb 0.0.65 2018-01-13 00:02:01 -08:00
fc6fb0811f Timers (#235)
* adding timer support

* updates strings
2018-01-13 00:00:55 -08:00
49bedcbcc5 0.0.64 2018-01-12 16:12:02 -08:00
32876f4584 Merge pull request #234 from Microsoft/largemotorview
Fix large motor SVG hole
2018-01-12 13:51:00 -08:00
da9bea30b5 Update large motor view SVG so that the drop shadow is outside the hole SVG 2018-01-12 13:50:09 -08:00
d0aa68aeee 0.0.63 2018-01-12 13:33:45 -08:00
51731fbbc9 bump pxt-common-packages to 0.15.5, 2018-01-12 13:33:40 -08:00
751ea1494b motor slider fixes and fix motor output in vm 2018-01-12 13:33:25 -08:00
dfe84471e8 Merge pull request #144 from Microsoft/motorslider
Add motor slider control
2018-01-12 13:04:45 -08:00
0dd5ab9bde appliying manual speed 2018-01-10 14:08:50 -08:00
e93e659e8a nit: remove unnecessary comment 2018-01-10 13:51:35 -08:00
8357372fb5 Update to make it more like a crank 2018-01-10 13:47:39 -08:00
10cd39a4ec Merge branch 'master' into motorslider 2018-01-10 12:52:51 -08:00
aa8635c4e7 Always use the motor slider control 2018-01-10 10:00:48 -08:00
4e4f5495da Merge branch 'master' into motorslider 2018-01-10 09:56:59 -08:00
16b9a5027d Add rotate icons 2017-12-29 11:39:06 -08:00
cbe68b3199 Add motor slider control 2017-12-28 13:23:30 -08:00
32 changed files with 1579 additions and 319 deletions

View File

@ -0,0 +1,215 @@
# Gyroboy LabView
```typescript
let mSum = 0;
let mPos = 0;
let mSpd = 0;
let mD = 0;
let mDP1 = 0;
let mDP2 = 0;
let mDP3 = 0;
let Crdv = 0;
let cLo = 0;
let gAng = 0;
let ok = false;
let pwr = 0;
let Cstr = 0;
let Cdrv = 0;
let gMn = 0;
let gMx = 0;
let gSum = 0;
let gyro = 0;
let gOS = 0;
let gSpd = 0;
let tInt = 0.014;
let lpwr = 0
let rpwr = 0
let tStart = 0
let st = 0
let oldDr = 0
function RST() {
motors.largeA.reset()
motors.largeD.reset()
motors.largeA.setRegulated(false)
motors.largeD.setRegulated(false)
sensors.gyro2.reset()
sensors.gyro2.rate()
control.timer2.reset()
loops.pause(5000)
mSum = 0;
mPos = 0;
mD = 0;
mDP1 = 0;
mDP2 = 0;
mDP3 = 0;
Crdv = 0;
cLo = 0;
gAng = 0;
ok = false;
pwr = 0;
st = 0;
Cstr = 0;
Cdrv = 0;
}
function OS() {
// OSL
do {
gMn = 1000;
gMx = -100;
gSum = 0;
// gChk
for (let i = 0; i < 200; i++) {
gyro = sensors.gyro2.rate()
gSum = gyro;
gMx = Math.max(gMx, gyro)
gMn = Math.min(gMn, gyro)
loops.pause(4);
}
} while (gMx - gMn > 2);
gOS = gSum / 200;
}
function GT() {
if (cLo == 0) {
tInt = 0.014;
control.timer1.reset();
} else {
tInt = control.timer1.seconds() / cLo;
}
cLo++;
}
function GG() {
gyro = sensors.gyro2.rate();
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
gSpd = gyro - gOS;
gAng = gAng + tInt * gSpd;
}
function GM() {
let temp = mSum
mSum = motors.largeD.angle() + motors.largeA.angle();
mD = mSum - temp;
mPos = mPos + mD;
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
mDP3 = mDP2;
mDP2 = mDP1;
mDP1 = mD;
}
function EQ() {
mPos = mPos - Cdrv * tInt;
pwr = (0.8 * gSpd + 15 * gAng) + (0.08 * mSpd + 0.12 * mPos) - 0.01 * Cdrv
if (pwr > 100) pwr = 100
else if (pwr < -100) pwr = -100
}
function cntrl() {
mPos = mPos - tInt * Cdrv
lpwr = (pwr + Cstr * 0.1)
rpwr = (pwr - Cstr * 0.1)
}
function CHK() {
if (Math.abs(pwr) < 100)
control.timer2.reset();
if (control.timer2.seconds() > 2) {
ok = true;
}
}
// M
loops.forever(function () {
RST();
brick.showImage(images.eyesSleeping)
OS()
gAng = -0.25;
music.playSoundEffect(sounds.movementsSpeedUp)
brick.showImage(images.eyesAwake)
st = 1;
// BALANCE
while (!ok) {
GT();
let t1 = control.timer1.millis()
GG();
GM();
EQ();
cntrl();
motors.largeA.setSpeed(lpwr)
motors.largeD.setSpeed(rpwr)
CHK()
let t2 = control.timer1.millis();
let p = 5 - (t2 - t1);
loops.pause(Math.max(1, p))
}
motors.stopAllMotors()
st = 0;
brick.setLight(BrickLight.RedPulse);
brick.showImage(images.eyesKnockedOut)
music.playSoundEffect(sounds.movementsSpeedDown)
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
brick.setLight(BrickLight.Off);
})
// BHV
loops.forever(function () {
switch (st) {
case 0:
Cdrv = 0;
Cstr = 0;
break;
case 1:
Cdrv = 40;
loops.pause(4000);
Cdrv = 0;
music.playTone(1000, 100);
st = 2;
break;
case 2:
switch (sensors.color1.color()) {
case ColorSensorColor.Red:
music.playTone(2000, 100);
Cdrv = 0;
Cstr = 0;
break;
case ColorSensorColor.Green:
music.playTone(2000, 100);
Cdrv = 150;
Cstr = 0;
break;
case ColorSensorColor.Blue:
music.playTone(2000, 100);
Cstr = 70;
break;
case ColorSensorColor.Yellow:
music.playTone(2000, 100);
Cstr = -70;
break;
case ColorSensorColor.White:
music.playTone(2000, 100);
Cdrv = -75;
break;
}
if (sensors.ultrasonic4.distance() < 25) {
Cstr = 0;
oldDr = Cdrv;
Cdrv = -10;
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
if (Math.randomRange(-1, 1) >= 1)
Cstr = 70;
else
Cstr = -70;
loops.pause(4000);
music.playTone(2000, 100)
Cstr = 0;
Cdrv = oldDr;
}
break;
}
loops.pause(80);
})
```

View File

@ -0,0 +1,390 @@
# Puppy
```typescript
let P_T = 0;
let ISS = 0;
let F_T = 0;
let P_C = 0;
let F_C = 0;
let DB_S = 0;
let NS = false;
let IBP = 0;
let IAP = 0;
let C = false;
let TC = false;
let OTC = false;
let COL = 0;
let OCOL = 0;
let _C = false;
let GTO = 0;
function DN() {
motors.largeAD.setBrake(true);
motors.largeAD.tank(50, 50, 1, MoveUnit.Seconds);
loops.pause(100);
motors.largeA.clearCounts()
motors.largeD.clearCounts()
}
function MNRH() {
motors.mediumC.setBrake(true)
brick.showImage(images.legoEv3icon)
brick.setLight(BrickLight.OrangePulse)
while (!brick.buttonEnter.wasPressed()) {
if (brick.buttonUp.wasPressed()) {
motors.mediumC.setSpeed(-100);
} else if (brick.buttonDown.wasPressed()) {
motors.mediumC.setSpeed(100);
} else {
motors.mediumC.stop();
}
}
motors.mediumC.stop();
motors.mediumC.clearCounts();
brick.setLight(BrickLight.Green);
}
function IS(t: number) {
ISS = t;
switch (t) {
case 0:
brick.showImage(images.eyesNeutral);
break;
case 1:
brick.showImage(images.eyesSleeping);
break;
case 2:
brick.showImage(images.eyesTear);
// draw rect...
break;
case 3:
brick.showImage(images.eyesHurt);
break;
case 4:
brick.showImage(images.eyesAngry);
break;
case 5:
brick.showImage(images.eyesTiredMiddle);
break;
case 6:
brick.showImage(images.eyesTiredRight);
break;
case 7:
brick.showImage(images.eyesTiredLeft);
break;
case 8:
brick.showImage(images.eyesLove);
break;
}
}
function UP() {
if (motors.largeA.angle() > -50) {
control.runInBackground(function () {
motors.largeD.clearCounts()
motors.largeD.setSpeed(-35);
pauseUntil(() => motors.largeD.angle() < -25);
motors.largeD.stop();
motors.largeD.setRegulated(false)
motors.largeD.setSpeed(-15)
pauseUntil(() => motors.largeD.angle() < -65);
motors.largeD.stop();
})
motors.largeA.clearCounts()
motors.largeA.setSpeed(-35);
pauseUntil(() => motors.largeA.angle() < -25);
motors.largeA.stop();
motors.largeA.setRegulated(false)
motors.largeA.setSpeed(-15)
pauseUntil(() => motors.largeA.angle() < -65);
motors.largeA.stop();
loops.pause(500);
}
}
function RST() {
P_T = Math.randomRange(3, 6);
F_T = Math.randomRange(2, 4);
P_C = 1;
F_C = 1;
control.timer1.reset();
control.timer2.reset();
control.timer3.reset();
CS(0);
}
function CS(db: number) {
if (DB_S != db) {
DB_S = db;
NS = true;
}
}
function MON() {
if (control.timer2.seconds() > 10) {
control.timer2.reset();
P_C--;
if (P_C < 0) {
P_C = 0;
}
}
if (control.timer1.seconds() > 20) {
control.timer1.reset()
F_C--;
if (F_C < 0) {
F_C = 0;
}
}
if (control.timer3.seconds() > 30) {
control.timer3.reset();
CS(1);
}
}
function UIS() {
if (control.timer5.seconds() > IBP) {
control.timer5.reset();
if (ISS == 1) {
ISS = 6;
IBP = Math.randomRange(1, 5);
} else {
ISS = 1;
IBP = 0.25;
}
IS(ISS);
}
if (control.timer6.seconds() > IAP) {
if (ISS != 1) {
control.timer6.reset();
IAP = Math.randomRange(1, 10)
if (ISS != 7) {
ISS = 7
} else {
ISS = 6;
}
IS(ISS);
}
}
}
function UPDB() {
if ((P_T == P_C) && (F_T == F_C)) {
CS(6);
}
if ((P_T > P_C) && (F_T < F_C)) {
CS(3);
}
if ((P_T < P_C) && (F_T > F_C)) {
CS(5);
}
if ((P_C == 0) && (F_C > 0)) {
CS(2)
}
if (F_C == 0) {
CS(4)
}
}
function PTC() {
C = false;
OTC = TC;
TC = sensors.touch1.isPressed()
if (TC != OTC && TC) {
P_C++;
control.timer3.reset();
if (DB_S != 4) {
IS(2);
music.playSoundEffect(sounds.animalsDogSniff);
C = true;
}
}
return C;
}
function FDC() {
OCOL = COL;
COL = sensors.color4.color();
_C = false;
if ((COL != 0) && (OCOL != COL)) {
F_C++;
_C = true;
control.timer3.reset();
IS(2);
music.playSoundEffect(sounds.expressionsCrunching)
}
return _C;
}
function IDL() {
if (NS) {
NS = false;
UP();
}
UIS();
UPDB();
PTC();
FDC();
}
function MHT(Pos: number) {
let _R = Pos - motors.mediumC.angle();
if (_R >= 0) {
motors.mediumC.setSpeed(100, _R, MoveUnit.Degrees);
} else {
motors.mediumC.setSpeed(-100, Math.abs(_R), MoveUnit.Degrees);
}
}
function SLP() {
if (NS) {
NS = false;
IS(5)
DN()
MHT(3000)
IS(1)
music.playSoundEffect(sounds.expressionsSnoring)
}
if (sensors.touch1.isPressed() || brick.buttonEnter.isPressed()) {
music.stopAllSounds();
control.timer3.reset();
CS(7);
}
}
function PLF() {
if (NS) {
NS = false
IS(0)
UP()
music.playSoundEffect(sounds.animalsDogBark2)
control.timer4.reset()
GTO = Math.randomRange(4, 8);
}
if(PTC()) {
CS(0);
}
if (control.timer4.seconds() > GTO) {
music.playSoundEffect(sounds.animalsDogBark2)
control.timer4.reset();
GTO = Math.randomRange(4, 8);
}
}
function NGR() {
NS = false
IS(4)
music.playSoundEffect(sounds.animalsDogGrowl);
UP();
loops.pause(1500);
music.stopAllSounds()
music.playSoundEffect(sounds.animalsDogBark1)
P_C--;
CS(0);
}
function HNG() {
if (NS) {
NS = false;
IS(3)
DN();
music.playSoundEffect(sounds.animalsDogWhine);
}
if(FDC()) {
CS(0)
}
if (PTC()) {
CS(3);
}
}
function PPP() {
NS = false;
IS(2);
UP();
loops.pause(100)
motors.largeA.setSpeed(-30, 70, MoveUnit.Degrees);
loops.pause(800);
music.playSoundEffect(sounds.mechanicalHorn1);
loops.pause(1000);
for(let i = 0; i < 3; ++i) {
motors.largeA.setSpeed(-30, 20, MoveUnit.Degrees);
motors.largeA.setSpeed(30, 20, MoveUnit.Degrees);
}
motors.largeA.setSpeed(30, 70, MoveUnit.Degrees);
F_C = 1;
CS(0);
}
function HPY() {
IS(8)
MHT(0);
motors.largeAD.setSpeed(10, 0.8, MoveUnit.Seconds);
for(let i = 0; i < 3; ++i) {
music.playSoundEffect(sounds.animalsDogBark1);
motors.largeAD.setSpeed(-100, 0.2, MoveUnit.Seconds);
loops.pause(300)
motors.largeAD.setSpeed(10, 0.3, MoveUnit.Seconds)
}
loops.pause(500);
music.stopAllSounds();
DN();
RST();
}
function STL() {
UP();
motors.largeAD.setSpeed(-20, 60, MoveUnit.Degrees);
music.playSoundEffect(sounds.animalsDogWhine);
motors.largeAD.setSpeed(20, 60, MoveUnit.Degrees);
}
function WKU() {
let stateC = false;
IS(5);
music.playSoundEffect(sounds.animalsDogWhine)
MHT(0)
DN()
STL()
loops.pause(1000);
UP()
CS(0;)
}
DN();
MNRH();
// compare button state???
IS(1);
UP();
RST();
loops.forever(function () {
MON();
switch (DB_S) {
case 0:
IDL();
break;
case 1:
SLP();
break;
case 2:
PLF();
break;
case 3:
NGR();
break;
case 4:
HNG();
break;
case 5:
PPP();
break;
case 6:
HPY();
break;
case 7:
WKU();
break;
}
})
```

View File

@ -0,0 +1,51 @@
# Robot Arm
```typescript
function INI() {
motors.largeB.setBrake(true)
motors.largeC.setBrake(true)
motors.mediumA.setBrake(true)
motors.largeB.setSpeed(-50)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
motors.largeC.setSpeed(50)
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
}
INI()
let down = false;
loops.forever(function () {
brick.showImage(images.informationQuestionMark)
brick.setLight(BrickLight.OrangePulse);
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
brick.setLight(BrickLight.Off)
music.playSoundEffect(sounds.mechanicalAirRelease)
brick.showImage(images.informationAccept)
if (down) {
brick.showImage(images.informationForward)
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
} else {
brick.showImage(images.informationBackward)
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
if (down) {
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
} else {
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop()
})
```

View File

@ -0,0 +1,51 @@
# Crane LabView
```blocks
function INI() {
motors.largeB.setBrake(true)
motors.largeC.setBrake(true)
motors.mediumA.setBrake(true)
motors.largeB.setSpeed(-50)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
motors.largeC.setSpeed(50)
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
}
INI()
let down = false;
loops.forever(function () {
brick.showImage(images.informationQuestionMark)
brick.setLight(BrickLight.OrangePulse);
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
brick.setLight(BrickLight.Off)
music.playSoundEffect(sounds.mechanicalAirRelease)
brick.showImage(images.informationAccept)
if (down) {
brick.showImage(images.informationForward)
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
} else {
brick.showImage(images.informationBackward)
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
if (down) {
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
} else {
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop()
})
```

View File

@ -0,0 +1,215 @@
# Gyro Boy LabView
```blocks
let mSum = 0;
let mPos = 0;
let mSpd = 0;
let mD = 0;
let mDP1 = 0;
let mDP2 = 0;
let mDP3 = 0;
let Crdv = 0;
let cLo = 0;
let gAng = 0;
let ok = false;
let pwr = 0;
let Cstr = 0;
let Cdrv = 0;
let gMn = 0;
let gMx = 0;
let gSum = 0;
let gyro = 0;
let gOS = 0;
let gSpd = 0;
let tInt = 0.014;
let lpwr = 0
let rpwr = 0
let tStart = 0
let st = 0
let oldDr = 0
function RST() {
motors.largeA.reset()
motors.largeD.reset()
motors.largeA.setRegulated(false)
motors.largeD.setRegulated(false)
sensors.gyro2.reset()
sensors.gyro2.rate()
control.timer2.reset()
loops.pause(5000)
mSum = 0;
mPos = 0;
mD = 0;
mDP1 = 0;
mDP2 = 0;
mDP3 = 0;
Crdv = 0;
cLo = 0;
gAng = 0;
ok = false;
pwr = 0;
st = 0;
Cstr = 0;
Cdrv = 0;
}
function OS() {
// OSL
do {
gMn = 1000;
gMx = -100;
gSum = 0;
// gChk
for (let i = 0; i < 200; i++) {
gyro = sensors.gyro2.rate()
gSum = gyro;
gMx = Math.max(gMx, gyro)
gMn = Math.min(gMn, gyro)
loops.pause(4);
}
} while (gMx - gMn > 2);
gOS = gSum / 200;
}
function GT() {
if (cLo == 0) {
tInt = 0.014;
control.timer1.reset();
} else {
tInt = control.timer1.seconds() / cLo;
}
cLo++;
}
function GG() {
gyro = sensors.gyro2.rate();
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
gSpd = gyro - gOS;
gAng = gAng + tInt * gSpd;
}
function GM() {
let temp = mSum
mSum = motors.largeD.angle() + motors.largeA.angle();
mD = mSum - temp;
mPos = mPos + mD;
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
mDP3 = mDP2;
mDP2 = mDP1;
mDP1 = mD;
}
function EQ() {
mPos = mPos - Cdrv * tInt;
pwr = (0.8 * gSpd + 15 * gAng) + (0.095 * mSpd + 0.13 * mPos) - 0.01 * Cdrv
if (pwr > 100) pwr = 100
else if (pwr < -100) pwr = -100
}
function cntrl() {
mPos = mPos - tInt * Cdrv
lpwr = (pwr + Cstr * 0.1)
rpwr = (pwr - Cstr * 0.1)
}
function CHK() {
if (Math.abs(pwr) < 100)
control.timer2.reset();
if (control.timer2.seconds() > 2) {
ok = true;
}
}
// M
loops.forever(function () {
RST();
brick.showImage(images.eyesSleeping)
OS()
gAng = -0.25;
music.playSoundEffect(sounds.movementsSpeedUp)
brick.showImage(images.eyesAwake)
st = 1;
// BALANCE
while (!ok) {
GT();
let t1 = control.timer1.millis()
GG();
GM();
EQ();
cntrl();
motors.largeA.setSpeed(lpwr)
motors.largeD.setSpeed(rpwr)
CHK()
let t2 = control.timer1.millis();
let p = 5 - (t2 - t1);
loops.pause(Math.max(1, p))
}
motors.stopAllMotors()
st = 0;
brick.setLight(BrickLight.RedPulse);
brick.showImage(images.eyesKnockedOut)
music.playSoundEffect(sounds.movementsSpeedDown)
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
brick.setLight(BrickLight.Off);
})
// BHV
loops.forever(function () {
switch (st) {
case 0:
Cdrv = 0;
Cstr = 0;
break;
case 1:
Cdrv = 40;
loops.pause(4000);
Cdrv = 0;
music.playTone(1000, 100);
st = 2;
break;
case 2:
switch (sensors.color1.color()) {
case ColorSensorColor.Red:
music.playTone(2000, 100);
Cdrv = 0;
Cstr = 0;
break;
case ColorSensorColor.Green:
music.playTone(2000, 100);
Cdrv = 150;
Cstr = 0;
break;
case ColorSensorColor.Blue:
music.playTone(2000, 100);
Cstr = 70;
break;
case ColorSensorColor.Yellow:
music.playTone(2000, 100);
Cstr = -70;
break;
case ColorSensorColor.White:
music.playTone(2000, 100);
Cdrv = -75;
break;
}
if (sensors.ultrasonic4.distance() < 25) {
Cstr = 0;
oldDr = Cdrv;
Cdrv = -10;
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
if (Math.randomRange(-1, 1) >= 1)
Cstr = 70;
else
Cstr = -70;
loops.pause(4000);
music.playTone(2000, 100)
Cstr = 0;
Cdrv = oldDr;
}
break;
}
loops.pause(80);
})
```

View File

@ -52,6 +52,12 @@
"console.logValue|param|value": "to write",
"console.sendToScreen": "Sends the log messages to the brick screen and uses the brick up and down buttons to scroll.",
"control": "Program controls and events.",
"control.Timer": "A timer",
"control.Timer.millis": "Gets the elapsed time in millis since the last reset",
"control.Timer.pauseUntil": "Pauses until the timer reaches the given amount of milliseconds",
"control.Timer.pauseUntil|param|ms": "how long to pause for, eg: 5, 100, 200, 500, 1000, 2000",
"control.Timer.reset": "Resets the timer",
"control.Timer.seconds": "Gets the elapsed time in seconds since the last reset",
"control.allocateNotifyEvent": "Allocates the next user notification event",
"control.deviceFirmwareVersion": "Determine the version of system software currently running.",
"control.dmesg": "Write data to DMESG debugging buffer.",

View File

@ -47,7 +47,19 @@
"console.log|block": "console|log %text",
"console.sendToScreen|block": "send console to screen",
"console|block": "console",
"control.Timer.millis|block": "%timer|millis",
"control.Timer.pauseUntil|block": "%timer|pause until (ms) %ms",
"control.Timer.reset|block": "%timer|reset",
"control.Timer.seconds|block": "%timer|seconds",
"control.raiseEvent|block": "raise event|from %src|with value %value",
"control.timer1|block": "timer 1",
"control.timer2|block": "timer 2",
"control.timer3|block": "timer 3",
"control.timer4|block": "timer 4",
"control.timer5|block": "timer 5",
"control.timer6|block": "timer 6",
"control.timer7|block": "timer 7",
"control.timer8|block": "timer 8",
"control|block": "control",
"motors.Motor.angle|block": "%motor|angle",
"motors.Motor.clearCounts|block": "%motor|clear counts",

View File

@ -58,7 +58,7 @@ namespace console {
namespace console.screen {
const maxLines = 100;
const screenLines = 8;
const screenLines = 10;
let lines: string[];
let scrollPosition = 0;
@ -66,8 +66,8 @@ namespace console.screen {
if (!lines) {
lines = [];
console.addListener(log);
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(-1))
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(1))
brick.buttonUp.onEvent(ButtonEvent.Click, () => scroll(-3))
brick.buttonDown.onEvent(ButtonEvent.Click, () => scroll(3))
}
}

View File

@ -312,6 +312,7 @@ namespace sensors.internal {
reset() {
if (this.isActive()) uartReset(this._port);
this.realmode = 0;
}
}

View File

@ -303,7 +303,7 @@ namespace motors {
}
private __setSpeed(speed: number) {
const b = mkCmd(this._port, this._regulated ? DAL.opOutputPower : DAL.opOutputSpeed, 1)
const b = mkCmd(this._port, this._regulated ? DAL.opOutputSpeed : DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, speed)
writePWM(b)
if (speed) {

View File

@ -11,6 +11,7 @@
"mmap.cpp",
"control.cpp",
"console.ts",
"timer.ts",
"serialnumber.cpp",
"buttons.ts",
"png.cpp",

64
libs/core/timer.ts Normal file
View File

@ -0,0 +1,64 @@
namespace control {
/**
* A timer
*/
//% fixedInstances
export class Timer {
start: number;
constructor() {
this.start = control.millis();
}
/**
* Gets the elapsed time in millis since the last reset
*/
//% blockId=timerMillis block="%timer|millis"
millis(): number {
return control.millis() - this.start;
}
/**
* Gets the elapsed time in seconds since the last reset
*/
//% blockId=timerSeconds block="%timer|seconds"
seconds(): number {
return this.millis() / 1000;
}
/**
* Resets the timer
*/
//% blockId=timerRest block="%timer|reset"
reset() {
this.start = control.millis();
}
/**
* Pauses until the timer reaches the given amount of milliseconds
* @param ms how long to pause for, eg: 5, 100, 200, 500, 1000, 2000
*/
//% blockId=timerPauseUntil block="%timer|pause until (ms) %ms"
pauseUntil(ms: number) {
const remaining = this.millis() - ms;
loops.pause(Math.max(0, remaining));
}
}
//% whenUsed fixedInstance block="timer 1"
export const timer1 = new Timer();
//% whenUsed fixedInstance block="timer 2"
export const timer2 = new Timer();
//% whenUsed fixedInstance block="timer 3"
export const timer3 = new Timer();
//% whenUsed fixedInstance block="timer 4"
export const timer4 = new Timer();
//% whenUsed fixedInstance block="timer 5"
export const timer5 = new Timer();
//% whenUsed fixedInstance block="timer 6"
export const timer6 = new Timer();
//% whenUsed fixedInstance block="timer 7"
export const timer7 = new Timer();
//% whenUsed fixedInstance block="timer 8"
export const timer8 = new Timer();
}

View File

@ -3,6 +3,9 @@
"datalog.addValue": "Adds a cell to the row of data",
"datalog.addValue|param|name": "name of the cell, eg: \"x\"",
"datalog.addValue|param|value": "value of the cell, eg: 0",
"datalog.flush": "Commits any buffered row to disk",
"datalog.setEnabled": "Turns on or off datalogging",
"datalog.setFile": "Starts a new data logger for the given file",
"datalog.setFile|param|filename": "the filename, eg: \"datalog.csv\"",
"datalog.setStorage": "* @param storage custom storage solution"
}

View File

@ -1,6 +1,7 @@
{
"datalog.addRow|block": "datalog add row",
"datalog.addValue|block": "datalog add %name|=%value",
"datalog.setEnabled|block": "datalog %enabled",
"datalog|block": "datalog",
"{id:category}Datalog": "Datalog"
}

View File

@ -3,13 +3,16 @@ namespace datalog {
let _headers: string[] = undefined;
let _headersLength: number;
let _values: number[];
let _buffer: string = "";
let _start: number;
let _filename = "data.csv";
let _filename = "datalog.csv";
let _storage: storage.Storage = storage.temporary;
let _enabled = true;
function clear() {
_headers = undefined;
_values = undefined;
_buffer = "";
}
function init() {
@ -31,7 +34,10 @@ namespace datalog {
_headersLength = _storage.size(_filename);
}
// commit row data
_storage.appendCSV(_filename, _values);
_buffer += storage.toCSV(_values, _storage.csvSeparator);
// buffered writes
if (_buffer.length > 1024)
flush();
}
// clear values
@ -44,6 +50,8 @@ namespace datalog {
//% weight=100
//% blockId=datalogAddRow block="datalog add row"
export function addRow(): void {
if (!_enabled) return;
commit();
init();
const s = (control.millis() - _start) / 1000;
@ -65,16 +73,16 @@ namespace datalog {
i = _headers.length - 1;
}
_values[i] = value;
if (i > 0) // 0 is time
console.logValue(name, value)
}
/**
* Starts a new data logger for the given file
* @param filename the filename, eg: "datalog.csv"
*/
//%
export function setFile(fn: string) {
_filename = fn;
export function setFile(filename: string) {
flush();
_filename = filename;
clear();
}
@ -84,7 +92,31 @@ namespace datalog {
*/
//%
export function setStorage(storage: storage.Storage) {
flush();
_storage = storage;
clear();
}
/**
* Commits any buffered row to disk
*/
//%
export function flush() {
if (_buffer) {
const b = _buffer;
_buffer = "";
_storage.append(_filename, b);
}
}
/**
* Turns on or off datalogging
* @param enabled
*/
//% blockId=datalogEnabled block="datalog %enabled"
//% enabled.fieldEditor=fieldonoff
export function setEnabled(enabled: boolean) {
flush();
_enabled = enabled;
}
}

View File

@ -1,5 +1,7 @@
{
"sensors.GyroSensor.angle": "Get the current angle from the gyroscope.",
"sensors.GyroSensor.drift": "Gets the computed rate drift",
"sensors.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
"sensors.GyroSensor.reset": "Forces a calibration of the gyro. Must be called when the sensor is completely still."
"sensors.GyroSensor.reset": "Forces a calibration of the gyro. Must be called when the sensor is completely still.",
"sensors.GyroSensor.setDriftCorrection": "Enables or disable drift correction"
}

View File

@ -8,16 +8,27 @@ namespace sensors {
//% fixedInstances
export class GyroSensor extends internal.UartSensor {
private calibrating: boolean;
private _drift: number;
private _drifting: boolean;
constructor(port: number) {
super(port)
this.calibrating = false;
this._drift = 0;
this._drifting = true;
this.setMode(GyroSensorMode.Rate);
}
_deviceType() {
return DAL.DEVICE_TYPE_GYRO
}
_query(): number {
return this.getNumber(NumberFormat.Int16LE, 0);
}
setMode(m: GyroSensorMode) {
if (m == GyroSensorMode.Rate && this.mode != m)
this._drift = 0;
this._setMode(m)
}
@ -37,8 +48,8 @@ namespace sensors {
if (this.calibrating)
pauseUntil(() => !this.calibrating, 2000);
this.setMode(GyroSensorMode.Angle)
return this.getNumber(NumberFormat.Int16LE, 0)
this.setMode(GyroSensorMode.Angle);
return this._query();
}
/**
@ -57,8 +68,14 @@ namespace sensors {
if (this.calibrating)
pauseUntil(() => !this.calibrating, 2000);
this.setMode(GyroSensorMode.Rate)
return this.getNumber(NumberFormat.Int16LE, 0)
this.setMode(GyroSensorMode.Rate);
let curr = this._query();
if (Math.abs(curr) < 20) {
const p = 0.0005;
this._drift = (1 - p) * this._drift + p * curr;
curr -= this._drift;
}
return curr;
}
/**
@ -76,23 +93,45 @@ namespace sensors {
if (this.calibrating) return; // already in calibration mode
this.calibrating = true;
// may be triggered by a button click, give time to settle
loops.pause(500);
// may be triggered by a button click,
// give time for robot to settle
loops.pause(700);
// send a reset command
super.reset();
// we need to switch mode twice to perform a calibration
if (this.mode == GyroSensorMode.Rate)
this.setMode(GyroSensorMode.Angle);
else
this.setMode(GyroSensorMode.Rate);
// switch back and wait
if (this.mode == GyroSensorMode.Rate)
this.setMode(GyroSensorMode.Angle);
else
this.setMode(GyroSensorMode.Rate);
// give it more time to settle
loops.pause(500);
this.calibrating = false;
// switch back to the desired mode
this.setMode(this.mode);
// wait till sensor is live
pauseUntil(() => this.isActive());
// give it a bit of time to init
loops.pause(1000)
// compute drift
this._drift = 0;
if (this.mode == GyroSensorMode.Rate) {
for (let i = 0; i < 200; ++i) {
this._drift += this._query();
loops.pause(4);
}
this._drift /= 200;
}
// and we're done
this.calibrating = false;
}
/**
* Gets the computed rate drift
*/
//%
drift(): number {
return this._drift;
}
/**
* Enables or disable drift correction
* @param enabled
*/
//%
setDriftCorrection(enabled: boolean) {
this._drifting = enabled;
}
}

View File

@ -121,7 +121,7 @@
"sounds.mechanicalMotorStart|block": "mechanical motor start",
"sounds.mechanicalMotorStop|block": "mechanical motor stop",
"sounds.mechanicalRatchet|block": "mechanical ratchet",
"sounds.mechanicalSonar|block": "\"mechanical sonar\"",
"sounds.mechanicalSonar|block": "mechanical sonar",
"sounds.mechanicalTickTack|block": "mechanical tick tack",
"sounds.mechanicalWalk|block": "mechanical walk",
"sounds.movementsArm1|block": "movements arm1",

View File

@ -175,7 +175,7 @@ namespace sounds {
export const mechanicalMotorStop = music.fromWAV(hex``);
//% fixedInstance jres block="mechanical ratchet"
export const mechanicalRatchet = music.fromWAV(hex``);
//% fixedInstance jres block='"mechanical sonar"'
//% fixedInstance jres block="mechanical sonar"
export const mechanicalSonar = music.fromWAV(hex``);
//% fixedInstance jres block="mechanical tick tack"
export const mechanicalTickTack = music.fromWAV(hex``);

View File

@ -7,7 +7,7 @@ namespace storage {
//% fixedInstances
export class Storage {
csvSeparator: string;
constructor() {
constructor() {
this.csvSeparator = ",";
}
@ -80,18 +80,13 @@ namespace storage {
}
/**
* Append a row of CSV data
* @param filename the file name to append data, eg: "data.csv"
* @param data the data to append
*/
* Append a row of CSV data
* @param filename the file name to append data, eg: "data.csv"
* @param data the data to append
*/
//% blockId=storageAppendCSV block="storage %source|%filename|append CSV %data"
appendCSV(filename: string, data: number[]) {
let s = ""
for (const d of data) {
if (s) s += this.csvSeparator;
s = s + d;
}
s += "\r\n"
let s = toCSV(data, this.csvSeparator);
this.append(filename, s)
}
@ -167,6 +162,16 @@ namespace storage {
}
}
export function toCSV(data: number[], sep: string) {
let s = ""
for (const d of data) {
if (s) s += sep;
s = s + d;
}
s += "\r\n"
return s;
}
class TemporaryStorage extends Storage {
constructor() {
super();

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "0.0.59",
"version": "0.0.64",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "0.0.62",
"version": "0.0.67",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true,
"keywords": [
@ -44,7 +44,7 @@
"webfonts-generator": "^0.4.0"
},
"dependencies": {
"pxt-common-packages": "0.15.4",
"pxt-common-packages": "0.15.6",
"pxt-core": "3.0.11"
},
"scripts": {

View File

@ -97,28 +97,21 @@ namespace pxsim {
return this.brickNode;
}
motorUsed(port: number, large: boolean) {
motorUsed(ports: number, large: boolean): boolean {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
const p = 1 << i;
if (port & p) {
const motorPort = this.motorMap[p];
if (!this.outputNodes[motorPort])
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
}
}
}
hasMotor(port: number) {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
const p = 1 << i;
if (port & p) {
if (ports & p) {
const motorPort = this.motorMap[p];
const outputNode = this.outputNodes[motorPort];
if (outputNode)
return true;
if (!outputNode) {
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
continue;
}
if (outputNode && outputNode.isLarge() != large)
return false;
}
}
return false;
return true;
}
getMotor(port: number, large?: boolean): MotorNode[] {

View File

@ -3,15 +3,23 @@
import lf = pxsim.localization.lf;
namespace pxsim.motors {
export function __motorUsed(port: number, large: boolean) {
//console.log("MOTOR INIT " + port);
if (!ev3board().hasMotor(port)) {
ev3board().motorUsed(port, large);
runtime.queueDisplayUpdate();
} else {
U.userError(`${lf("Multiple motors are connected to Port")} ${String.fromCharCode('A'.charCodeAt(0) + ev3board().motorMap[port])}`);
function portsToString(out: number): string {
let r = "";
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (out & (1 << i)) {
if (r.length > 0) r += "+";
r += "ABCD"[i];
}
}
return r;
}
export function __motorUsed(ports: number, large: boolean) {
//console.log("MOTOR INIT " + port);
if (ev3board().motorUsed(ports, large))
runtime.queueDisplayUpdate();
else
U.userError(`${lf("Multiple motors are connected to Port")} ${portsToString(ports)}`);
}
}

View File

@ -17,6 +17,8 @@ namespace pxsim {
private speedCmdTime: number;
private _synchedMotor: MotorNode; // non-null if synchronized
private manualSpeed: number = undefined;
constructor(port: number, large: boolean) {
super(port);
this.setLarge(large);
@ -42,7 +44,7 @@ namespace pxsim {
setSpeedCmd(cmd: DAL, values: number[]) {
if (this.speedCmd != cmd ||
JSON.stringify(this.speedCmdValues) != JSON.stringify(values))
this.setChangedState();
this.setChangedState();
// new command TODO: values
this.speedCmd = cmd;
this.speedCmdValues = values;
@ -68,6 +70,10 @@ namespace pxsim {
this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000;
}
isLarge(): boolean {
return this.id == NodeType.LargeMotor;
}
setPolarity(polarity: number) {
// Either 1 or 255 (reverse)
/*
@ -96,6 +102,17 @@ namespace pxsim {
this.started = true;
}
manualMotorDown() {
}
manualMotorMove(speed: number) {
this.manualSpeed = speed;
}
manualMotorUp() {
this.manualSpeed = undefined;
}
updateState(elapsed: number) {
//console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`)
const interval = Math.min(20, elapsed);
@ -109,79 +126,84 @@ namespace pxsim {
}
private updateStateStep(elapsed: number) {
// compute new speed
switch (this.speedCmd) {
case DAL.opOutputSpeed:
case DAL.opOutputPower:
// assume power == speed
// TODO: PID
this.speed = this.speedCmdValues[0];
break;
case DAL.opOutputTimeSpeed:
case DAL.opOutputTimePower:
case DAL.opOutputStepPower:
case DAL.opOutputStepSpeed: {
// ramp up, run, ramp down, <brake> using time
const speed = this.speedCmdValues[0];
const step1 = this.speedCmdValues[1];
const step2 = this.speedCmdValues[2];
const step3 = this.speedCmdValues[3];
const brake = this.speedCmdValues[4];
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
if (dstep < step1) // rampup
this.speed = speed * dstep / step1;
else if (dstep < step1 + step2) // run
this.speed = speed;
else if (dstep < step1 + step2 + step3)
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
else {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
break;
}
case DAL.opOutputStepSync:
case DAL.opOutputTimeSync: {
const otherMotor = this._synchedMotor;
if (otherMotor.port < this.port) // handled in other motor code
if (!this.manualSpeed) {
// compute new speed
switch (this.speedCmd) {
case DAL.opOutputSpeed:
case DAL.opOutputPower:
// assume power == speed
// TODO: PID
this.speed = this.speedCmdValues[0];
break;
case DAL.opOutputTimeSpeed:
case DAL.opOutputTimePower:
case DAL.opOutputStepPower:
case DAL.opOutputStepSpeed: {
// ramp up, run, ramp down, <brake> using time
const speed = this.speedCmdValues[0];
const step1 = this.speedCmdValues[1];
const step2 = this.speedCmdValues[2];
const step3 = this.speedCmdValues[3];
const brake = this.speedCmdValues[4];
const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed)
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
if (dstep < step1) // rampup
this.speed = speed * dstep / step1;
else if (dstep < step1 + step2) // run
this.speed = speed;
else if (dstep < step1 + step2 + step3)
this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3);
else {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
break;
const speed = this.speedCmdValues[0];
const turnRatio = this.speedCmdValues[1];
const stepsOrTime = this.speedCmdValues[2];
const brake = this.speedCmdValues[3];
const dstep = this.speedCmd == DAL.opOutputTimeSync
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
// 0 is special case, run infinite
if (!stepsOrTime || dstep < stepsOrTime)
this.speed = speed;
else {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
case DAL.opOutputStepSync:
case DAL.opOutputTimeSync: {
const otherMotor = this._synchedMotor;
if (otherMotor.port < this.port) // handled in other motor code
break;
// turn ratio is a bit weird to interpret
// see https://communities.theiet.org/blogs/698/1706
if (turnRatio < 0) {
otherMotor.speed = speed;
this.speed *= (100 + turnRatio) / 100;
} else {
otherMotor.speed = this.speed * (100 - turnRatio) / 100;
const speed = this.speedCmdValues[0];
const turnRatio = this.speedCmdValues[1];
const stepsOrTime = this.speedCmdValues[2];
const brake = this.speedCmdValues[3];
const dstep = this.speedCmd == DAL.opOutputTimeSync
? pxsim.U.now() - this.speedCmdTime
: this.tacho - this.speedCmdTacho;
// 0 is special case, run infinite
if (!stepsOrTime || dstep < stepsOrTime)
this.speed = speed;
else {
if (brake) this.speed = 0;
this.clearSpeedCmd();
}
// turn ratio is a bit weird to interpret
// see https://communities.theiet.org/blogs/698/1706
if (turnRatio < 0) {
otherMotor.speed = speed;
this.speed *= (100 + turnRatio) / 100;
} else {
otherMotor.speed = this.speed * (100 - turnRatio) / 100;
}
// clamp
this.speed = Math.max(-100, Math.min(100, this.speed >> 0));
otherMotor.speed = Math.max(-100, Math.min(100, otherMotor.speed >> 0));;
// stop other motor if needed
if (!this._synchedMotor)
otherMotor.clearSpeedCmd();
break;
}
// clamp
this.speed = Math.max(-100, Math.min(100, this.speed >> 0));
otherMotor.speed = Math.max(-100, Math.min(100, otherMotor.speed >> 0));;
// stop other motor if needed
if (!this._synchedMotor)
otherMotor.clearSpeedCmd();
break;
}
}
else {
this.speed = this.manualSpeed;
}
this.speed = Math.round(this.speed); // integer only
// compute delta angle

View File

@ -97,6 +97,7 @@ namespace pxsim {
motors.forEach(motor => motor.stop());
return 2;
}
case DAL.opOutputPower:
case DAL.opOutputSpeed: {
// setSpeed
const port = buf.data[1];

View File

@ -1,92 +1,77 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 82 156">
<defs>
<clipPath id="clip-path" transform="translate(0.98 1.9)">
<path d="M79,17.05A17.07,17.07,0,0,1,64.92,33.86l.36.39V70c0,.42-.14.4-.39.68L54,81.22v10l.75.78v.79h6.79a4,4,0,0,1,4,4v25.82a4,4,0,0,1-4,4H54.75v8.18A5.79,5.79,0,0,1,49,140.61h-6.5v7.57a4,4,0,0,1-2.9,3.84v1a.6.6,0,0,1-.6.6H12.69a.6.6,0,0,1-.6-.6h0v-1.29a4,4,0,0,1-2.17-3.55v-7.57H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59l13.68.1,0-11.8H26a4,4,0,0,1-4-4V39.79a4,4,0,0,1,4-4h6.78l0-11.77c0-.84.15-.84.46-1.14l10.41-10.1.22-.19a1.53,1.53,0,0,1,1.59.23A17.07,17.07,0,0,1,79,17.05Z" style="fill: none"/>
</clipPath>
<clipPath id="clip-path-2" transform="translate(0.98 1.9)">
<path d="M49,140.61H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59s19.46.14,23.87.14a2.27,2.27,0,0,1,2.37,1L54.75,92v42.79A5.79,5.79,0,0,1,49,140.61Z" style="fill: none"/>
</clipPath>
<clipPath id="clip-path-3" transform="translate(0.98 1.9)">
<path d="M43.18,135.24H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.21C15,95.94,21.86,86.8,21.86,86.8H43.18A5.78,5.78,0,0,1,49,92.58h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" style="fill: none"/>
</clipPath>
</defs>
<title>Large Motor</title>
<g style="isolation: isolate">
<g id="e13b39e7-895d-4931-9be9-7aecaf709784">
<g style="clip-path: url(#clip-path)">
<g id="Large_Motor" data-name="Large Motor">
<path id="LM_back2" data-name="LM back2" d="M39,153.62H12.69a.6.6,0,0,1-.6-.6h0v-5.3a.6.6,0,0,1,.6-.6H39a.6.6,0,0,1,.6.6V153A.6.6,0,0,1,39,153.62Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<g>
<image width="36" height="20" transform="translate(9 136)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAACXBIWXMAAAsSAAALEgHS3X78AAAAp0lEQVRIS+3WsW3DMBBG4Y+GSmcGp/cAHsuzeIasFPdWVpD6c0FKcBWwOxV8wIEgSIAPvOL+EhFKKcUBiIiAgjO+25rJildErJMqdMdVlcwg8MQDv5P6Q1fc5ErRujW1TfmoLPa3T//dymJI9TKkehlSvQypXoZUL5vUNhAz2R1Oao75w9IOMmpRHVZqSpjxo3KRw+YwQ2lx+EsVykqfK+aIWGhSR+MNDy9ID5XUCOsAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_back1-2" data-name="LM back1-2" d="M41.86,152.17H10.53a.6.6,0,0,1-.6-.6v-14.7a.6.6,0,0,1,.6-.6H41.86a.6.6,0,0,1,.6.6h0v14.7A.6.6,0,0,1,41.86,152.17Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_rightside" data-name="LM rightside">
<path id="LM_rightside5" data-name="LM rightside5" d="M33.08,69.61H27.47A5.45,5.45,0,0,1,22,64.15h0V41.25a5.45,5.45,0,0,1,5.46-5.46h5.61a5.46,5.46,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,33.08,69.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<circle id="LM_rightside4" data-name="LM rightside4" cx="28.3" cy="66.21" r="3.79" style="fill: #fff"/>
<circle id="LM_rightside3" data-name="LM rightside3" cx="28.3" cy="43" r="3.79" style="fill: #fff"/>
<path id="LM_rightside2" data-name="LM rightside2" d="M24.4,59.69A4.16,4.16,0,0,1,26.74,59a5.23,5.23,0,0,1,3,.71c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.85-1.23-.46l-1,.58s-.36.19-.36-.33V55s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.39-.29-1.32-.29-1.32H29.1s-.73,0-.73-.65v-1.3s-.23-.36-1.17-.3a3.56,3.56,0,0,0-1.4.3v1.3a.66.66,0,0,1-.66.65c-.63,0-1.26,0-1.26,0s-.25.19-.29,1.32.29,1.39.29,1.39h1.26s.8.05.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.41-.82.46,0,1.8,0,1.8S23.67,60.12,24.4,59.69Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
<path id="LM_rightside1" data-name="LM rightside1" d="M31.25,47.89a.84.84,0,0,1-1,.68.85.85,0,0,1-.24-.09,6.63,6.63,0,0,0-2.85-.77,5.11,5.11,0,0,0-2.77.77c-.83.4-1.07-.59-1.07-.59V46.13a.72.72,0,0,1,.76-.66.67.67,0,0,1,.31.1,5.79,5.79,0,0,0,2.77.84,7.12,7.12,0,0,0,2.85-.84s1.18-.24,1.2.56S31.25,47.89,31.25,47.89Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
</g>
<g>
<image width="36" height="76" transform="translate(32 12)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAACXBIWXMAAAsSAAALEgHS3X78AAACAElEQVRoQ+3avVHDMBiA4VdcypgREmo4RggLpKKHAZiIAWgoKZggrEAGCBsQpxeFpNgJ/vkkK5YLvXe6g2Cb53zE9oVPaa3xSSmlALTvjh4pn2MrpQpgab/dAYdL4MQoC3oAnuxLH8AW2Gmty9YdAxKhaqAXYAUozJnaAm/AJiZs1rfBGegBKOyP7oAFMLfbRYN1ojpAYM7WtX3dbR8F1orqAdVz27n9BsMaUR4gV1yY1vpkYX7BGvgE9oD2WL/AO3CPfROFrKs6MOAMnVcAt3b57lsV6QzV194eYw0UfWelacUGRYFdAjQYNsPcy54xV+rwv4P/Bb8jZ5gr8oK4IFcQzF2nVOdWw/KG9d77IuUFGwsFHrAxUSCEjY0CASwFCnpgqVDQAUuJghZYahQY2Ao4YJ77v08eXRJWUHvenwoKaneVKaGOZZS0jJKWUdIySlpGScsoaRklLaOkZZS0jJKWUdIySlpGScsoaRklLaOkTQml3RdTQZXAD+bD2EmgSuALMwmyg/SoEtgAr9RGU1KiGkGQDtUKgjSoThCMj+oFwbgoEQjGQ4lBMA7KCwSXR3mDoPonpBsFccWYUwgCgUEdMAN/YDBzzKjJvG0nQe7W4Q2CCnFDhVgCj1TznCHtGDDVqLTWxylXW4wzdWDA/GfjnOcZMijddGBhouHTsfsDst/cEY24RzwAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level4-2" data-name="LM level4-2" d="M64.91,70.7,51.5,83.63,32.93,83,32.76,24c0-.84.16-.84.46-1.13l10.42-10.1.21-.19c.59-.4,2,.11,2,.95L65.29,34.25V70C65.3,70.44,65.16,70.43,64.91,70.7Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g>
<image width="25" height="27" transform="translate(32 69)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAACXBIWXMAAAsSAAALEgHS3X78AAABYUlEQVRIS+2WvVXDMBRG7/NxGVf0CRVFchghWSAVA2QAxmEGGgZgguzgHlPTELv/KCSD/BMs2wkV9xwf2/LPlZ70JJkk2piZdQojUd8PAWuXm1kGrIBF3wcDVEAhqWw/aIi8ZAcccLKxFMAzcGzL0voikDwCWyBjPGt8JMysKfMtMuAeeAE+Ac04TsArsAcySUj6blGGq82aaS0JyXARqYDCzHJJSnzItrh+ucW1bi4ZsCQYUAmu0w9M75dzNCqc4KxLLivpkPjzJcL1Kwl/xL9oMnXC1lkdw6SBk+IyOPf3Qz9Z8DOzD73bIAXegCfiloUV8ABs/HV07qWSKjPLiSP3xwY3m+yIlKVwflXsofSVeseFHCJlKSPxlTqZ2TEoHpSNFtVIKsfIJotgnGyWCHplW3pG8GwRdGQVbqXu35zMJZAVONEdgayzr5uL33wugBvgQ1IFVxDVmJmF+Xk1UZsvIeCPQjWq5BoAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level3-2" data-name="LM level3-2" d="M54,92V74.7a2.19,2.19,0,0,0-.3-1.12c-.28-.27-3.52-3.62-3.52-3.62a1.55,1.55,0,0,0-1.16-.4c-.75,0-11.62,0-11.62,0L33,74.26v8l10.66.57Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_leftside" data-name="LM leftside">
<path id="LM_leftside5" data-name="LM leftside5" d="M60.08,126.64H54.47A5.45,5.45,0,0,1,49,121.18h0V98.28a5.46,5.46,0,0,1,5.46-5.46h5.61a5.47,5.47,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,60.08,126.64Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<circle id="LM_leftside4" data-name="LM leftside4" cx="61.67" cy="123.24" r="3.79" style="fill: #fff"/>
<circle id="LM_leftside3" data-name="LM leftside3" cx="61.67" cy="100.03" r="3.79" style="fill: #fff"/>
<path id="LM_leftside2" data-name="LM leftside2" d="M57.77,116.72a4.15,4.15,0,0,1,2.34-.7,5.14,5.14,0,0,1,3,.7c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.84-1.23-.46l-1,.58s-.36.19-.36-.33V112s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.38-.29-1.33-.29-1.33H62.47s-.73,0-.73-.64v-1.3s-.23-.36-1.17-.31a3.57,3.57,0,0,0-1.4.31v1.3a.66.66,0,0,1-.66.64H57.25s-.25.2-.29,1.33.29,1.38.29,1.38h1.26s.8,0,.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.4-.82.46,0,1.8,0,1.8S57,117.16,57.77,116.72Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
<path id="LM_leftside1" data-name="LM leftside1" d="M64.62,104.92a.83.83,0,0,1-1,.68.68.68,0,0,1-.24-.08,6.46,6.46,0,0,0-2.85-.77,5,5,0,0,0-2.77.77c-.83.4-1.07-.6-1.07-.6v-1.76a.71.71,0,0,1,.76-.65.8.8,0,0,1,.31.09,5.79,5.79,0,0,0,2.77.84,7,7,0,0,0,2.85-.84s1.18-.24,1.2.56S64.62,104.92,64.62,104.92Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
</g>
<g>
<image width="58" height="64" transform="translate(0 81)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAACXBIWXMAAAsSAAALEgHS3X78AAACFElEQVRoQ+2bQY7TMBSGvxcqsaFbJDbDrEEcYeYCcwYOwIlYsWLDjg0nGG6A1ANkbgCNhGb1WNgBpxPbaUjT+smf5E3lxPlq/25S5YmqshQiIrk+S6EzLlxmHDOKiGyB18CLXN8F6IAW6I6RXkTWi94C73HCp6YFvgI7oFXVfaY/sIBsIPoBuAG26SMWoZ/ZHfAZuJ8ivMl1SHEgess6ouDGeQtc4WMjInlhVZ3VcAPeAd+AX4Ceqf0EvgDv8Cs11hpm4Hfda1xG11q6MbbAG9+S1zFLliMGWIHBF++jNcrRmfUnu8Gd/Bo32Lnp9w4gnt+jZM+4IU0hKzxZ9sJyGiMpPFmWy8ppiqjwJNkLzWmK/no7oBWRnapqdje+8Jym2BLcdEDmp6eQnKYYrMDczJaS00lEZQvMaZZR2YJzmuSJrIGcRhmbWVM5DRnIWsxpyF9ZqzkNacB2TkP6mTWb05DGek5DGtxfn6aXb0+Du1G+wrgo/Mus2aUbknsQMEWVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUovq8le5TLwanBvbj4A2VKRwtjjvLr+g2fAb1wFxUvgFfB89NCy2APfgU/AD1V9BNio6l5E7oOOpb9u0It+5KC4aQNwINyxTonZqWiJVHENytNk3eLBU9ERqc97UovnXwArGj2U8vx34WFJ/AG0vvY6LSeZMAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level2_grey-2" data-name="LM level2 grey-2" d="M49,140.61H6.31a5.78,5.78,0,0,1-5.78-5.78h0V105.19C10.89,91.13,18.65,81.32,18.65,81.32h.6s19.46.15,23.86.15a2.29,2.29,0,0,1,2.38,1L54.75,92v42.8A5.78,5.78,0,0,1,49,140.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_total" data-name="LM total">
<g id="LM_whitepart" data-name="LM whitepart">
<g style="clip-path: url(#clip-path-2)">
<g id="LM_whitepart_combined" data-name="LM whitepart combined">
<path id="LM_whitepart_top" data-name="LM whitepart top" d="M43.48,141l-7.15-7.37L12.54,102.56V87.7L-.52,103.84v31.22l1,7.69Z" transform="translate(0.98 1.9)" style="fill: #f1f1f1"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="82px" height="156px" viewBox="0 0 82 156" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Large Motor</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-66.000000, -54.000000)">
<g id="Large-Motor" transform="translate(66.000000, 54.000000)">
<path d="M39.98,155.52 L13.67,155.52 C13.3386292,155.52 13.07,155.251371 13.07,154.92 L13.07,149.62 C13.07,149.288629 13.3386292,149.02 13.67,149.02 L39.98,149.02 C40.3113708,149.02 40.58,149.288629 40.58,149.62 L40.58,154.9 C40.5854219,155.062566 40.5246096,155.220368 40.4114947,155.337253 C40.2983799,155.454138 40.1426565,155.52009 39.98,155.52 Z" id="LM_back2" fill="#A8AAA8" fill-rule="nonzero"></path>
<g id="Group" transform="translate(9.000000, 136.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAAAXNSR0IArs4c6QAAAMRJREFUSA3tlrERwjAMRW2OEmYgPQMwFrMwAytBT1iB9OY/x05J1IAopLtv2Y5yevfPhXIpJWVF+oMQSwEDmJ00tKzkFpM6P8Q1bbUZpLN0lLwcw6G7dJFuQOEUQCfJE0rtK0sCigCmq144LIshG4fmqy0DatWiVhBOhVNWB6x18abCKasD1rr+puocY/3pS3ULA1DMMU/pJfHBQ/SGAZY6JYzKVw6Kw5x+vnYGcsptHN5rDxCzlUfg0CgWHJuhPCg+9XwDDy9ID0K8XgsAAAAASUVORK5CYII="></image>
<path d="M33.84,18.07 L2.51,18.07 C2.17862915,18.07 1.91,17.8013708 1.91,17.47 L1.91,2.77 C1.91,2.43862915 2.17862915,2.17 2.51,2.17 L33.84,2.17 C34.1713708,2.17 34.44,2.43862915 34.44,2.77 L34.44,17.47 C34.44,17.8013708 34.1713708,18.07 33.84,18.07 Z" id="LM_back1-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_rightside" transform="translate(22.000000, 37.000000)" fill-rule="nonzero">
<path d="M12.06,34.51 L6.45,34.51 C4.99937339,34.5153259 3.60647912,33.9421088 2.57978624,32.9172929 C1.55309337,31.892477 0.977328505,30.5006339 0.98,29.05 L0.98,6.15 C0.977339027,4.70110385 1.55173283,3.31078487 2.57625885,2.28625885 C3.60078487,1.26173283 4.99110385,0.687339027 6.44,0.69 L12.05,0.69 C15.0654747,0.69 17.51,3.13452527 17.51,6.15 L17.51,29.05 C17.5126553,30.4971617 16.939633,31.8859609 15.9172718,32.910198 C14.8949106,33.9344351 13.5071641,34.5100024 12.06,34.51 Z" id="LM_rightside5" fill="#A8AAA8"></path>
<circle id="LM_rightside4" fill="#FFFFFF" cx="6.3" cy="29.21" r="3.79"></circle>
<circle id="LM_rightside3" fill="#FFFFFF" cx="6.3" cy="6" r="3.79"></circle>
<path d="M3.38,24.59 C4.07351535,24.1313154 4.88857129,23.8909784 5.72,23.9 C6.76862292,23.8298668 7.81405119,24.0772848 8.72,24.61 C9.97,25.54 9.95,24.51 9.95,24.51 L9.95,22.71 C9.95,22.26 9.39,21.86 8.72,22.25 L7.72,22.83 C7.72,22.83 7.36,23.02 7.36,22.5 L7.36,19.9 C7.36,19.9 7.36,19.11 8.09,19.13 C8.82,19.15 9.47,19.13 9.47,19.13 C9.47,19.13 9.76,18.88 9.76,17.74 C9.76,16.6 9.47,16.42 9.47,16.42 L8.08,16.42 C8.08,16.42 7.35,16.42 7.35,15.77 L7.35,14.47 C7.35,14.47 7.12,14.11 6.18,14.17 C5.6978322,14.1741563 5.22153417,14.2762201 4.78,14.47 L4.78,15.77 C4.77453579,16.1305967 4.48063814,16.4200414 4.12,16.42 C3.49,16.42 2.86,16.42 2.86,16.42 C2.86,16.42 2.61,16.61 2.57,17.74 C2.53,18.87 2.86,19.13 2.86,19.13 L4.12,19.13 C4.12,19.13 4.92,19.18 4.94,19.9 C4.96,20.62 4.94,22.52 4.94,22.52 C4.94,22.52 4.94,23.03 4.6,22.85 L3.39,22.27 C3.39,22.27 2.56,21.86 2.57,22.73 C2.58,23.6 2.57,24.53 2.57,24.53 C2.57,24.53 2.65,25.02 3.38,24.59 Z" id="LM_rightside2" fill="#FFFFFF"></path>
<path d="M10.23,12.79 C10.1913976,13.0147775 10.0630557,13.2141964 9.87446015,13.3424414 C9.68586455,13.4706864 9.453229,13.5167322 9.23,13.47 C9.14591061,13.4523039 9.06499079,13.421959 8.99,13.38 C8.1099436,12.9124008 7.1357966,12.6492102 6.14,12.61 C5.162003,12.5962776 4.20061308,12.8635231 3.37,13.38 C2.54,13.78 2.3,12.79 2.3,12.79 L2.3,11.03 C2.33192589,10.6400455 2.66941985,10.3469587 3.06,10.37 C3.16998614,10.3773249 3.27646607,10.4116733 3.37,10.47 C4.20732336,10.980005 5.16044012,11.2690368 6.14,11.31 C7.13850164,11.2335413 8.10964397,10.9473099 8.99,10.47 C8.99,10.47 10.17,10.23 10.19,11.03 C10.21,11.83 10.23,12.79 10.23,12.79 Z" id="LM_rightside1" fill="#FFFFFF"></path>
</g>
<g id="Group" transform="translate(32.000000, 12.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="76" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAAAXNSR0IArs4c6QAAAnlJREFUaAXtmsFRwzAQRROGI6EEwhmGEqABTtyhACqiAC4cOVBBaAEKCB0AuYf/hdbjBMcrbYTlw+7MZp3IWr98OZIn2ul6vZ7k2BTG89Evr2PGRaY5ucEzQ+55zL9EXP0HXDJUBLoCyG2EekZ8hy8B9h0/KxKSoFpA97jqJZxDSKUI9QhflAQ7RMJe2wKiUhxC2jn8BH7ENzivGFgvVA9Q4MDLMZygwUqB7YRSgISDkcoVBeuEygASuLJgnBLaHr/5NeIL/AvO+SjVP3HuE/wCHn5E7dypxwfo3JhBoaZvPKBiZ9F5bDOhR28msSrUVpLqUmXmmkn+nBiGjp1jEsuQtYHkeC8wsBQH2huMv745/A7Omdp+H6DzljGXaaogFGdkzswlgZAumAlM5qnwOCKZCsdsMIEqzPEnXRbYUFCkTAYbEioZbGioJLAaUCpYLahesJpQO8FqQwkYV5MVnM/9bxuPLjyjknG64KoSnvfHAkUtmlVlTFAEC+ZQooQWXSlNIWl3pUQJLbpSmkLS7kqJElp0pTSFpN2VEiW06EppCkm7KyVKaNGV0hSSdldKlNCiK6UpJO2ulCihRVdKU0jaXSlRQouulKaQtI9JKW7JBRsLFCtAPuD8M3YyBigCvcJZCcJ/h6tDEWgBf2DEPnOomampVCcQ4KoptROoFlQvUA0oFWhoqCSgIaGSgYaCygIaAiobiFCy3yelIPyM1uwo/b41vZqAeCVCcb1hwR+NMNxzY6lJ2HtDtBiBuHRszNSpiQTiFB0EgkA3cEarcQ0zVzWGajAUc7WHq4RSYetV1rLcb9ZZ57kFmZsznA8g3qcm64QyZSrY6Qey39wRVmjftAAAAABJRU5ErkJggg=="></image>
<path d="M33.89,60.6 L20.48,73.53 L1.91,72.9 L1.74,13.9 C1.74,13.06 1.9,13.06 2.2,12.77 L12.62,2.67 L12.83,2.48 C13.42,2.08 14.83,2.59 14.83,3.43 L34.27,24.15 L34.27,59.9 C34.28,60.34 34.14,60.33 33.89,60.6 Z" id="LM_level4-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="Group" transform="translate(32.000000, 69.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="25" height="27" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAAAXNSR0IArs4c6QAAAZhJREFUSA3tlj1SwzAQRnEmJanogYoChiOQC1BxAA7AcTgDDQfgBLlDekxNQ5LefE/WeizHGa9l07Ezny3L2n36W9lFVVVnXStk3Trvs+IdB5Rz0a0XY6X6K+ncG7zV7qByqZj7Vl0oJqAIWevNswRsrJVyeJM2XdjSIrUgL6p7kBjZWLuVQ5gJxUthcepYk3vpXfqRmOdc7eT7IT1KK+IjGxG9pzcoZyRyawx/ZiSsl0a2FahaxCnjBetyLWXvOPmaAbuUmg210AOLDgTY1NEoRGNJhwFBhT4npKFZARCW0Ouqea8GmjdqT7R/UM+k+KosYe0U8HhlbRxAZPA2EoaCkArkHfehtjFkfQP0Kb1KTRarfMqAPEl3EmV37i11DB04j+TkMdohQJwmfFJcsLBGHHpy8Ng+dupLjZlyzAWzzVC7OK6xUzsBN63mg7DRIAsuIKNzw7JBAMfAJoFOwPjcHO3gyaAeGJuEL3XyJzQLqAMrI+imDUt+t3CYatognBhM3YX0rXUMaTA7yDoKMKZCqPozkAHt/gsh4I9CsIZ80gAAAABJRU5ErkJggg=="></image>
<path d="M22.9800421,24.9 L22.98,7.6 C22.9824406,7.20649401 22.8788083,6.81960003 22.68,6.48 C22.4,6.21 19.16,2.86 19.16,2.86 C18.8448174,2.57277854 18.4252272,2.42809227 18,2.46 C17.25,2.46 6.38,2.46 6.38,2.46 L1.98,7.16 L1.98,15.16 L12.64,15.73 L22.9800421,24.9 Z" id="LM_level3-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_leftside" transform="translate(49.000000, 94.000000)" fill-rule="nonzero">
<path d="M12.06,34.54 L6.45,34.54 C4.99937339,34.5453259 3.60647912,33.9721088 2.57978624,32.9472929 C1.55309337,31.922477 0.977328505,30.5306339 0.98,29.08 L0.98,6.18 C0.98,3.16452527 3.42452527,0.72 6.44,0.72 L12.05,0.72 C15.0631921,0.725503561 17.5044964,3.16680786 17.51,6.18 L17.51,29.08 C17.5126553,30.5271617 16.939633,31.9159609 15.9172718,32.940198 C14.8949106,33.9644351 13.5071641,34.5400024 12.06,34.54 Z" id="LM_leftside5" fill="#A8AAA8"></path>
<circle id="LM_leftside4" fill="#FFFFFF" cx="12.67" cy="29.24" r="3.79"></circle>
<circle id="LM_leftside3" fill="#FFFFFF" cx="12.67" cy="6.03" r="3.79"></circle>
<path d="M9.75,24.62 C10.4421225,24.1572205 11.2574415,23.9133217 12.09,23.92 C13.1380484,23.8411302 14.1850856,24.0854388 15.09,24.62 C16.34,25.55 16.32,24.52 16.32,24.52 L16.32,22.72 C16.32,22.27 15.76,21.88 15.09,22.26 L14.09,22.84 C14.09,22.84 13.73,23.03 13.73,22.51 L13.73,19.9 C13.73,19.9 13.73,19.11 14.46,19.13 C15.19,19.15 15.84,19.13 15.84,19.13 C15.84,19.13 16.13,18.88 16.13,17.75 C16.13,16.62 15.84,16.42 15.84,16.42 L14.45,16.42 C14.45,16.42 13.72,16.42 13.72,15.78 L13.72,14.48 C13.72,14.48 13.49,14.12 12.55,14.17 C12.0671703,14.1775857 11.5908982,14.283046 11.15,14.48 L11.15,15.78 C11.1391868,16.1366743 10.8468382,16.4201639 10.49,16.42 L9.23,16.42 C9.23,16.42 8.98,16.62 8.94,17.75 C8.9,18.88 9.23,19.13 9.23,19.13 L10.49,19.13 C10.49,19.13 11.29,19.13 11.31,19.9 C11.33,20.67 11.31,22.52 11.31,22.52 C11.31,22.52 11.31,23.03 10.97,22.85 L9.76,22.27 C9.76,22.27 8.93,21.87 8.94,22.73 C8.95,23.59 8.94,24.53 8.94,24.53 C8.94,24.53 8.98,25.06 9.75,24.62 Z" id="LM_leftside2" fill="#FFFFFF"></path>
<path d="M16.6,12.82 C16.5640845,13.0461448 16.4363396,13.2474057 16.2469908,13.3761629 C16.057642,13.5049201 15.8235128,13.5497335 15.6,13.5 C15.5157002,13.4885804 15.4342916,13.4614442 15.36,13.42 C14.4821686,12.9467916 13.506699,12.6832437 12.51,12.65 C11.5311949,12.6299456 10.5680375,12.8976825 9.74,13.42 C8.91,13.82 8.67,12.82 8.67,12.82 L8.67,11.06 C8.70188656,10.6714097 9.04116607,10.3812364 9.43,10.41 C9.53837526,10.4186243 9.6438555,10.4492476 9.74,10.5 C10.5773234,11.010005 11.5304401,11.2990368 12.51,11.34 C13.5091637,11.2671668 14.4810541,10.9807149 15.36,10.5 C15.36,10.5 16.54,10.26 16.56,11.06 C16.58,11.86 16.6,12.82 16.6,12.82 Z" id="LM_leftside1" fill="#FFFFFF"></path>
</g>
<g id="Group" transform="translate(0.000000, 81.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="58" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAAAXNSR0IArs4c6QAAAqRJREFUaAXtm01OwzAQhSlUYgNbJDalaxBHgAtwBg7AiVixYsOODScoN0DqAcoNoJUQq/CecaK64zhOm7T1yCNNf+zUns/P4xjkDIqiOOjKBrCu2mpqB3G3Dnywxm+8cYDzFBUX8BPvBd0WLtDcDL5oA90JrAW9Ref3cAL3bQR9hU/hMwDPYzrcGHYJ9AEd3sCpcN9WKkvYZ/gkBni4SVQroFR2G6AMmf1cwUdwkzaIpRmYObuO2w7v8P4G/4ZzwdiFf6HfF/g13MzUOp5DXNDaMIpcdcdw5ui2pi668hpVvrQenFlrwaLh6A684XVb6Ay8TS1vD61z1jZGNanqGM7Odm0cfK4ZxhCjN39bwVpQNsqVd5sL0j9F+LUROBoWoM50Qb/B/AjH1VttEDga1sJFLQS9ocQ1XAscBWun777laQidwIzXbD4Q/xS3o6JxNbag+5qnTcAjXFDt1YOwAE0hT0PAzp0iCItWOB1SyNMQcFVXC2unb0p5WkHVffDCJpyndZymXMAqyNNaYAGLK1Xl6TK5A6sxT72wWvNUwGrOUwGLArV56sBqz1MHFl/4r0/+Ic4NBBVWa1yNuVHmhlk1KBUsbz3OhpkVGq2E1cgmmDKsGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjFJZnu3XaA4XYXly8xMe9WxMQiNCHnKRz9gRXn/gfILiDH4OP4anbgR9hz/BP3D69pdAQ3yY41zFhF+spX7coAR9BI/zrIA5XL0CTNl5ziJVmyFw71NczuNp9uQMQasDyQkSm9PjFHA1dgeWlfYA2Op1SX0HqLMKl8EL2LJC4/sftL72OnfR538AAAAASUVORK5CYII="></image>
<path d="M49.98,61.51 L7.29,61.51 C4.09779415,61.51 1.51,58.9222059 1.51,55.73 L1.51,26.09 C11.87,12.03 19.63,2.22 19.63,2.22 L20.23,2.22 C20.23,2.22 39.69,2.37 44.09,2.37 C45.013529,2.18179526 45.9580478,2.5786519 46.47,3.37 L55.73,12.9 L55.73,55.7 C55.7379772,57.2329575 55.1366519,58.7062958 54.0583133,59.7958867 C52.9799747,60.8854775 51.5129577,61.5020641 49.98,61.51 Z" id="LM_level2_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_total">
<g id="LM_whitepart" transform="translate(0.000000, 89.000000)" fill="#F1F1F1" fill-rule="nonzero">
<g id="LM_whitepart_combined">
<polygon id="LM_whitepart_top" points="44.46 53.9 37.31 46.53 13.52 15.46 13.52 0.6 0.46 16.74 0.46 47.96 1.46 55.65"></polygon>
</g>
</g>
</g>
</g>
<g>
<image width="47" height="52" transform="translate(5 87)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAACXBIWXMAAAsSAAALEgHS3X78AAABnElEQVRoQ+2azXHCMBBG3zIccQuBM5MWoIHUkAJSUQrIJQWkAlIJ6SDYd+UgGWTjHxQHr5TRm9HFIzz75G8Z8KwYY5iKiMjYnr/AdBQrUwVEpADWwGps70Qq4GiMKf2LkwRc8XvgGStxT47AG3DwJZb9+4fxin8BdkAx/InJbHFPWUQuEsaY4IUt9gn4AE6AmWl9A+/AIy49CwJxDbvBxmaOk/cpgAe8fgsWwN5k69acxdc0vvGCBFzud9jT39C6mQY3C7Sado/O6V9xk4By7ge5SQD93PcyKhBj7n0GBWLNvU+vQArFQ49AzE3bpu8JRNu0ba4EYm/aNg2BVHLvcxZIKfc+/hNIJvc+C0gv9z4LF501iUWnpo7QCvtHIaniodkDycTGZ/THXOxkAW2ygDZZQJssoE0W0CYLaJMFtMkC2mQBbbKANv9K4PdDE/PSqLMWqIAvoDEJEiElts7qfEV59iFknbD1PQFFPbexBDDGlCJy4EJs70hL4BN4pW/cpiVRcf/5nxA6Z4WgY+BpxgmsEDqntWDixFYM/ACNRtJx4q2GRAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_top_grey-2" data-name="LM top grey-2" d="M43.18,135.54H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.51C15,96.24,21.86,87.1,21.86,87.1H43.18A5.78,5.78,0,0,1,49,92.88h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_top" data-name="LM top">
<g style="clip-path: url(#clip-path-3)">
<g id="LM_top_total" data-name="LM top total">
<path id="LM_top_lines" data-name="LM top lines" d="M18.6,112.05v27.47a1.08,1.08,0,0,1-1.12,1,1.06,1.06,0,0,1-1.05-1V112.05A1.09,1.09,0,0,1,18.6,112Zm3.61,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.62,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.61,0v27.47a1.09,1.09,0,0,1-2.17.07V112.05a1.09,1.09,0,0,1,2.17-.07Zm3.62,0v27.47A1.1,1.1,0,0,1,32,140.64a1.08,1.08,0,0,1-1.11-1V112.05a1.09,1.09,0,0,1,2.17-.07Z" transform="translate(0.98 1.9)" style="fill: #6a6a6a"/>
<g id="Group" transform="translate(5.000000, 87.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="47" height="52" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAAAXNSR0IArs4c6QAAAhhJREFUaAXtWttRwzAQxAyfpAWSb4YWoAFqoIBURAH8UAAVhEpMBxD+za6xFMmyQcqNLWnmbmbHj1in3btTYjvXdF13IbUGJvURMx5cA7LNxLkYX/YacN/gYAtc25PL7HzDbQu+R9e9SMBA/gEOnwCKWNJaOH8BDq6Iq3NndMjv4eMeYCaWtFs477OMuU8iWEKpgCOSfQTegC+AtbkGPjHPK3AH9NVziZ0kg3ou2B3Aslkj8pjGGgN3A9j1liwAg+mE6SSWLhtMEZj3jZckYKh7Rp3R3wGeMxyvbtECBvL8xuGi5TZH9IMARQnIXPcBafdElIAh2jnr3uXs7f8roMS6dxX8KaDUuo8SUAN5CpnMQMmL1o3+rAB8kPvHasxz9jjIQOmLdqzEE1BL3bsirICa6n5SAE5WU/eBgNrq3hMwlA4fB3Pc37tczto3a4APCHxQKOIOM0WJEcAx2e/tU4iba10B5lxVWxWQO12aAc2AMAJaQsIAiodrBsQhFDrQDAgDKB6uGRCHUOhAMyAMoHi4ZkAcQqEDzYAwgOLhmgFxCIUO3Azwn/YazONpBLAT5APwOkEKVEN+5Em+v8Y+CRjfyOXofeDksWBPBnszyHNj+jv6bhUcHPGO9IAPjK3dA2Hmndsy8u/AM3DqVMGBbbcZiWCKtkAp1oJI0CtEckHD0/CqneRtRwgvzGwMaNCtRU6BgMxEk6f/AY1G0nHf2MzkAAAAAElFTkSuQmCC"></image>
<path d="M39.16,50.44 L8.07,50.44 C6.5353168,50.4426552 5.06258085,49.834865 3.97645681,48.7506168 C2.89033276,47.6663686 2.2799977,46.1946855 2.28,44.66 L2.28,22.41 C10.98,11.14 17.84,2 17.84,2 L39.16,2 C40.6998701,1.9893432 42.1803327,2.59359794 43.2729596,3.67871541 C44.3655865,4.76383288 44.9800369,6.24009301 44.98,7.78 L44.98,44.66 C44.98,46.1929513 44.3710375,47.6631169 43.2870772,48.7470772 C42.2031169,49.8310375 40.7329513,50.44 39.2,50.44 L39.16,50.44 Z" id="LM_top_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_top" transform="translate(17.000000, 112.000000)" fill="#6A6A6A" fill-rule="nonzero">
<g id="LM_top_total">
<path d="M2.58,1.95 L2.58,29.42 C2.53732346,30.0007732 2.04187943,30.443134 1.46,30.42 C0.901094365,30.4156223 0.441619994,29.9780276 0.41,29.42 L0.41,1.95 C0.449349984,1.38861093 0.909606462,0.949468178 1.47222361,0.93650465 C2.03484076,0.923541121 2.51483504,1.34101911 2.58,1.9 L2.58,1.95 Z M6.19,1.95 L6.19,29.42 C6.2296472,29.8325035 6.03195189,30.231808 5.67986701,30.4503653 C5.32778212,30.6689226 4.88221788,30.6689226 4.53013299,30.4503653 C4.17804811,30.231808 3.9803528,29.8325035 4.02,29.42 L4.02,1.95 C3.9803528,1.53749648 4.17804811,1.138192 4.53013299,0.919634704 C4.88221788,0.701077408 5.32778212,0.701077408 5.67986701,0.919634704 C6.03195189,1.138192 6.2296472,1.53749648 6.19,1.95 Z M9.81,1.95 L9.81,29.42 C9.8496472,29.8325035 9.65195189,30.231808 9.29986701,30.4503653 C8.94778212,30.6689226 8.50221788,30.6689226 8.15013299,30.4503653 C7.79804811,30.231808 7.6003528,29.8325035 7.64,29.42 L7.64,1.95 C7.6003528,1.53749648 7.79804811,1.138192 8.15013299,0.919634704 C8.50221788,0.701077408 8.94778212,0.701077408 9.29986701,0.919634704 C9.65195189,1.138192 9.8496472,1.53749648 9.81,1.95 Z M13.42,1.95 L13.42,29.42 C13.3873113,29.9829764 12.9306072,30.4280683 12.3669758,30.44625 C11.8033444,30.4644316 11.318904,30.0496992 11.25,29.49 L11.25,1.95 C11.2826887,1.38702361 11.7393928,0.941931677 12.3030242,0.923750018 C12.8666556,0.905568359 13.351096,1.3203008 13.42,1.88 L13.42,1.95 Z M17.04,1.95 L17.04,29.42 C17.0513034,30.0199642 16.5796777,30.5182857 15.98,30.54 C15.401933,30.5576338 14.9125708,30.1167669 14.87,29.54 L14.87,1.95 C14.9026887,1.38702361 15.3593928,0.941931677 15.9230242,0.923750018 C16.4866556,0.905568359 16.971096,1.3203008 17.04,1.88 L17.04,1.95 Z" id="LM_top_lines"></path>
</g>
</g>
<circle id="LM_detail_2" fill="#9A9A9A" fill-rule="nonzero" cx="50.32" cy="137.11" r="2.24"></circle>
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="44" y="0" width="38" height="38" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAAAXNSR0IArs4c6QAAAu1JREFUWAnNmD1y1EAQhb1bhJgjsMT8HAEuQGJHRJyOhAwCTmAyQqpMvOsbYDtGvE/Mm+oZaWUtaHfoqt75n/70WquSZtV13dkhtpKF+Y9V38gpbfeq7OSU2RTnsEBauZq7JkHVMIBdyiltgH2SU9oy8CGQs+AEdq4oALyQR5gaFpgMQiOZga/V3gnwzgNT5SRcUguw1/L3cuCAjGlcqV1bV3UYGLgP8q/yu4dUfFRtkpuVWoABCOgYTF6XKvUc1nFhT+VcGH6tGJMqjiqXwN5og6gWAZYwUkqareLV3jRr4Cy6FgHxVv5F/lP+S06alnT2ZG9iEOs8Mrheg5GOV/KPchYvCTS2FzGIRcw+iwajXKszGqo9T0792DYdz6SiYKLTeav62JUeo49Yo+nt06rBU6ezvkin9yUsFsxp5a99ynQqXGFkbSOHI9s6PWgZuJQ/k6NiCwOsAIzK+QHZAgxBLNAmCVb8W1spZjFQrhDIyrUGMyAcmQW4AbFnNigLFuByrlXP1A3AiB1Z+nuuoG0AFUMWLL7n4oSWdd77buSUvXJFB52NrFPcnTy/4qNc7GBCSyuEAq7oaEmWYmeBfM/ljsZwBYfhYCoGGkAOMmi4wcCJ4RAm3/t6ZeqFWqeKB7aa1EpBBIKDsreo3A/14LM+eP8sX+zXX2QZrN/Zb51q/J+v6QHwiSDfyb/Lj/FJyC0Tfe/3A0xOq9b0hrynSi8Xv5X3xxOCGdxOBZwmcFV5ger+ClN1UQOEL/5vqRyAEW1wVsIV6DX5ikEZNyhnHBs59+S/GhcPCAc5KAbgNomiammjZyVMSeclQAEXD3L6YX4OMKD8qPAZyYMnTQPlHDApyEY3aWM2B5Z3LpeqZlulGiDRIhRvHOy5Y/84aay+V7k4OahoMD4jAbS5n3bxIE3tDKX2/b40sjjaLDgW+HNNVYNQ2gC9SI3PKgG0WbnZUF44G84LKAOouw1Mu1aOI4861V43Wf4V3OSOCw7+BmjmA7QisxQnAAAAAElFTkSuQmCC"></image>
<circle id="LM_detail_1" fill="#9A9A9A" fill-rule="nonzero" cx="21.66" cy="86.59" r="2.24"></circle>
<g id="hole" transform="translate(45.000000, 1.000000)" fill-rule="nonzero">
<g id="Group" fill="#D42715">
<circle id="LM_red-2" cx="17.96" cy="17.95" r="17.06"></circle>
</g>
<g id="LM_details_in_red" transform="translate(2.000000, 2.000000)">
<circle id="LM_detail_red_hole4" fill="#393939" cx="12.9" cy="27.01" r="3.79"></circle>
<circle id="LM_detail_red_hole3" fill="#393939" cx="4.75" cy="12.89" r="3.79"></circle>
<circle id="LM_detail_red_hole2" fill="#393939" cx="18.87" cy="4.74" r="3.79"></circle>
<circle id="LM_detail_red_hole1" fill="#393939" cx="27.02" cy="18.86" r="3.79"></circle>
<path d="M18.18,15.31 C17.9816076,15.2705154 17.8089761,15.149396 17.7043432,14.9762761 C17.5997103,14.8031562 17.5727287,14.5940066 17.63,14.4 C17.84,13.68 17.99,13.07 17.99,13.07 C17.99,13.07 17.82,12.72 16.72,12.43 C15.62,12.14 15.37,12.37 15.37,12.37 L14.98,13.7 C14.98,13.7 14.82,14.42 14.17,14.24 L12.98,13.9 C12.98,13.9 12.58,14.03 12.38,14.96 C12.2599627,15.4271881 12.2395203,15.9143986 12.32,16.39 L13.57,16.72 C13.9132251,16.8260991 14.1147049,17.1808788 14.03,17.53 C13.87,18.14 13.7,18.74 13.7,18.74 C13.7,18.74 13.82,19.04 14.9,19.36 C15.98,19.68 16.32,19.45 16.32,19.45 L16.64,18.23 C16.64,18.23 16.9,17.47 17.64,17.64 C18.04,17.7533333 18.44,17.8833333 18.84,18.03 C19.3790257,17.4116231 19.6330766,16.5950309 19.54,15.78 C18.89,15.55 18.18,15.31 18.18,15.31 Z" id="LM_detail_hole" fill="#1F1F1F"></path>
<path d="M15.62,23.13 L14.07,22.9 L12.54,22.33 C12.29437,22.2663058 12.1467122,22.015735 12.21,21.77 L12.76,19.72 C12.8281001,19.4784149 13.0772913,19.3360199 13.32,19.4 L14.77,20 L16.4,20.22 C16.64563,20.2836942 16.7932878,20.534265 16.73,20.78 L16.18,22.83 C16.1519467,22.9468655 16.0773095,23.0471692 15.9734274,23.1076097 C15.8695454,23.1680501 15.7454609,23.1833663 15.63,23.15 L15.62,23.13 Z" id="LM_detail_red4" fill="#393939"></path>
<path d="M23.13,16.2 L22.87,17.75 L22.3,19.27 C22.2716803,19.3872072 22.1975067,19.4881458 22.0941102,19.5501837 C21.9907137,19.6122216 21.8667451,19.6301684 21.75,19.6 L19.69,19.05 C19.4484149,18.9818999 19.3060199,18.7327087 19.37,18.49 L19.98,17.05 L20.2,15.42 C20.2283197,15.3027928 20.3024933,15.2018542 20.4058898,15.1398163 C20.5092863,15.0777784 20.6332549,15.0598316 20.75,15.09 L22.75,15.64 C22.9915851,15.7081001 23.1339801,15.9572913 23.07,16.2 L23.13,16.2 Z" id="LM_detail_red3" fill="#393939"></path>
<path d="M16.19,8.69 L17.74,8.94 L19.27,9.51 C19.5107539,9.57376787 19.6570302,9.81756168 19.6,10.06 L19.05,12.11 C18.9818999,12.3515851 18.7327087,12.4939801 18.49,12.43 L17.04,11.83 L15.41,11.61 C15.167847,11.5417439 15.0223875,11.2949036 15.08,11.05 L15.63,9 C15.6580533,8.88313454 15.7326905,8.78283079 15.8365726,8.72239033 C15.9404546,8.66194987 16.0645391,8.64663373 16.18,8.68 L16.19,8.69 Z" id="LM_detail_red2" fill="#393939"></path>
<path d="M8.68,15.62 L8.98,14.07 L9.55,12.55 C9.57831973,12.4327928 9.65249325,12.3318542 9.75588978,12.2698163 C9.85928631,12.2077784 9.98325491,12.1898316 10.1,12.22 L12.16,12.77 C12.4015851,12.8381001 12.5439801,13.0872913 12.48,13.33 L11.87,14.77 L11.65,16.4 C11.6216803,16.5172072 11.5475067,16.6181458 11.4441102,16.6801837 C11.3407137,16.7422216 11.2167451,16.7601684 11.1,16.73 L9.1,16.18 C8.85841494,16.1118999 8.71601994,15.8627087 8.78,15.62 L8.68,15.62 Z" id="LM_detail_red1" fill="#393939"></path>
</g>
</g>
</g>
</g>
<circle id="LM_detail_2" data-name="LM detail 2" cx="50.32" cy="137.11" r="2.24" style="fill: #9a9a9a"/>
<circle id="LM_detail_1" data-name="LM detail 1" cx="21.66" cy="86.59" r="2.24" style="fill: #9a9a9a"/>
<g id="hole">
<g>
<image width="38" height="38" transform="translate(44)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAAsSAAALEgHS3X78AAACRklEQVRYR9WYPXLbMBBGHzgpxRwhTJ3ER0gukMauUvl0btIlhU9gdSkzQ9dWbmBTtTYFdiUA/BGh0ILyzWBAUiTx+C0JYdeJCDlyzrlgdwU02pu2wEb7vSR3IMDNvUahUpgGuNHetAF+aG/aA+dAzoJzztV4gI/EMHOdM+AW2IhIxwxNwqlbNfAZuMXDpTBhmE3pTQ24Be6ANdAdc/HN2A+JW7d4wJphmFTpOTX+Pu/wD7YCWufcpIuDzinYF2K36t6Jp6kjdvFhFFBEooaH+ArcA8/ADh+mJdtO732vY9Uph4iQgjngCviuFx8b5F/bs451hUYxbBWxauCDtqXCOKXp8UbC+cLxp16qvTAS3lLhTJuF9xNBeC2sK84bzlQ2bYXzJ5VOtA1+5n/PvHnsNdT7twmdswmyhEKDGltchF9rKcdMPYMMrjSYyRGwVJQPaaiIpSJek5V0MHrv4D9w7pK0Bf5oT5UeKCghWeJXyQEZvfQ8uljnTHuD7J0r7Zgp4gg/iNKAvQgaXOnQRh+DZWWVbtgPT5RzsJfvhs49apuV8C4sy8jiyF38Mj0AfAt8A37zOinhbLCh7KvjfOHd4d/xO2AtA4l1BKcfx/4CDuFdWh0+4/+l/aARvVqJiHTOuQfd3bJsOULwIGu8AS3wZFNHqtEq00QhB/LXfcIJlabRKpM62HKYnLccsiPrQxlwOlgIlVWjyy0eGlhazbTjcKRwSEZ1cxYcRLXgIeca4Fq3f7JAyRUy4EIlRWuYdo5cKNNJcOfSX2jmA7RYwAeRAAAAAElFTkSuQmCC" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<circle id="LM_red-2" data-name="LM red-2" cx="62.96" cy="18.95" r="17.06" style="fill: #d42715"/>
</g>
<g id="LM_details_in_red" data-name="LM details in red">
<circle id="LM_detail_red_hole4" data-name="LM detail red hole4" cx="59.9" cy="30.01" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole3" data-name="LM detail red hole3" cx="51.75" cy="15.89" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole2" data-name="LM detail red hole2" cx="65.87" cy="7.74" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole1" data-name="LM detail red hole1" cx="74.02" cy="21.86" r="3.79" style="fill: #393939"/>
<path id="LM_detail_hole" data-name="LM detail hole" d="M64.2,16.41a.72.72,0,0,1-.55-.91c.21-.72.36-1.33.36-1.33s-.17-.35-1.27-.64-1.35-.06-1.35-.06L61,14.8s-.16.72-.81.54L59,15s-.4.13-.6,1.06a3.44,3.44,0,0,0-.06,1.43l1.25.33a.68.68,0,0,1,.46.81c-.16.61-.33,1.21-.33,1.21s.12.3,1.2.62,1.42.09,1.42.09l.32-1.22s.26-.76,1-.59q.6.17,1.2.39a2.92,2.92,0,0,0,.7-2.25C64.91,16.65,64.2,16.41,64.2,16.41Z" transform="translate(0.98 1.9)" style="fill: #1f1f1f"/>
<path id="LM_detail_red4" data-name="LM detail red4" d="M61.64,24.23,60.09,24l-1.53-.57a.46.46,0,0,1-.33-.56h0l.55-2.05a.46.46,0,0,1,.56-.32l1.45.6,1.63.22a.46.46,0,0,1,.33.56h0l-.55,2.05a.44.44,0,0,1-.55.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red3" data-name="LM detail red3" d="M69.15,17.3l-.26,1.55-.57,1.52a.45.45,0,0,1-.55.33h0l-2.06-.55a.46.46,0,0,1-.32-.56L66,18.15l.22-1.63a.45.45,0,0,1,.55-.33h0l2,.55a.46.46,0,0,1,.32.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red2" data-name="LM detail red2" d="M62.21,9.79l1.55.25,1.53.57a.46.46,0,0,1,.33.55h0l-.55,2.05a.46.46,0,0,1-.56.32l-1.45-.6-1.63-.22a.47.47,0,0,1-.33-.56h0l.55-2.05a.44.44,0,0,1,.55-.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red1" data-name="LM detail red1" d="M54.7,16.72,55,15.17l.57-1.52a.45.45,0,0,1,.55-.33h0l2.06.55a.46.46,0,0,1,.32.56l-.61,1.44-.22,1.63a.45.45,0,0,1-.55.33h0l-2-.55a.46.46,0,0,1-.32-.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,94 +1,79 @@
namespace pxsim {
export const LARGE_MOTOR_SVG = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 82 156">
<defs>
<clipPath id="clip-path" transform="translate(0.98 1.9)">
<path d="M79,17.05A17.07,17.07,0,0,1,64.92,33.86l.36.39V70c0,.42-.14.4-.39.68L54,81.22v10l.75.78v.79h6.79a4,4,0,0,1,4,4v25.82a4,4,0,0,1-4,4H54.75v8.18A5.79,5.79,0,0,1,49,140.61h-6.5v7.57a4,4,0,0,1-2.9,3.84v1a.6.6,0,0,1-.6.6H12.69a.6.6,0,0,1-.6-.6h0v-1.29a4,4,0,0,1-2.17-3.55v-7.57H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59l13.68.1,0-11.8H26a4,4,0,0,1-4-4V39.79a4,4,0,0,1,4-4h6.78l0-11.77c0-.84.15-.84.46-1.14l10.41-10.1.22-.19a1.53,1.53,0,0,1,1.59.23A17.07,17.07,0,0,1,79,17.05Z" style="fill: none"/>
</clipPath>
<clipPath id="clip-path-2" transform="translate(0.98 1.9)">
<path d="M49,140.61H6.3a5.78,5.78,0,0,1-5.78-5.79h0V105.18C10.89,91.12,18.65,81.32,18.65,81.32h.59s19.46.14,23.87.14a2.27,2.27,0,0,1,2.37,1L54.75,92v42.79A5.79,5.79,0,0,1,49,140.61Z" style="fill: none"/>
</clipPath>
<clipPath id="clip-path-3" transform="translate(0.98 1.9)">
<path d="M43.18,135.24H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.21C15,95.94,21.86,86.8,21.86,86.8H43.18A5.78,5.78,0,0,1,49,92.58h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" style="fill: none"/>
</clipPath>
</defs>
<title>Large Motor</title>
<g style="isolation: isolate">
<g id="e13b39e7-895d-4931-9be9-7aecaf709784">
<g style="clip-path: url(#clip-path)">
<g id="Large_Motor" data-name="Large Motor">
<path id="LM_back2" data-name="LM back2" d="M39,153.62H12.69a.6.6,0,0,1-.6-.6h0v-5.3a.6.6,0,0,1,.6-.6H39a.6.6,0,0,1,.6.6V153A.6.6,0,0,1,39,153.62Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<g>
<image width="36" height="20" transform="translate(9 136)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAACXBIWXMAAAsSAAALEgHS3X78AAAAp0lEQVRIS+3WsW3DMBBG4Y+GSmcGp/cAHsuzeIasFPdWVpD6c0FKcBWwOxV8wIEgSIAPvOL+EhFKKcUBiIiAgjO+25rJildErJMqdMdVlcwg8MQDv5P6Q1fc5ErRujW1TfmoLPa3T//dymJI9TKkehlSvQypXoZUL5vUNhAz2R1Oao75w9IOMmpRHVZqSpjxo3KRw+YwQ2lx+EsVykqfK+aIWGhSR+MNDy9ID5XUCOsAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_back1-2" data-name="LM back1-2" d="M41.86,152.17H10.53a.6.6,0,0,1-.6-.6v-14.7a.6.6,0,0,1,.6-.6H41.86a.6.6,0,0,1,.6.6h0v14.7A.6.6,0,0,1,41.86,152.17Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_rightside" data-name="LM rightside">
<path id="LM_rightside5" data-name="LM rightside5" d="M33.08,69.61H27.47A5.45,5.45,0,0,1,22,64.15h0V41.25a5.45,5.45,0,0,1,5.46-5.46h5.61a5.46,5.46,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,33.08,69.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<circle id="LM_rightside4" data-name="LM rightside4" cx="28.3" cy="66.21" r="3.79" style="fill: #fff"/>
<circle id="LM_rightside3" data-name="LM rightside3" cx="28.3" cy="43" r="3.79" style="fill: #fff"/>
<path id="LM_rightside2" data-name="LM rightside2" d="M24.4,59.69A4.16,4.16,0,0,1,26.74,59a5.23,5.23,0,0,1,3,.71c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.85-1.23-.46l-1,.58s-.36.19-.36-.33V55s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.39-.29-1.32-.29-1.32H29.1s-.73,0-.73-.65v-1.3s-.23-.36-1.17-.3a3.56,3.56,0,0,0-1.4.3v1.3a.66.66,0,0,1-.66.65c-.63,0-1.26,0-1.26,0s-.25.19-.29,1.32.29,1.39.29,1.39h1.26s.8.05.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.41-.82.46,0,1.8,0,1.8S23.67,60.12,24.4,59.69Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
<path id="LM_rightside1" data-name="LM rightside1" d="M31.25,47.89a.84.84,0,0,1-1,.68.85.85,0,0,1-.24-.09,6.63,6.63,0,0,0-2.85-.77,5.11,5.11,0,0,0-2.77.77c-.83.4-1.07-.59-1.07-.59V46.13a.72.72,0,0,1,.76-.66.67.67,0,0,1,.31.1,5.79,5.79,0,0,0,2.77.84,7.12,7.12,0,0,0,2.85-.84s1.18-.24,1.2.56S31.25,47.89,31.25,47.89Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
</g>
<g>
<image width="36" height="76" transform="translate(32 12)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAACXBIWXMAAAsSAAALEgHS3X78AAACAElEQVRoQ+3avVHDMBiA4VdcypgREmo4RggLpKKHAZiIAWgoKZggrEAGCBsQpxeFpNgJ/vkkK5YLvXe6g2Cb53zE9oVPaa3xSSmlALTvjh4pn2MrpQpgab/dAYdL4MQoC3oAnuxLH8AW2Gmty9YdAxKhaqAXYAUozJnaAm/AJiZs1rfBGegBKOyP7oAFMLfbRYN1ojpAYM7WtX3dbR8F1orqAdVz27n9BsMaUR4gV1yY1vpkYX7BGvgE9oD2WL/AO3CPfROFrKs6MOAMnVcAt3b57lsV6QzV194eYw0UfWelacUGRYFdAjQYNsPcy54xV+rwv4P/Bb8jZ5gr8oK4IFcQzF2nVOdWw/KG9d77IuUFGwsFHrAxUSCEjY0CASwFCnpgqVDQAUuJghZYahQY2Ao4YJ77v08eXRJWUHvenwoKaneVKaGOZZS0jJKWUdIySlpGScsoaRklLaOkZZS0jJKWUdIySlpGScsoaRklLaOkTQml3RdTQZXAD+bD2EmgSuALMwmyg/SoEtgAr9RGU1KiGkGQDtUKgjSoThCMj+oFwbgoEQjGQ4lBMA7KCwSXR3mDoPonpBsFccWYUwgCgUEdMAN/YDBzzKjJvG0nQe7W4Q2CCnFDhVgCj1TznCHtGDDVqLTWxylXW4wzdWDA/GfjnOcZMijddGBhouHTsfsDst/cEY24RzwAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level4-2" data-name="LM level4-2" d="M64.91,70.7,51.5,83.63,32.93,83,32.76,24c0-.84.16-.84.46-1.13l10.42-10.1.21-.19c.59-.4,2,.11,2,.95L65.29,34.25V70C65.3,70.44,65.16,70.43,64.91,70.7Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g>
<image width="25" height="27" transform="translate(32 69)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAACXBIWXMAAAsSAAALEgHS3X78AAABYUlEQVRIS+2WvVXDMBRG7/NxGVf0CRVFchghWSAVA2QAxmEGGgZgguzgHlPTELv/KCSD/BMs2wkV9xwf2/LPlZ70JJkk2piZdQojUd8PAWuXm1kGrIBF3wcDVEAhqWw/aIi8ZAcccLKxFMAzcGzL0voikDwCWyBjPGt8JMysKfMtMuAeeAE+Ac04TsArsAcySUj6blGGq82aaS0JyXARqYDCzHJJSnzItrh+ucW1bi4ZsCQYUAmu0w9M75dzNCqc4KxLLivpkPjzJcL1Kwl/xL9oMnXC1lkdw6SBk+IyOPf3Qz9Z8DOzD73bIAXegCfiloUV8ABs/HV07qWSKjPLiSP3xwY3m+yIlKVwflXsofSVeseFHCJlKSPxlTqZ2TEoHpSNFtVIKsfIJotgnGyWCHplW3pG8GwRdGQVbqXu35zMJZAVONEdgayzr5uL33wugBvgQ1IFVxDVmJmF+Xk1UZsvIeCPQjWq5BoAAAAASUVORK5CYII=" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level3-2" data-name="LM level3-2" d="M54,92V74.7a2.19,2.19,0,0,0-.3-1.12c-.28-.27-3.52-3.62-3.52-3.62a1.55,1.55,0,0,0-1.16-.4c-.75,0-11.62,0-11.62,0L33,74.26v8l10.66.57Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_leftside" data-name="LM leftside">
<path id="LM_leftside5" data-name="LM leftside5" d="M60.08,126.64H54.47A5.45,5.45,0,0,1,49,121.18h0V98.28a5.46,5.46,0,0,1,5.46-5.46h5.61a5.47,5.47,0,0,1,5.46,5.46v22.9A5.45,5.45,0,0,1,60.08,126.64Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
<circle id="LM_leftside4" data-name="LM leftside4" cx="61.67" cy="123.24" r="3.79" style="fill: #fff"/>
<circle id="LM_leftside3" data-name="LM leftside3" cx="61.67" cy="100.03" r="3.79" style="fill: #fff"/>
<path id="LM_leftside2" data-name="LM leftside2" d="M57.77,116.72a4.15,4.15,0,0,1,2.34-.7,5.14,5.14,0,0,1,3,.7c1.25.93,1.23-.1,1.23-.1v-1.8c0-.45-.56-.84-1.23-.46l-1,.58s-.36.19-.36-.33V112s0-.79.73-.77,1.38,0,1.38,0,.29-.25.29-1.38-.29-1.33-.29-1.33H62.47s-.73,0-.73-.64v-1.3s-.23-.36-1.17-.31a3.57,3.57,0,0,0-1.4.31v1.3a.66.66,0,0,1-.66.64H57.25s-.25.2-.29,1.33.29,1.38.29,1.38h1.26s.8,0,.82.77,0,2.62,0,2.62,0,.51-.34.33l-1.21-.58s-.83-.4-.82.46,0,1.8,0,1.8S57,117.16,57.77,116.72Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
<path id="LM_leftside1" data-name="LM leftside1" d="M64.62,104.92a.83.83,0,0,1-1,.68.68.68,0,0,1-.24-.08,6.46,6.46,0,0,0-2.85-.77,5,5,0,0,0-2.77.77c-.83.4-1.07-.6-1.07-.6v-1.76a.71.71,0,0,1,.76-.65.8.8,0,0,1,.31.09,5.79,5.79,0,0,0,2.77.84,7,7,0,0,0,2.85-.84s1.18-.24,1.2.56S64.62,104.92,64.62,104.92Z" transform="translate(0.98 1.9)" style="fill: #fff"/>
</g>
<g>
<image width="58" height="64" transform="translate(0 81)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAACXBIWXMAAAsSAAALEgHS3X78AAACFElEQVRoQ+2bQY7TMBSGvxcqsaFbJDbDrEEcYeYCcwYOwIlYsWLDjg0nGG6A1ANkbgCNhGb1WNgBpxPbaUjT+smf5E3lxPlq/25S5YmqshQiIrk+S6EzLlxmHDOKiGyB18CLXN8F6IAW6I6RXkTWi94C73HCp6YFvgI7oFXVfaY/sIBsIPoBuAG26SMWoZ/ZHfAZuJ8ivMl1SHEgess6ouDGeQtc4WMjInlhVZ3VcAPeAd+AX4Ceqf0EvgDv8Cs11hpm4Hfda1xG11q6MbbAG9+S1zFLliMGWIHBF++jNcrRmfUnu8Gd/Bo32Lnp9w4gnt+jZM+4IU0hKzxZ9sJyGiMpPFmWy8ppiqjwJNkLzWmK/no7oBWRnapqdje+8Jym2BLcdEDmp6eQnKYYrMDczJaS00lEZQvMaZZR2YJzmuSJrIGcRhmbWVM5DRnIWsxpyF9ZqzkNacB2TkP6mTWb05DGek5DGtxfn6aXb0+Du1G+wrgo/Mus2aUbknsQMEWVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUqVtUovq8le5TLwanBvbj4A2VKRwtjjvLr+g2fAb1wFxUvgFfB89NCy2APfgU/AD1V9BNio6l5E7oOOpb9u0It+5KC4aQNwINyxTonZqWiJVHENytNk3eLBU9ERqc97UovnXwArGj2U8vx34WFJ/AG0vvY6LSeZMAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_level2_grey-2" data-name="LM level2 grey-2" d="M49,140.61H6.31a5.78,5.78,0,0,1-5.78-5.78h0V105.19C10.89,91.13,18.65,81.32,18.65,81.32h.6s19.46.15,23.86.15a2.29,2.29,0,0,1,2.38,1L54.75,92v42.8A5.78,5.78,0,0,1,49,140.61Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_total" data-name="LM total">
<g id="LM_whitepart" data-name="LM whitepart">
<g style="clip-path: url(#clip-path-2)">
<g id="LM_whitepart_combined" data-name="LM whitepart combined">
<path id="LM_whitepart_top" data-name="LM whitepart top" d="M43.48,141l-7.15-7.37L12.54,102.56V87.7L-.52,103.84v31.22l1,7.69Z" transform="translate(0.98 1.9)" style="fill: #f1f1f1"/>
export const LARGE_MOTOR_SVG = `<?xml version="1.0" encoding="UTF-8"?>
<svg width="82px" height="156px" viewBox="0 0 82 156" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<title>Large Motor</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-66.000000, -54.000000)">
<g id="Large-Motor" transform="translate(66.000000, 54.000000)">
<path d="M39.98,155.52 L13.67,155.52 C13.3386292,155.52 13.07,155.251371 13.07,154.92 L13.07,149.62 C13.07,149.288629 13.3386292,149.02 13.67,149.02 L39.98,149.02 C40.3113708,149.02 40.58,149.288629 40.58,149.62 L40.58,154.9 C40.5854219,155.062566 40.5246096,155.220368 40.4114947,155.337253 C40.2983799,155.454138 40.1426565,155.52009 39.98,155.52 Z" id="LM_back2" fill="#A8AAA8" fill-rule="nonzero"></path>
<g id="Group" transform="translate(9.000000, 136.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAVCAYAAADB5CeuAAAAAXNSR0IArs4c6QAAAMRJREFUSA3tlrERwjAMRW2OEmYgPQMwFrMwAytBT1iB9OY/x05J1IAopLtv2Y5yevfPhXIpJWVF+oMQSwEDmJ00tKzkFpM6P8Q1bbUZpLN0lLwcw6G7dJFuQOEUQCfJE0rtK0sCigCmq144LIshG4fmqy0DatWiVhBOhVNWB6x18abCKasD1rr+puocY/3pS3ULA1DMMU/pJfHBQ/SGAZY6JYzKVw6Kw5x+vnYGcsptHN5rDxCzlUfg0CgWHJuhPCg+9XwDDy9ID0K8XgsAAAAASUVORK5CYII="></image>
<path d="M33.84,18.07 L2.51,18.07 C2.17862915,18.07 1.91,17.8013708 1.91,17.47 L1.91,2.77 C1.91,2.43862915 2.17862915,2.17 2.51,2.17 L33.84,2.17 C34.1713708,2.17 34.44,2.43862915 34.44,2.77 L34.44,17.47 C34.44,17.8013708 34.1713708,18.07 33.84,18.07 Z" id="LM_back1-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_rightside" transform="translate(22.000000, 37.000000)" fill-rule="nonzero">
<path d="M12.06,34.51 L6.45,34.51 C4.99937339,34.5153259 3.60647912,33.9421088 2.57978624,32.9172929 C1.55309337,31.892477 0.977328505,30.5006339 0.98,29.05 L0.98,6.15 C0.977339027,4.70110385 1.55173283,3.31078487 2.57625885,2.28625885 C3.60078487,1.26173283 4.99110385,0.687339027 6.44,0.69 L12.05,0.69 C15.0654747,0.69 17.51,3.13452527 17.51,6.15 L17.51,29.05 C17.5126553,30.4971617 16.939633,31.8859609 15.9172718,32.910198 C14.8949106,33.9344351 13.5071641,34.5100024 12.06,34.51 Z" id="LM_rightside5" fill="#A8AAA8"></path>
<circle id="LM_rightside4" fill="#FFFFFF" cx="6.3" cy="29.21" r="3.79"></circle>
<circle id="LM_rightside3" fill="#FFFFFF" cx="6.3" cy="6" r="3.79"></circle>
<path d="M3.38,24.59 C4.07351535,24.1313154 4.88857129,23.8909784 5.72,23.9 C6.76862292,23.8298668 7.81405119,24.0772848 8.72,24.61 C9.97,25.54 9.95,24.51 9.95,24.51 L9.95,22.71 C9.95,22.26 9.39,21.86 8.72,22.25 L7.72,22.83 C7.72,22.83 7.36,23.02 7.36,22.5 L7.36,19.9 C7.36,19.9 7.36,19.11 8.09,19.13 C8.82,19.15 9.47,19.13 9.47,19.13 C9.47,19.13 9.76,18.88 9.76,17.74 C9.76,16.6 9.47,16.42 9.47,16.42 L8.08,16.42 C8.08,16.42 7.35,16.42 7.35,15.77 L7.35,14.47 C7.35,14.47 7.12,14.11 6.18,14.17 C5.6978322,14.1741563 5.22153417,14.2762201 4.78,14.47 L4.78,15.77 C4.77453579,16.1305967 4.48063814,16.4200414 4.12,16.42 C3.49,16.42 2.86,16.42 2.86,16.42 C2.86,16.42 2.61,16.61 2.57,17.74 C2.53,18.87 2.86,19.13 2.86,19.13 L4.12,19.13 C4.12,19.13 4.92,19.18 4.94,19.9 C4.96,20.62 4.94,22.52 4.94,22.52 C4.94,22.52 4.94,23.03 4.6,22.85 L3.39,22.27 C3.39,22.27 2.56,21.86 2.57,22.73 C2.58,23.6 2.57,24.53 2.57,24.53 C2.57,24.53 2.65,25.02 3.38,24.59 Z" id="LM_rightside2" fill="#FFFFFF"></path>
<path d="M10.23,12.79 C10.1913976,13.0147775 10.0630557,13.2141964 9.87446015,13.3424414 C9.68586455,13.4706864 9.453229,13.5167322 9.23,13.47 C9.14591061,13.4523039 9.06499079,13.421959 8.99,13.38 C8.1099436,12.9124008 7.1357966,12.6492102 6.14,12.61 C5.162003,12.5962776 4.20061308,12.8635231 3.37,13.38 C2.54,13.78 2.3,12.79 2.3,12.79 L2.3,11.03 C2.33192589,10.6400455 2.66941985,10.3469587 3.06,10.37 C3.16998614,10.3773249 3.27646607,10.4116733 3.37,10.47 C4.20732336,10.980005 5.16044012,11.2690368 6.14,11.31 C7.13850164,11.2335413 8.10964397,10.9473099 8.99,10.47 C8.99,10.47 10.17,10.23 10.19,11.03 C10.21,11.83 10.23,12.79 10.23,12.79 Z" id="LM_rightside1" fill="#FFFFFF"></path>
</g>
<g id="Group" transform="translate(32.000000, 12.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="36" height="76" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAABNCAYAAAAhOa00AAAAAXNSR0IArs4c6QAAAnlJREFUaAXtmsFRwzAQRROGI6EEwhmGEqABTtyhACqiAC4cOVBBaAEKCB0AuYf/hdbjBMcrbYTlw+7MZp3IWr98OZIn2ul6vZ7k2BTG89Evr2PGRaY5ucEzQ+55zL9EXP0HXDJUBLoCyG2EekZ8hy8B9h0/KxKSoFpA97jqJZxDSKUI9QhflAQ7RMJe2wKiUhxC2jn8BH7ENzivGFgvVA9Q4MDLMZygwUqB7YRSgISDkcoVBeuEygASuLJgnBLaHr/5NeIL/AvO+SjVP3HuE/wCHn5E7dypxwfo3JhBoaZvPKBiZ9F5bDOhR28msSrUVpLqUmXmmkn+nBiGjp1jEsuQtYHkeC8wsBQH2huMv745/A7Omdp+H6DzljGXaaogFGdkzswlgZAumAlM5qnwOCKZCsdsMIEqzPEnXRbYUFCkTAYbEioZbGioJLAaUCpYLahesJpQO8FqQwkYV5MVnM/9bxuPLjyjknG64KoSnvfHAkUtmlVlTFAEC+ZQooQWXSlNIWl3pUQJLbpSmkLS7kqJElp0pTSFpN2VEiW06EppCkm7KyVKaNGV0hSSdldKlNCiK6UpJO2ulCihRVdKU0jaXSlRQouulKaQtI9JKW7JBRsLFCtAPuD8M3YyBigCvcJZCcJ/h6tDEWgBf2DEPnOomampVCcQ4KoptROoFlQvUA0oFWhoqCSgIaGSgYaCygIaAiobiFCy3yelIPyM1uwo/b41vZqAeCVCcb1hwR+NMNxzY6lJ2HtDtBiBuHRszNSpiQTiFB0EgkA3cEarcQ0zVzWGajAUc7WHq4RSYetV1rLcb9ZZ57kFmZsznA8g3qcm64QyZSrY6Qey39wRVmjftAAAAABJRU5ErkJggg=="></image>
<path d="M33.89,60.6 L20.48,73.53 L1.91,72.9 L1.74,13.9 C1.74,13.06 1.9,13.06 2.2,12.77 L12.62,2.67 L12.83,2.48 C13.42,2.08 14.83,2.59 14.83,3.43 L34.27,24.15 L34.27,59.9 C34.28,60.34 34.14,60.33 33.89,60.6 Z" id="LM_level4-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="Group" transform="translate(32.000000, 69.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="25" height="27" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAcCAYAAAB/E6/TAAAAAXNSR0IArs4c6QAAAZhJREFUSA3tlj1SwzAQRnEmJanogYoChiOQC1BxAA7AcTgDDQfgBLlDekxNQ5LefE/WeizHGa9l07Ezny3L2n36W9lFVVVnXStk3Trvs+IdB5Rz0a0XY6X6K+ncG7zV7qByqZj7Vl0oJqAIWevNswRsrJVyeJM2XdjSIrUgL6p7kBjZWLuVQ5gJxUthcepYk3vpXfqRmOdc7eT7IT1KK+IjGxG9pzcoZyRyawx/ZiSsl0a2FahaxCnjBetyLWXvOPmaAbuUmg210AOLDgTY1NEoRGNJhwFBhT4npKFZARCW0Ouqea8GmjdqT7R/UM+k+KosYe0U8HhlbRxAZPA2EoaCkArkHfehtjFkfQP0Kb1KTRarfMqAPEl3EmV37i11DB04j+TkMdohQJwmfFJcsLBGHHpy8Ng+dupLjZlyzAWzzVC7OK6xUzsBN63mg7DRIAsuIKNzw7JBAMfAJoFOwPjcHO3gyaAeGJuEL3XyJzQLqAMrI+imDUt+t3CYatognBhM3YX0rXUMaTA7yDoKMKZCqPozkAHt/gsh4I9CsIZ80gAAAABJRU5ErkJggg=="></image>
<path d="M22.9800421,24.9 L22.98,7.6 C22.9824406,7.20649401 22.8788083,6.81960003 22.68,6.48 C22.4,6.21 19.16,2.86 19.16,2.86 C18.8448174,2.57277854 18.4252272,2.42809227 18,2.46 C17.25,2.46 6.38,2.46 6.38,2.46 L1.98,7.16 L1.98,15.16 L12.64,15.73 L22.9800421,24.9 Z" id="LM_level3-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_leftside" transform="translate(49.000000, 94.000000)" fill-rule="nonzero">
<path d="M12.06,34.54 L6.45,34.54 C4.99937339,34.5453259 3.60647912,33.9721088 2.57978624,32.9472929 C1.55309337,31.922477 0.977328505,30.5306339 0.98,29.08 L0.98,6.18 C0.98,3.16452527 3.42452527,0.72 6.44,0.72 L12.05,0.72 C15.0631921,0.725503561 17.5044964,3.16680786 17.51,6.18 L17.51,29.08 C17.5126553,30.5271617 16.939633,31.9159609 15.9172718,32.940198 C14.8949106,33.9644351 13.5071641,34.5400024 12.06,34.54 Z" id="LM_leftside5" fill="#A8AAA8"></path>
<circle id="LM_leftside4" fill="#FFFFFF" cx="12.67" cy="29.24" r="3.79"></circle>
<circle id="LM_leftside3" fill="#FFFFFF" cx="12.67" cy="6.03" r="3.79"></circle>
<path d="M9.75,24.62 C10.4421225,24.1572205 11.2574415,23.9133217 12.09,23.92 C13.1380484,23.8411302 14.1850856,24.0854388 15.09,24.62 C16.34,25.55 16.32,24.52 16.32,24.52 L16.32,22.72 C16.32,22.27 15.76,21.88 15.09,22.26 L14.09,22.84 C14.09,22.84 13.73,23.03 13.73,22.51 L13.73,19.9 C13.73,19.9 13.73,19.11 14.46,19.13 C15.19,19.15 15.84,19.13 15.84,19.13 C15.84,19.13 16.13,18.88 16.13,17.75 C16.13,16.62 15.84,16.42 15.84,16.42 L14.45,16.42 C14.45,16.42 13.72,16.42 13.72,15.78 L13.72,14.48 C13.72,14.48 13.49,14.12 12.55,14.17 C12.0671703,14.1775857 11.5908982,14.283046 11.15,14.48 L11.15,15.78 C11.1391868,16.1366743 10.8468382,16.4201639 10.49,16.42 L9.23,16.42 C9.23,16.42 8.98,16.62 8.94,17.75 C8.9,18.88 9.23,19.13 9.23,19.13 L10.49,19.13 C10.49,19.13 11.29,19.13 11.31,19.9 C11.33,20.67 11.31,22.52 11.31,22.52 C11.31,22.52 11.31,23.03 10.97,22.85 L9.76,22.27 C9.76,22.27 8.93,21.87 8.94,22.73 C8.95,23.59 8.94,24.53 8.94,24.53 C8.94,24.53 8.98,25.06 9.75,24.62 Z" id="LM_leftside2" fill="#FFFFFF"></path>
<path d="M16.6,12.82 C16.5640845,13.0461448 16.4363396,13.2474057 16.2469908,13.3761629 C16.057642,13.5049201 15.8235128,13.5497335 15.6,13.5 C15.5157002,13.4885804 15.4342916,13.4614442 15.36,13.42 C14.4821686,12.9467916 13.506699,12.6832437 12.51,12.65 C11.5311949,12.6299456 10.5680375,12.8976825 9.74,13.42 C8.91,13.82 8.67,12.82 8.67,12.82 L8.67,11.06 C8.70188656,10.6714097 9.04116607,10.3812364 9.43,10.41 C9.53837526,10.4186243 9.6438555,10.4492476 9.74,10.5 C10.5773234,11.010005 11.5304401,11.2990368 12.51,11.34 C13.5091637,11.2671668 14.4810541,10.9807149 15.36,10.5 C15.36,10.5 16.54,10.26 16.56,11.06 C16.58,11.86 16.6,12.82 16.6,12.82 Z" id="LM_leftside1" fill="#FFFFFF"></path>
</g>
<g id="Group" transform="translate(0.000000, 81.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="58" height="64" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAABBCAYAAABvnNwUAAAAAXNSR0IArs4c6QAAAqRJREFUaAXtm01OwzAQhSlUYgNbJDalaxBHgAtwBg7AiVixYsOODScoN0DqAcoNoJUQq/CecaK64zhOm7T1yCNNf+zUns/P4xjkDIqiOOjKBrCu2mpqB3G3Dnywxm+8cYDzFBUX8BPvBd0WLtDcDL5oA90JrAW9Ref3cAL3bQR9hU/hMwDPYzrcGHYJ9AEd3sCpcN9WKkvYZ/gkBni4SVQroFR2G6AMmf1cwUdwkzaIpRmYObuO2w7v8P4G/4ZzwdiFf6HfF/g13MzUOp5DXNDaMIpcdcdw5ui2pi668hpVvrQenFlrwaLh6A684XVb6Ay8TS1vD61z1jZGNanqGM7Odm0cfK4ZxhCjN39bwVpQNsqVd5sL0j9F+LUROBoWoM50Qb/B/AjH1VttEDga1sJFLQS9ocQ1XAscBWun777laQidwIzXbD4Q/xS3o6JxNbag+5qnTcAjXFDt1YOwAE0hT0PAzp0iCItWOB1SyNMQcFVXC2unb0p5WkHVffDCJpyndZymXMAqyNNaYAGLK1Xl6TK5A6sxT72wWvNUwGrOUwGLArV56sBqz1MHFl/4r0/+Ic4NBBVWa1yNuVHmhlk1KBUsbz3OhpkVGq2E1cgmmDKsGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjKysGBIlBVlZJUIKjFJZnu3XaA4XYXly8xMe9WxMQiNCHnKRz9gRXn/gfILiDH4OP4anbgR9hz/BP3D69pdAQ3yY41zFhF+spX7coAR9BI/zrIA5XL0CTNl5ziJVmyFw71NczuNp9uQMQasDyQkSm9PjFHA1dgeWlfYA2Op1SX0HqLMKl8EL2LJC4/sftL72OnfR538AAAAASUVORK5CYII="></image>
<path d="M49.98,61.51 L7.29,61.51 C4.09779415,61.51 1.51,58.9222059 1.51,55.73 L1.51,26.09 C11.87,12.03 19.63,2.22 19.63,2.22 L20.23,2.22 C20.23,2.22 39.69,2.37 44.09,2.37 C45.013529,2.18179526 45.9580478,2.5786519 46.47,3.37 L55.73,12.9 L55.73,55.7 C55.7379772,57.2329575 55.1366519,58.7062958 54.0583133,59.7958867 C52.9799747,60.8854775 51.5129577,61.5020641 49.98,61.51 Z" id="LM_level2_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_total">
<g id="LM_whitepart" transform="translate(0.000000, 89.000000)" fill="#F1F1F1" fill-rule="nonzero">
<g id="LM_whitepart_combined">
<polygon id="LM_whitepart_top" points="44.46 53.9 37.31 46.53 13.52 15.46 13.52 0.6 0.46 16.74 0.46 47.96 1.46 55.65"></polygon>
</g>
</g>
</g>
</g>
<g>
<image width="47" height="52" transform="translate(5 87)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAACXBIWXMAAAsSAAALEgHS3X78AAABnElEQVRoQ+2azXHCMBBG3zIccQuBM5MWoIHUkAJSUQrIJQWkAlIJ6SDYd+UgGWTjHxQHr5TRm9HFIzz75G8Z8KwYY5iKiMjYnr/AdBQrUwVEpADWwGps70Qq4GiMKf2LkwRc8XvgGStxT47AG3DwJZb9+4fxin8BdkAx/InJbHFPWUQuEsaY4IUt9gn4AE6AmWl9A+/AIy49CwJxDbvBxmaOk/cpgAe8fgsWwN5k69acxdc0vvGCBFzud9jT39C6mQY3C7Sado/O6V9xk4By7ge5SQD93PcyKhBj7n0GBWLNvU+vQArFQ49AzE3bpu8JRNu0ba4EYm/aNg2BVHLvcxZIKfc+/hNIJvc+C0gv9z4LF501iUWnpo7QCvtHIaniodkDycTGZ/THXOxkAW2ygDZZQJssoE0W0CYLaJMFtMkC2mQBbbKANv9K4PdDE/PSqLMWqIAvoDEJEiElts7qfEV59iFknbD1PQFFPbexBDDGlCJy4EJs70hL4BN4pW/cpiVRcf/5nxA6Z4WgY+BpxgmsEDqntWDixFYM/ACNRtJx4q2GRAAAAABJRU5ErkJggg==" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<path id="LM_top_grey-2" data-name="LM top grey-2" d="M43.18,135.54H12.09a5.78,5.78,0,0,1-5.79-5.78h0V107.51C15,96.24,21.86,87.1,21.86,87.1H43.18A5.78,5.78,0,0,1,49,92.88h0v36.88a5.78,5.78,0,0,1-5.78,5.78Z" transform="translate(0.98 1.9)" style="fill: #a8aaa8"/>
</g>
<g id="LM_top" data-name="LM top">
<g style="clip-path: url(#clip-path-3)">
<g id="LM_top_total" data-name="LM top total">
<path id="LM_top_lines" data-name="LM top lines" d="M18.6,112.05v27.47a1.08,1.08,0,0,1-1.12,1,1.06,1.06,0,0,1-1.05-1V112.05A1.09,1.09,0,0,1,18.6,112Zm3.61,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.62,0v27.47a1.09,1.09,0,1,1-2.17,0V112.05a1.09,1.09,0,1,1,2.17,0Zm3.61,0v27.47a1.09,1.09,0,0,1-2.17.07V112.05a1.09,1.09,0,0,1,2.17-.07Zm3.62,0v27.47A1.1,1.1,0,0,1,32,140.64a1.08,1.08,0,0,1-1.11-1V112.05a1.09,1.09,0,0,1,2.17-.07Z" transform="translate(0.98 1.9)" style="fill: #6a6a6a"/>
<g id="Group" transform="translate(5.000000, 87.000000)">
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="0" y="0" width="47" height="52" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAA1CAYAAAAHz2g0AAAAAXNSR0IArs4c6QAAAhhJREFUaAXtWttRwzAQxAyfpAWSb4YWoAFqoIBURAH8UAAVhEpMBxD+za6xFMmyQcqNLWnmbmbHj1in3btTYjvXdF13IbUGJvURMx5cA7LNxLkYX/YacN/gYAtc25PL7HzDbQu+R9e9SMBA/gEOnwCKWNJaOH8BDq6Iq3NndMjv4eMeYCaWtFs477OMuU8iWEKpgCOSfQTegC+AtbkGPjHPK3AH9NVziZ0kg3ou2B3Aslkj8pjGGgN3A9j1liwAg+mE6SSWLhtMEZj3jZckYKh7Rp3R3wGeMxyvbtECBvL8xuGi5TZH9IMARQnIXPcBafdElIAh2jnr3uXs7f8roMS6dxX8KaDUuo8SUAN5CpnMQMmL1o3+rAB8kPvHasxz9jjIQOmLdqzEE1BL3bsirICa6n5SAE5WU/eBgNrq3hMwlA4fB3Pc37tczto3a4APCHxQKOIOM0WJEcAx2e/tU4iba10B5lxVWxWQO12aAc2AMAJaQsIAiodrBsQhFDrQDAgDKB6uGRCHUOhAMyAMoHi4ZkAcQqEDzYAwgOLhmgFxCIUO3Azwn/YazONpBLAT5APwOkEKVEN+5Em+v8Y+CRjfyOXofeDksWBPBnszyHNj+jv6bhUcHPGO9IAPjK3dA2Hmndsy8u/AM3DqVMGBbbcZiWCKtkAp1oJI0CtEckHD0/CqneRtRwgvzGwMaNCtRU6BgMxEk6f/AY1G0nHf2MzkAAAAAElFTkSuQmCC"></image>
<path d="M39.16,50.44 L8.07,50.44 C6.5353168,50.4426552 5.06258085,49.834865 3.97645681,48.7506168 C2.89033276,47.6663686 2.2799977,46.1946855 2.28,44.66 L2.28,22.41 C10.98,11.14 17.84,2 17.84,2 L39.16,2 C40.6998701,1.9893432 42.1803327,2.59359794 43.2729596,3.67871541 C44.3655865,4.76383288 44.9800369,6.24009301 44.98,7.78 L44.98,44.66 C44.98,46.1929513 44.3710375,47.6631169 43.2870772,48.7470772 C42.2031169,49.8310375 40.7329513,50.44 39.2,50.44 L39.16,50.44 Z" id="LM_top_grey-2" fill="#A8AAA8" fill-rule="nonzero"></path>
</g>
<g id="LM_top" transform="translate(17.000000, 112.000000)" fill="#6A6A6A" fill-rule="nonzero">
<g id="LM_top_total">
<path d="M2.58,1.95 L2.58,29.42 C2.53732346,30.0007732 2.04187943,30.443134 1.46,30.42 C0.901094365,30.4156223 0.441619994,29.9780276 0.41,29.42 L0.41,1.95 C0.449349984,1.38861093 0.909606462,0.949468178 1.47222361,0.93650465 C2.03484076,0.923541121 2.51483504,1.34101911 2.58,1.9 L2.58,1.95 Z M6.19,1.95 L6.19,29.42 C6.2296472,29.8325035 6.03195189,30.231808 5.67986701,30.4503653 C5.32778212,30.6689226 4.88221788,30.6689226 4.53013299,30.4503653 C4.17804811,30.231808 3.9803528,29.8325035 4.02,29.42 L4.02,1.95 C3.9803528,1.53749648 4.17804811,1.138192 4.53013299,0.919634704 C4.88221788,0.701077408 5.32778212,0.701077408 5.67986701,0.919634704 C6.03195189,1.138192 6.2296472,1.53749648 6.19,1.95 Z M9.81,1.95 L9.81,29.42 C9.8496472,29.8325035 9.65195189,30.231808 9.29986701,30.4503653 C8.94778212,30.6689226 8.50221788,30.6689226 8.15013299,30.4503653 C7.79804811,30.231808 7.6003528,29.8325035 7.64,29.42 L7.64,1.95 C7.6003528,1.53749648 7.79804811,1.138192 8.15013299,0.919634704 C8.50221788,0.701077408 8.94778212,0.701077408 9.29986701,0.919634704 C9.65195189,1.138192 9.8496472,1.53749648 9.81,1.95 Z M13.42,1.95 L13.42,29.42 C13.3873113,29.9829764 12.9306072,30.4280683 12.3669758,30.44625 C11.8033444,30.4644316 11.318904,30.0496992 11.25,29.49 L11.25,1.95 C11.2826887,1.38702361 11.7393928,0.941931677 12.3030242,0.923750018 C12.8666556,0.905568359 13.351096,1.3203008 13.42,1.88 L13.42,1.95 Z M17.04,1.95 L17.04,29.42 C17.0513034,30.0199642 16.5796777,30.5182857 15.98,30.54 C15.401933,30.5576338 14.9125708,30.1167669 14.87,29.54 L14.87,1.95 C14.9026887,1.38702361 15.3593928,0.941931677 15.9230242,0.923750018 C16.4866556,0.905568359 16.971096,1.3203008 17.04,1.88 L17.04,1.95 Z" id="LM_top_lines"></path>
</g>
</g>
<circle id="LM_detail_2" fill="#9A9A9A" fill-rule="nonzero" cx="50.32" cy="137.11" r="2.24"></circle>
<image id="Bitmap" opacity="0.3" style="mix-blend-mode: multiply;" x="44" y="0" width="38" height="38" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAAAXNSR0IArs4c6QAAAu1JREFUWAnNmD1y1EAQhb1bhJgjsMT8HAEuQGJHRJyOhAwCTmAyQqpMvOsbYDtGvE/Mm+oZaWUtaHfoqt75n/70WquSZtV13dkhtpKF+Y9V38gpbfeq7OSU2RTnsEBauZq7JkHVMIBdyiltgH2SU9oy8CGQs+AEdq4oALyQR5gaFpgMQiOZga/V3gnwzgNT5SRcUguw1/L3cuCAjGlcqV1bV3UYGLgP8q/yu4dUfFRtkpuVWoABCOgYTF6XKvUc1nFhT+VcGH6tGJMqjiqXwN5og6gWAZYwUkqareLV3jRr4Cy6FgHxVv5F/lP+S06alnT2ZG9iEOs8Mrheg5GOV/KPchYvCTS2FzGIRcw+iwajXKszGqo9T0792DYdz6SiYKLTeav62JUeo49Yo+nt06rBU6ezvkin9yUsFsxp5a99ynQqXGFkbSOHI9s6PWgZuJQ/k6NiCwOsAIzK+QHZAgxBLNAmCVb8W1spZjFQrhDIyrUGMyAcmQW4AbFnNigLFuByrlXP1A3AiB1Z+nuuoG0AFUMWLL7n4oSWdd77buSUvXJFB52NrFPcnTy/4qNc7GBCSyuEAq7oaEmWYmeBfM/ljsZwBYfhYCoGGkAOMmi4wcCJ4RAm3/t6ZeqFWqeKB7aa1EpBBIKDsreo3A/14LM+eP8sX+zXX2QZrN/Zb51q/J+v6QHwiSDfyb/Lj/FJyC0Tfe/3A0xOq9b0hrynSi8Xv5X3xxOCGdxOBZwmcFV5ger+ClN1UQOEL/5vqRyAEW1wVsIV6DX5ikEZNyhnHBs59+S/GhcPCAc5KAbgNomiammjZyVMSeclQAEXD3L6YX4OMKD8qPAZyYMnTQPlHDApyEY3aWM2B5Z3LpeqZlulGiDRIhRvHOy5Y/84aay+V7k4OahoMD4jAbS5n3bxIE3tDKX2/b40sjjaLDgW+HNNVYNQ2gC9SI3PKgG0WbnZUF44G84LKAOouw1Mu1aOI4861V43Wf4V3OSOCw7+BmjmA7QisxQnAAAAAElFTkSuQmCC"></image>
<circle id="LM_detail_1" fill="#9A9A9A" fill-rule="nonzero" cx="21.66" cy="86.59" r="2.24"></circle>
<g id="hole" transform="translate(45.000000, 1.000000)" fill-rule="nonzero">
<g id="Group" fill="#D42715">
<circle id="LM_red-2" cx="17.96" cy="17.95" r="17.06"></circle>
</g>
<g id="LM_details_in_red" transform="translate(2.000000, 2.000000)">
<circle id="LM_detail_red_hole4" fill="#393939" cx="12.9" cy="27.01" r="3.79"></circle>
<circle id="LM_detail_red_hole3" fill="#393939" cx="4.75" cy="12.89" r="3.79"></circle>
<circle id="LM_detail_red_hole2" fill="#393939" cx="18.87" cy="4.74" r="3.79"></circle>
<circle id="LM_detail_red_hole1" fill="#393939" cx="27.02" cy="18.86" r="3.79"></circle>
<path d="M18.18,15.31 C17.9816076,15.2705154 17.8089761,15.149396 17.7043432,14.9762761 C17.5997103,14.8031562 17.5727287,14.5940066 17.63,14.4 C17.84,13.68 17.99,13.07 17.99,13.07 C17.99,13.07 17.82,12.72 16.72,12.43 C15.62,12.14 15.37,12.37 15.37,12.37 L14.98,13.7 C14.98,13.7 14.82,14.42 14.17,14.24 L12.98,13.9 C12.98,13.9 12.58,14.03 12.38,14.96 C12.2599627,15.4271881 12.2395203,15.9143986 12.32,16.39 L13.57,16.72 C13.9132251,16.8260991 14.1147049,17.1808788 14.03,17.53 C13.87,18.14 13.7,18.74 13.7,18.74 C13.7,18.74 13.82,19.04 14.9,19.36 C15.98,19.68 16.32,19.45 16.32,19.45 L16.64,18.23 C16.64,18.23 16.9,17.47 17.64,17.64 C18.04,17.7533333 18.44,17.8833333 18.84,18.03 C19.3790257,17.4116231 19.6330766,16.5950309 19.54,15.78 C18.89,15.55 18.18,15.31 18.18,15.31 Z" id="LM_detail_hole" fill="#1F1F1F"></path>
<path d="M15.62,23.13 L14.07,22.9 L12.54,22.33 C12.29437,22.2663058 12.1467122,22.015735 12.21,21.77 L12.76,19.72 C12.8281001,19.4784149 13.0772913,19.3360199 13.32,19.4 L14.77,20 L16.4,20.22 C16.64563,20.2836942 16.7932878,20.534265 16.73,20.78 L16.18,22.83 C16.1519467,22.9468655 16.0773095,23.0471692 15.9734274,23.1076097 C15.8695454,23.1680501 15.7454609,23.1833663 15.63,23.15 L15.62,23.13 Z" id="LM_detail_red4" fill="#393939"></path>
<path d="M23.13,16.2 L22.87,17.75 L22.3,19.27 C22.2716803,19.3872072 22.1975067,19.4881458 22.0941102,19.5501837 C21.9907137,19.6122216 21.8667451,19.6301684 21.75,19.6 L19.69,19.05 C19.4484149,18.9818999 19.3060199,18.7327087 19.37,18.49 L19.98,17.05 L20.2,15.42 C20.2283197,15.3027928 20.3024933,15.2018542 20.4058898,15.1398163 C20.5092863,15.0777784 20.6332549,15.0598316 20.75,15.09 L22.75,15.64 C22.9915851,15.7081001 23.1339801,15.9572913 23.07,16.2 L23.13,16.2 Z" id="LM_detail_red3" fill="#393939"></path>
<path d="M16.19,8.69 L17.74,8.94 L19.27,9.51 C19.5107539,9.57376787 19.6570302,9.81756168 19.6,10.06 L19.05,12.11 C18.9818999,12.3515851 18.7327087,12.4939801 18.49,12.43 L17.04,11.83 L15.41,11.61 C15.167847,11.5417439 15.0223875,11.2949036 15.08,11.05 L15.63,9 C15.6580533,8.88313454 15.7326905,8.78283079 15.8365726,8.72239033 C15.9404546,8.66194987 16.0645391,8.64663373 16.18,8.68 L16.19,8.69 Z" id="LM_detail_red2" fill="#393939"></path>
<path d="M8.68,15.62 L8.98,14.07 L9.55,12.55 C9.57831973,12.4327928 9.65249325,12.3318542 9.75588978,12.2698163 C9.85928631,12.2077784 9.98325491,12.1898316 10.1,12.22 L12.16,12.77 C12.4015851,12.8381001 12.5439801,13.0872913 12.48,13.33 L11.87,14.77 L11.65,16.4 C11.6216803,16.5172072 11.5475067,16.6181458 11.4441102,16.6801837 C11.3407137,16.7422216 11.2167451,16.7601684 11.1,16.73 L9.1,16.18 C8.85841494,16.1118999 8.71601994,15.8627087 8.78,15.62 L8.68,15.62 Z" id="LM_detail_red1" fill="#393939"></path>
</g>
</g>
</g>
</g>
<circle id="LM_detail_2" data-name="LM detail 2" cx="50.32" cy="137.11" r="2.24" style="fill: #9a9a9a"/>
<circle id="LM_detail_1" data-name="LM detail 1" cx="21.66" cy="86.59" r="2.24" style="fill: #9a9a9a"/>
<g id="hole">
<g>
<image width="38" height="38" transform="translate(44)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAnCAYAAACMo1E1AAAACXBIWXMAAAsSAAALEgHS3X78AAACRklEQVRYR9WYPXLbMBBGHzgpxRwhTJ3ER0gukMauUvl0btIlhU9gdSkzQ9dWbmBTtTYFdiUA/BGh0ILyzWBAUiTx+C0JYdeJCDlyzrlgdwU02pu2wEb7vSR3IMDNvUahUpgGuNHetAF+aG/aA+dAzoJzztV4gI/EMHOdM+AW2IhIxwxNwqlbNfAZuMXDpTBhmE3pTQ24Be6ANdAdc/HN2A+JW7d4wJphmFTpOTX+Pu/wD7YCWufcpIuDzinYF2K36t6Jp6kjdvFhFFBEooaH+ArcA8/ADh+mJdtO732vY9Uph4iQgjngCviuFx8b5F/bs451hUYxbBWxauCDtqXCOKXp8UbC+cLxp16qvTAS3lLhTJuF9xNBeC2sK84bzlQ2bYXzJ5VOtA1+5n/PvHnsNdT7twmdswmyhEKDGltchF9rKcdMPYMMrjSYyRGwVJQPaaiIpSJek5V0MHrv4D9w7pK0Bf5oT5UeKCghWeJXyQEZvfQ8uljnTHuD7J0r7Zgp4gg/iNKAvQgaXOnQRh+DZWWVbtgPT5RzsJfvhs49apuV8C4sy8jiyF38Mj0AfAt8A37zOinhbLCh7KvjfOHd4d/xO2AtA4l1BKcfx/4CDuFdWh0+4/+l/aARvVqJiHTOuQfd3bJsOULwIGu8AS3wZFNHqtEq00QhB/LXfcIJlabRKpM62HKYnLccsiPrQxlwOlgIlVWjyy0eGlhazbTjcKRwSEZ1cxYcRLXgIeca4Fq3f7JAyRUy4EIlRWuYdo5cKNNJcOfSX2jmA7RYwAeRAAAAAElFTkSuQmCC" style="opacity: 0.30000000000000004;mix-blend-mode: multiply"/>
<circle id="LM_red-2" data-name="LM red-2" cx="62.96" cy="18.95" r="17.06" style="fill: #d42715"/>
</g>
<g id="LM_details_in_red" data-name="LM details in red">
<circle id="LM_detail_red_hole4" data-name="LM detail red hole4" cx="59.9" cy="30.01" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole3" data-name="LM detail red hole3" cx="51.75" cy="15.89" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole2" data-name="LM detail red hole2" cx="65.87" cy="7.74" r="3.79" style="fill: #393939"/>
<circle id="LM_detail_red_hole1" data-name="LM detail red hole1" cx="74.02" cy="21.86" r="3.79" style="fill: #393939"/>
<path id="LM_detail_hole" data-name="LM detail hole" d="M64.2,16.41a.72.72,0,0,1-.55-.91c.21-.72.36-1.33.36-1.33s-.17-.35-1.27-.64-1.35-.06-1.35-.06L61,14.8s-.16.72-.81.54L59,15s-.4.13-.6,1.06a3.44,3.44,0,0,0-.06,1.43l1.25.33a.68.68,0,0,1,.46.81c-.16.61-.33,1.21-.33,1.21s.12.3,1.2.62,1.42.09,1.42.09l.32-1.22s.26-.76,1-.59q.6.17,1.2.39a2.92,2.92,0,0,0,.7-2.25C64.91,16.65,64.2,16.41,64.2,16.41Z" transform="translate(0.98 1.9)" style="fill: #1f1f1f"/>
<path id="LM_detail_red4" data-name="LM detail red4" d="M61.64,24.23,60.09,24l-1.53-.57a.46.46,0,0,1-.33-.56h0l.55-2.05a.46.46,0,0,1,.56-.32l1.45.6,1.63.22a.46.46,0,0,1,.33.56h0l-.55,2.05a.44.44,0,0,1-.55.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red3" data-name="LM detail red3" d="M69.15,17.3l-.26,1.55-.57,1.52a.45.45,0,0,1-.55.33h0l-2.06-.55a.46.46,0,0,1-.32-.56L66,18.15l.22-1.63a.45.45,0,0,1,.55-.33h0l2,.55a.46.46,0,0,1,.32.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red2" data-name="LM detail red2" d="M62.21,9.79l1.55.25,1.53.57a.46.46,0,0,1,.33.55h0l-.55,2.05a.46.46,0,0,1-.56.32l-1.45-.6-1.63-.22a.47.47,0,0,1-.33-.56h0l.55-2.05a.44.44,0,0,1,.55-.32Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
<path id="LM_detail_red1" data-name="LM detail red1" d="M54.7,16.72,55,15.17l.57-1.52a.45.45,0,0,1,.55-.33h0l2.06.55a.46.46,0,0,1,.32.56l-.61,1.44-.22,1.63a.45.45,0,0,1-.55.33h0l-2-.55a.46.46,0,0,1-.32-.56Z" transform="translate(0.98 1.9)" style="fill: #393939"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>`;
}

View File

@ -44,7 +44,7 @@ namespace pxsim.visuals {
}
.sim-text.number {
font-family: Courier, Lato, Work Sans, PT Serif, Source Serif Pro;
font-weight: bold;
/*font-weight: bold;*/
}
.sim-text.inverted {
fill:#5A5A5A;
@ -71,6 +71,15 @@ namespace pxsim.visuals {
fill: gray !important;
cursor: pointer;
}
/* Motor slider */
.sim-motor-btn {
cursor: pointer;
}
.sim-motor-btn:hover .btn {
stroke-width: 2px;
stroke: black !important;
}
`;
const EV3_WIDTH = 99.984346;
@ -222,9 +231,8 @@ namespace pxsim.visuals {
}
case NodeType.MediumMotor:
case NodeType.LargeMotor: {
// TODO: figure out if the motor is in "input" or "output" mode
const state = ev3board().getMotors()[port];
view = new MotorReporterControl(this.element, this.defs, state, port);
view = new MotorSliderControl(this.element, this.defs, state, port);
break;
}
}

View File

@ -27,8 +27,8 @@ namespace pxsim.visuals {
this.group = svg.elt("g") as SVGGElement;
const reporterGroup = pxsim.svg.child(this.group, "g");
reporterGroup.setAttribute("transform", `translate(31, 42)`);
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
reporterGroup.setAttribute("transform", `translate(${this.getWidth() / 2}, 42)`);
this.reporter = pxsim.svg.child(reporterGroup, "text", { 'text-anchor': 'middle', 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement;
const sliderGroup = pxsim.svg.child(this.group, "g");
sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`)
@ -60,12 +60,15 @@ namespace pxsim.visuals {
}, ev => {
captured = true;
if ((ev as MouseEvent).clientY != undefined) {
dragSurface.setAttribute('cursor', '-webkit-grabbing');
this.updateSliderValue(pt, parent, ev as MouseEvent);
}
}, () => {
captured = false;
dragSurface.setAttribute('cursor', '-webkit-grab');
}, () => {
captured = false;
dragSurface.setAttribute('cursor', '-webkit-grab');
})
return this.group;

View File

@ -0,0 +1,167 @@
namespace pxsim.visuals {
export class MotorSliderControl extends ControlView<MotorNode> {
private group: SVGGElement;
private gradient: SVGLinearGradientElement;
private slider: SVGGElement;
private reporter: SVGTextElement;
private dial: SVGGElement;
private static SLIDER_RADIUS = 100;
private internalSpeed: number = 0;
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
this.group = svg.elt("g") as SVGGElement;
const slider = pxsim.svg.child(this.group, 'g', { 'transform': 'translate(25,25)' })
const outerCircle = pxsim.svg.child(slider, "circle", {
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent;`,
'stroke': '#a8aaa8', 'stroke-width': '1rem'
}) as SVGCircleElement;
this.reporter = pxsim.svg.child(this.group, "text", {
'x': this.getInnerWidth() / 2, 'y': this.getInnerHeight() / 2,
'text-anchor': 'middle', 'alignment-baseline': 'middle',
'style': 'font-size: 50px',
'class': 'sim-text inverted number'
}) as SVGTextElement;
this.dial = pxsim.svg.child(slider, "g", { 'cursor': '-webkit-grab' }) as SVGGElement;
const handleInner = pxsim.svg.child(this.dial, "g");
pxsim.svg.child(handleInner, "circle", { 'cx': 0, 'cy': 0, 'r': 30, 'style': 'fill: #f12a21;' });
pxsim.svg.child(handleInner, "circle", { 'cx': 0, 'cy': 0, 'r': 29.5, 'style': 'fill: none;stroke: #b32e29' });
this.updateDial();
let pt = parent.createSVGPoint();
let captured = false;
const dragSurface = svg.child(this.group, "rect", {
x: 0,
y: 0,
width: this.getInnerWidth(),
height: this.getInnerHeight(),
opacity: 0,
cursor: '-webkit-grab'
})
touchEvents(dragSurface, ev => {
if (captured && (ev as MouseEvent).clientY != undefined) {
ev.preventDefault();
this.updateSliderValue(pt, parent, ev as MouseEvent);
this.handleSliderMove();
}
}, ev => {
captured = true;
if ((ev as MouseEvent).clientY != undefined) {
this.updateSliderValue(pt, parent, ev as MouseEvent);
this.handleSliderDown();
}
}, () => {
captured = false;
this.handleSliderUp();
}, () => {
captured = false;
this.handleSliderUp();
})
return this.group;
}
getInnerWidth() {
return 250;
}
getInnerHeight() {
return 250;
}
private lastPosition: number;
private prevVal: number;
private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
let cur = svg.cursorPoint(pt, parent, ev);
const coords = {
x: cur.x / this.scaleFactor - this.left / this.scaleFactor,
y: cur.y / this.scaleFactor - this.top / this.scaleFactor
};
const radius = MotorSliderControl.SLIDER_RADIUS / 2;
const dx = coords.x - radius;
const dy = coords.y - radius;
const atan = Math.atan(-dy / dx);
let deg = Math.ceil(atan * (180 / Math.PI));
if (dx < 0) {
deg -= 270;
} else if (dy > 0) {
deg -= 450;
} else if (dx >= 0 && dy <= 0) {
deg = 90 - deg;
}
const value = Math.abs(Math.ceil((deg % 360) / 360 * this.getMax()));
this.internalSpeed = value;
this.updateDial();
this.prevVal = deg;
this.lastPosition = cur.x;
}
private handleSliderDown() {
const state = this.state;
state.manualMotorDown();
}
private handleSliderMove() {
this.dial.setAttribute('cursor', '-webkit-grabbing');
const state = this.state;
state.manualMotorMove(this.internalSpeed);
}
private handleSliderUp() {
this.dial.setAttribute('cursor', '-webkit-grab');
const state = this.state;
state.manualMotorUp();
this.internalSpeed = 0;
this.updateDial();
}
private updateDial() {
let speed = this.internalSpeed;
// Update dial position
const deg = speed / this.getMax() * 360; // degrees
const radius = MotorSliderControl.SLIDER_RADIUS;
const dialRadius = 5;
const x = Math.ceil((radius - dialRadius) * Math.sin(deg * Math.PI / 180)) + radius;
const y = Math.ceil((radius - dialRadius) * -Math.cos(deg * Math.PI / 180)) + radius;
this.dial.setAttribute('transform', `translate(${x}, ${y})`);
}
updateState() {
if (!this.visible) {
return;
}
const node = this.state;
const speed = node.getSpeed();
// Update reporter
this.reporter.textContent = `${speed}`;
}
private getMin() {
return 0;
}
private getMax() {
return 100;
}
}
}

View File

@ -46,9 +46,9 @@ namespace pxsim.visuals {
}
protected renderMotorAngle(holeEl: Element, angle: number) {
const width = 125.92;
const height = 37.9;
const transform = `rotate(${angle} ${width / 2} ${height / 2})`;
const width = 35.92;
const height = 35.9;
const transform = `translate(45.000000, 1.000000) rotate(${angle} ${width / 2} ${height / 2})`;
holeEl.setAttribute("transform", transform);
}