Helios++
Helios software for LiDAR simulations
|
Class representing an oscillating mirror beam deflector. More...
#include <OscillatingMirrorBeamDeflector.h>
Public Member Functions | |
OscillatingMirrorBeamDeflector (double scanAngleMax_rad, double scanFreqMax_Hz, double scanFreqMin_Hz, int scanProduct) | |
Constructor for oscillating mirror beam deflector. More... | |
std::shared_ptr< AbstractBeamDeflector > | clone () override |
void | _clone (std::shared_ptr< AbstractBeamDeflector > abd) override |
void | applySettings (std::shared_ptr< ScannerSettings > settings) override |
void | doSimStep () override |
void | restartDeflector () override |
void | updateBeamAngle () |
Update the current beam angle at each simulation step. | |
void | accelerateBeamAngle (double const p, double const pa, double const norm, double const sign) |
Compute the beam angle acceleration. More... | |
void | linearBeamAngle (double const sign) |
Compute the beam angle linear behavior. More... | |
void | decelerateBeamAngle (double const p, double const pb, double const norm, double const sign) |
Compute the beam angle deceleration. More... | |
void | setScanAngle_rad (double scanAngle_rad) override |
void | setScanFreq_Hz (double scanFreq_Hz) override |
![]() | |
AbstractBeamDeflector (double scanAngleMax_rad, double scanFreqMax_Hz, double scanFreqMin_Hz) | |
Base constructor for beam deflectors. More... | |
virtual bool | lastPulseLeftDevice () |
Check if last pulse left device (true) or not (false) More... | |
Rotation | getEmitterRelativeAttitude () |
Get the relative emitter attitude. More... | |
Rotation & | getEmitterRelativeAttitudeByReference () |
Get the relative emitter attitude by referencce. More... | |
Public Attributes | |
int | cfg_device_scanProduct = 1000000 |
Scan product to limit maximum scan angle and the scanning frequency. | |
int | currentScanLinePulse = 0 |
Current scan line pulse. | |
int | cfg_device_turningPulses = 100 |
How many pulses are required for the turning around. More... | |
int | cached_pulsesPerScanline = 0 |
Pulses per scan line. | |
int | cached_halfScanlinePulse |
The number of the pulse at the half of the scanline. | |
int | cached_firstAccelerateScanlinePulse |
The number of the scanline pulse where the first accelerate operation starts. The first accelerate operation occurs during the positive monotonic region of the bitonic scanline. | |
int | cached_firstLinearScanlinePulse |
The number of the scanline pulse where the first constant linear operation starts. The first linear operation occurs during the positive monotonic region of the bitonic scanline. | |
int | cached_firstDecelerateScanlinePulse |
The number of the scanline pulse where the first decelerate operation starts. The first decelerate operation occurs during the positive monotonic region of the bitonic scanline. | |
int | cached_secondAccelerateScanlinePulse |
The number of scanline pulse where the second accelerate operation starts. The second accelerate operation occurs duting the negative monotonic region of the bitonic scanline. | |
int | cached_secondLinearScanlinePulse |
The number of scanline pulse where the second constant linear operation starts. The second linear operation occurs during the negative monotonic region of the bitonic scanline. | |
int | cached_secondDecelerateScanlinePulse |
The number of the scanline pulse where the second decelerate operation starts. The second decelerate operation occurs during the negative monotonic region of the bitonic scanline. | |
double | cached_middleNorm |
The norm to be applied for acceleration and deceleration when at the middle stage of the scanline. It is, for the first deceleration and the second acceleration. | |
double | cached_extremeNorm |
The norm to be applied for acceleration and deceleration when at the extremes of the scanline (its start and its end). It is, for the first acceleration and the second deceleration. | |
![]() | |
double | cfg_device_scanFreqMax_Hz = 0 |
Minimum scanning frequency (hertz) | |
double | cfg_device_scanFreqMin_Hz = 0 |
Maximum scanning frequency (hertz) | |
double | cfg_device_scanAngleMax_rad = 0 |
Maximum scanning angle (radians) | |
double | cfg_setting_scanFreq_Hz = 0 |
Scanning frequency (hertz) | |
double | cfg_setting_scanAngle_rad = 0 |
Scanning angle (radians) | |
double | cfg_setting_verticalAngleMin_rad = 0 |
Minimum vertical scanning angle (radians) | |
double | cfg_setting_verticalAngleMax_rad = 0 |
Maximum vertical scanning angle (radians) | |
double | state_currentBeamAngle_rad = 0 |
Current beam angle (radians) | |
double | state_angleDiff_rad = 0 |
Angle differential (radians) | |
double | cached_angleBetweenPulses_rad |
Angle between pulses (radians) | |
Rotation | cached_emitterRelativeAttitude = Rotation(glm::dvec3(1, 0, 0), 0) |
Relative emitter attitude. | |
Class representing an oscillating mirror beam deflector.
Let \(\theta\) be the scan angle, \(\gamma(p)\) be the beam angle on pulse \(p\), \(p_t\) be the number of pulses required for a turning operation and \(n\) the number of pulses describing a scacnline.
Thus, it is possible to define the first acceleration stage start pulse \(p_a\), the first linear stage start pulse \(p_b\), the first deceleration stage start pulse \(p_c\), the second acceleration stage start pulse \(p_d\), the second linear stage start pulse \(p_e\) and the second deceleration stage start pulse \(p_f\). As follows:
\[ \begin{split} p_a &=&\, 1 \\ p_b &=&\, \left\lfloor\frac{p_t}{2}\right\rfloor \\ p_c &=&\, \left\lfloor\frac{n}{2}\right\rfloor - \left\lfloor\frac{p_t}{2}\right\rfloor \\ p_d &=&\, \left\lfloor\frac{n}{2}\right\rfloor + 1 \\ p_e &=&\, \left\lfloor\frac{n}{2}\right\rfloor + 1 + \left\lfloor\frac{p_t}{2}\right\rfloor \\ p_f &=&\, n - \left\lfloor\frac{p_t}{2}\right\rfloor + 1 \end{split} \]
Considering the oscillating mirror beam deflector has bitonic scanlines where, for convenience, the first half of the scanline is the positive monotonic stage while the second half of the scanline is the negative monotonic stage. There are \(6\) different stages: The first acceleration stage inside interval \([p_a, p_b)\), the first linear stage inside interval \([p_b, p_c)\), the first deceleration stage inside interval \([p_c, \frac{n}{2})\), the second acceleration stage inside interval \([p_d, p_e)\), the second linear stage inside interval \([p_e, p_f)\) and the second deceleration stage inside interval \([p_f, n]\).
Notice that \(\gamma(0) = -\theta\) and \(\gamma\left(\frac{n}{2}\right) = \theta\) are the frontiers that must be satisfied. Then, the oscillating mirror beam deflector can be modelled as a function \(\gamma(p)\) which gives the beam angle on pulse \(p\) (as stated before). This function will behave like the function \(f\) for linear stages, like the function \(g\) for acceleration stages and like the function \(h\) for deceleration stages. These three functions are defined for the first positive monotonic part of the scanline, without loss of generality (negative monotonic part can be obtained just by substracting instread of adding):
\[ \begin{split} f(p+1) &=&\, \gamma(p) + \frac{d}{dp}f(p) \\ g(p+1) &=&\, \gamma(p) + \frac{d}{dp}g(p) \\ h(p+1) &=&\, \gamma(p) + \frac{d}{dp}h(p) \end{split} \]
Considering the step between pulses is \(1\), the derivatives with respect to simulation steps of the previous functions can be defined using forward finite differences as follows. Where \(a\) and \(b\) denote the first and last pulse of the current acceleration/linear/deceleration stage, respectively:
\[ \begin{split} \frac{d}{dp}f(p) \approx&\, \frac{\Delta^{1}_{1}[f](p)}{1} =&\, \frac{f(p+1)-f(p)}{1} =&\, \omega \\ \frac{d}{dp}g(p) \approx&\, \frac{\Delta^{1}_{1}[g](p)}{1} =&\, \frac{g(p+1)-g(p)}{1} =&\, \frac{p+1-a}{b-a} \omega \\ \frac{d}{dp}h(p) \approx&\, \frac{\Delta^{1}_1[h](p)}{1} =&\, \frac{h(p+1)-h(p)}{1} =&\, \frac{b-p-1}{b-a} \omega \end{split} \]
Finally, notice that solving this model reduces to finding the angle between pulses \(\omega\) that makes the model satisfy its frontiers. It is, solving below expression for \(\omega\):
\[ \theta = \sum_{p=p_a}^{p_b-1}{\frac{p-p_a}{p_b-p_a}\omega} + \sum_{p=p_b}^{p_c-1}{\omega} + \sum_{p=p_c}^{p_d-1}{\frac{p_d-p}{p_d-p_c}\omega} - \theta \iff \omega = 2\theta \left[ \sum_{p=p_a}^{p_b-1}{\frac{p-p_a}{p_b-p_a}} + \left(p_c - p_b\right) + \sum_{p=p_c}^{p_d-1}{\frac{p_d-p}{p_d-p_c}} \right]^{-1} \]
Simplifying, \(\omega\) can be simply calculated as depicted below:
\[ \omega = 2 \theta \left( p_c - p_b + \frac{ p_b - p_a + p_d - p_c - 1 }{2} \right)^{-1} = 4 \theta \left( {p_c+p_d-p_a-p_b-1} \right)^{-1} \]
|
inline |
Constructor for oscillating mirror beam deflector.
void OscillatingMirrorBeamDeflector::accelerateBeamAngle | ( | double const | p, |
double const | pa, | ||
double const | norm, | ||
double const | sign | ||
) |
Compute the beam angle acceleration.
p | Current pulse |
pa | Start pulse of the acceleration stage (inclusive) |
sign | Specify whether the beam angle is increasing (positive, 1) or decreasing (negative, -1) |
|
overridevirtual |
Reimplemented from AbstractBeamDeflector.
void OscillatingMirrorBeamDeflector::decelerateBeamAngle | ( | double const | p, |
double const | pb, | ||
double const | norm, | ||
double const | sign | ||
) |
Compute the beam angle deceleration.
p | Current pulse |
pb | End pulse of the deceleration stage (exclusive) |
sign | Specify whether the beam angle is increasing (positive, 1) or decreasing (negative, -1) |
|
overridevirtual |
Implements AbstractBeamDeflector.
void OscillatingMirrorBeamDeflector::linearBeamAngle | ( | double const | sign | ) |
Compute the beam angle linear behavior.
sign | Specify whether the beam angle is increasing (positive, 1) or decreasing (negative, -1) |
|
overridevirtual |
Reimplemented from AbstractBeamDeflector.
|
overridevirtual |
Reimplemented from AbstractBeamDeflector.
|
overridevirtual |
Reimplemented from AbstractBeamDeflector.
int OscillatingMirrorBeamDeflector::cfg_device_turningPulses = 100 |
How many pulses are required for the turning around.
CAUTION If number of turning pulses \(>\) number of pulses per scan line, then the oscillating mirror beam deflector will not work properly. Because there is not enough time to complete both necessary turnings per scanline.