Gyro tutorials (#930)
* gyro tutorials * tutorials * fix gyro simulator * images * updated image * fix svg errors
This commit is contained in:
parent
cb816c91ad
commit
80b9c715b2
BIN
docs/static/tutorials/calibrate-gyro.png
vendored
Normal file
BIN
docs/static/tutorials/calibrate-gyro.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
docs/static/tutorials/move-straight-with-gyro.png
vendored
Normal file
BIN
docs/static/tutorials/move-straight-with-gyro.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
@ -25,6 +25,11 @@ Step by step guides to coding your @boardname@.
|
||||
"description": "Use the color sensor to follow line or detect colors",
|
||||
"url":"/tutorials/color-sensor",
|
||||
"imageUrl":"/static/tutorials/what-color.png"
|
||||
}, {
|
||||
"name": "Gyro",
|
||||
"description": "Drive straight or turn more precisely with the gyro",
|
||||
"url":"/tutorials/gyro",
|
||||
"imageUrl":"/static/tutorials/calibrate-gyro.png"
|
||||
}, {
|
||||
"name": "Ultrasonic Sensor",
|
||||
"description": "Use the ultrasonic sensor to detect obstacles",
|
||||
|
37
docs/tutorials/calibrate-gyro.md
Normal file
37
docs/tutorials/calibrate-gyro.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Calibrate Gyro
|
||||
|
||||
## Introduction @fullscreen
|
||||
|
||||
The gyroscope is a very useful sensor in the EV3 system. It detects the rotation rate
|
||||
which can be very useful to correct the trajectory of the robot and do precise turns.
|
||||
|
||||
However, the sensor can be imprecise and subject to drifting. It is recommend to
|
||||
calibrate your sensor at least once after starting your brick. You don't have to
|
||||
recalibrate on every run.
|
||||
|
||||
* [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
|
||||
* [EV3 Driving Base with Gyro](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-gyro-sensor-driving-base-a521f8ebe355c281c006418395309e15.pdf)
|
||||
|
||||
|
||||
## Step 1 Show ports
|
||||
|
||||
Add the ``||brick:show ports||`` to see the status of the gyroscope.
|
||||
|
||||
```blocks
|
||||
brick.showPorts()
|
||||
```
|
||||
|
||||
|
||||
## Step 2 Calibration
|
||||
|
||||
Add a ``||sensors:calibrate gyro||`` block to calibrate the gyro. The block
|
||||
detects if the sensor is present and does a full reset of the sensor if necessary.
|
||||
|
||||
```blocks
|
||||
brick.showPorts()
|
||||
sensors.gyro2.calibrate()
|
||||
```
|
||||
|
||||
## Step 3 Download and run @fullscreen
|
||||
|
||||
Download this program to your brick and press the ENTER button.
|
19
docs/tutorials/gyro.md
Normal file
19
docs/tutorials/gyro.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Gyro tutorials
|
||||
|
||||
## Tutorials
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Calibrate",
|
||||
"description": "Make sure you gyro sensor is ready to use",
|
||||
"cardType": "tutorial",
|
||||
"url":"/tutorials/calibrate-gyro",
|
||||
"imageUrl":"/static/tutorials/calibrate-gyro.png"
|
||||
}, {
|
||||
"name": "Move Straight",
|
||||
"description": "Use the gyro to correct the trajectory of the robot",
|
||||
"cardType": "tutorial",
|
||||
"url":"/tutorials/move-straight-with-gyro",
|
||||
"imageUrl":"/static/tutorials/move-straight-with-gyro.png"
|
||||
}]
|
||||
```
|
61
docs/tutorials/move-straight-with-gyro.md
Normal file
61
docs/tutorials/move-straight-with-gyro.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Move Straight With Gyro
|
||||
|
||||
## Introduction @fullscreen
|
||||
|
||||
Rotating using a wheel is not precise. The wheel can slip or the motors
|
||||
can be slightly different.
|
||||
With the help of the gyro you can detect and correct deviations in your trajectory.
|
||||
|
||||
* [EV3 Driving Base](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
|
||||
* [EV3 Driving Base with Gyro](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-gyro-sensor-driving-base-a521f8ebe355c281c006418395309e15.pdf)
|
||||
|
||||
|
||||
## Step 1 Calibration
|
||||
|
||||
Add a ``||sensors:calibrate gyro||`` block in a ``||brick:on button enter pressed||`` block so that you can manually start a calibration process. Run the calibration
|
||||
at least once after connecting the gyro.
|
||||
|
||||
```blocks
|
||||
brick.showPorts()
|
||||
sensors.gyro2.calibrate()
|
||||
```
|
||||
|
||||
## Step 2 Compute the error
|
||||
|
||||
Make a new **error** variable and drag the ``||sensors:gyro rate||``
|
||||
and multiply it by -1. Since the rate shows the rotation rate, we will
|
||||
counter it by negating it.
|
||||
|
||||
```blocks
|
||||
let error = 0
|
||||
brick.showPorts()
|
||||
sensors.gyro2.calibrate()
|
||||
while (true) {
|
||||
error = sensors.gyro2.rate() * -1
|
||||
}
|
||||
```
|
||||
|
||||
## Step 3 Steer with feedback
|
||||
|
||||
Drag a ``||motors:steer motors||`` block under the variable and pass
|
||||
the **error** variable into the turn ratio section.
|
||||
|
||||
If the robot is turning right, the gyro will report a positive rotation rate
|
||||
and the turn ratio will be negative which will the turn the robot left!
|
||||
|
||||
```blocks
|
||||
let error = 0
|
||||
brick.showPorts()
|
||||
sensors.gyro2.calibrate()
|
||||
while (true) {
|
||||
error = sensors.gyro2.rate() * -1
|
||||
motors.largeBC.steer(error, 50)
|
||||
}
|
||||
```
|
||||
|
||||
## Step 4 Run it!
|
||||
|
||||
Download to your brick and test out if the robot is going straight.
|
||||
|
||||
This kind of technique is called a proportional controller;
|
||||
it corrects the inputs (motor speed) with a feedback proportional to the output (rotation rate).
|
@ -1,6 +1,6 @@
|
||||
# calibrate
|
||||
|
||||
Reset the zero reference for the gyro to current position of the brick.
|
||||
Detects if the gyro is drifting and performs a full reset if needed.
|
||||
|
||||
```sig
|
||||
sensors.gyro2.calibrate()
|
||||
|
@ -73,7 +73,7 @@ namespace sensors {
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a calibration of the with light progress indicators.
|
||||
* Detects if calibration is necessary and performs a full reset, drift computation.
|
||||
* Must be called when the sensor is completely still.
|
||||
*/
|
||||
//% help=sensors/gyro/calibrate
|
||||
@ -95,6 +95,19 @@ namespace sensors {
|
||||
// give time for robot to settle
|
||||
pause(700);
|
||||
|
||||
// compute drift
|
||||
this.computeDriftNoCalibration();
|
||||
if (Math.abs(this.drift()) < 0.1) {
|
||||
// no drift, skipping calibration
|
||||
brick.setStatusLight(StatusLight.Green); // success
|
||||
pause(1000);
|
||||
brick.setStatusLight(statusLight); // resture previous light
|
||||
|
||||
// and we're done
|
||||
this.calibrating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// calibrating
|
||||
brick.setStatusLight(StatusLight.OrangePulse);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
namespace pxsim {
|
||||
const enum GyroSensorMode {
|
||||
export const enum GyroSensorMode {
|
||||
None = -1,
|
||||
Angle = 0,
|
||||
Rate = 1,
|
||||
@ -20,6 +20,7 @@ namespace pxsim {
|
||||
}
|
||||
|
||||
setAngle(angle: number) {
|
||||
angle = angle | 0;
|
||||
if (this.angle != angle) {
|
||||
this.angle = angle;
|
||||
this.setChangedState();
|
||||
@ -27,6 +28,7 @@ namespace pxsim {
|
||||
}
|
||||
|
||||
setRate(rate: number) {
|
||||
rate = rate | 0;
|
||||
if (this.rate != rate) {
|
||||
this.rate = rate;
|
||||
this.setChangedState();
|
||||
|
@ -49,11 +49,13 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
private updateDimensions(width: number, height: number, strict?: boolean) {
|
||||
width = Math.max(0, width);
|
||||
height = Math.max(0, height);
|
||||
if (this.content) {
|
||||
const currentWidth = this.getInnerWidth();
|
||||
const currentHeight = this.getInnerHeight();
|
||||
const newHeight = currentHeight / currentWidth * width;
|
||||
const newWidth = currentWidth / currentHeight * height;
|
||||
const newHeight = Math.max(0, currentHeight / currentWidth * width);
|
||||
const newWidth = Math.max(0, currentWidth / currentHeight * height);
|
||||
if (strict) {
|
||||
this.content.setAttribute('width', `${width}`);
|
||||
this.content.setAttribute('height', `${height}`);
|
||||
|
@ -1,13 +1,16 @@
|
||||
|
||||
|
||||
namespace pxsim.visuals {
|
||||
const MAX_RATE = 40;
|
||||
const MAX_ANGLE = 360;
|
||||
|
||||
export class RotationSliderControl extends ControlView<GyroSensorNode> {
|
||||
private group: SVGGElement;
|
||||
private slider: SVGGElement;
|
||||
private text: SVGTextElement;
|
||||
|
||||
private static SLIDER_WIDTH = 70;
|
||||
private static SLIDER_HEIGHT = 78;
|
||||
//private static SLIDER_HEIGHT = 78;
|
||||
|
||||
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||
this.group = svg.elt("g") as SVGGElement;
|
||||
@ -23,6 +26,14 @@ namespace pxsim.visuals {
|
||||
pxsim.svg.child(this.slider, "circle", { 'cx': 9, 'cy': 50, 'r': 13, 'style': 'fill: #f12a21' });
|
||||
pxsim.svg.child(this.slider, "circle", { 'cx': 9, 'cy': 50, 'r': 12.5, 'style': 'fill: none;stroke: #b32e29' });
|
||||
|
||||
this.text = pxsim.svg.child(this.group, "text", {
|
||||
'x': RotationSliderControl.SLIDER_WIDTH / 2,
|
||||
'y': RotationSliderControl.SLIDER_WIDTH * 1.2,
|
||||
'text-anchor': 'middle', 'dominant-baseline': 'middle',
|
||||
'style': 'font-size: 16px',
|
||||
'class': 'sim-text inverted number'
|
||||
}) as SVGTextElement;
|
||||
|
||||
const dragSurface = svg.child(this.group, "rect", {
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -61,7 +72,17 @@ namespace pxsim.visuals {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const percentage = node.getValue();
|
||||
let percentage = 50;
|
||||
if (node.getMode() == GyroSensorMode.Rate) {
|
||||
const rate = node.getValue();
|
||||
this.text.textContent = `${rate}°/s`
|
||||
// cap rate at 40deg/s
|
||||
percentage = 50 + Math.sign(rate) * Math.min(MAX_RATE, Math.abs(rate)) / MAX_RATE * 50;
|
||||
} else { //angle
|
||||
const angle = node.getValue();
|
||||
this.text.textContent = `${angle}°`
|
||||
percentage = 50 + Math.sign(angle) * Math.min(MAX_ANGLE, Math.abs(angle)) / MAX_ANGLE * 50;
|
||||
}
|
||||
const x = RotationSliderControl.SLIDER_WIDTH * percentage / 100;
|
||||
const y = Math.abs((percentage - 50) / 50) * 10;
|
||||
this.slider.setAttribute("transform", `translate(${x}, ${y})`);
|
||||
@ -73,8 +94,14 @@ namespace pxsim.visuals {
|
||||
const bBox = this.content.getBoundingClientRect();
|
||||
let t = Math.max(0, Math.min(1, (width + bBox.left / this.scaleFactor - cur.x / this.scaleFactor) / width))
|
||||
|
||||
t = -(t - 0.5) * 2; // [-1,1]
|
||||
|
||||
const state = this.state;
|
||||
state.setRate((1 - t) * (100));
|
||||
if (state.getMode() == GyroSensorMode.Rate) {
|
||||
state.setRate(MAX_RATE * t);
|
||||
} else {
|
||||
state.setAngle(MAX_ANGLE * t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
"Touch Sensor Tutorials": "tutorials/touch-sensor",
|
||||
"Color Sensor Tutorials": "tutorials/color-sensor",
|
||||
"Ultrasonic Sensor Tutorials": "tutorials/ultrasonic-sensor",
|
||||
"Gyro Sensor Tutorials": "tutorials/gyro",
|
||||
"Infrared Sensor Tutorials": "tutorials/infrared-sensor",
|
||||
"FLL / City Shaper": "tutorials/city-shaper",
|
||||
"Design Engineering": "design-engineering",
|
||||
|
Loading…
Reference in New Issue
Block a user