The LEGO Control+ motors - Technic XLarge Linear Motor and Technic Large Linear Motor - have internally the modes
POS (reporting a position) and
APOS (reporting an absolute position). Further does the LEGO Wireless Protocol specify methods
Strange thing: When using
GotoAbsolutePosition does not work as expected and goes to strange positions and not the expected absolute physical position!
GotoAbsolutePosition does not orient itself on the physical
APOS. It is aligned with virtual
And to put it in context, a memorable quote:
There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton
Let us start with the simple mode:
APOS is the absolute position in degrees measured from a zero point. It goes from 0, 1 .. 179, 180 then to -180, -179, .., -1, 0. Simple, straight forward. For the current Control+ motors the zero point is physically not marked.
POS on the other hand is more complicated. The value 0 is aligned with the position of the motor was when the device was activated (most likely: put under power). From that moment on, it counts the degrees moved away from that position. And that number can get quite high (it is a
Int32) and exceeds the traditional 0-360 degree range.
- Motor is put under power:
- Motor is moved by 30 degrees:
- Motor is moved by -70 degrees:
- Motor is further moved by two full turns (aka. -720 degrees) :
StartSpeedForDegrees moves the motor by the amount of degrees relative to the current position. If the motor is at
POS: 20 and the command is invoked with 5 degrees the motor is afterwards in
GotoAbsolutePosition moves the motor to a given absolute position within the range of
POS. An example: If the position is
POS: -760 and command is invoked with -40 the motor will make two full turns and is not oriented 40 degrees of the physical zero but -40 degrees of the initial position of the motor. Consequently it takes an
Int32 as a parameter.
These two unexpected behaviors are traps when programming against the LEGO Wireless Protocol / Powered UP. They are a horrible user experience in regards to their naming (developer perspective). However, they are the correct interface and the right thing to do.
Note: This reflection is based on the Technic Control+ L/XL Linear Motors. There might be a different handling with different motors. I will update the post if I become aware of a difference.
Adjust the mental model
- For most use cases, an (physical) absolute position (
APOS) is useless. A Technic axle can be connected in 3 wrong offsets compared to the pyhsical zero point of the motor (remember: unmarked). Even more interesting for gears.
GotoAbsolutePositionshould be (mentally and in SDKs) named
GotoPositionto better reflect the fact that it is aligned with the
POSrange and not the
- The two full turns can then easily be explained as the amount of degrees as a delta between the current pos and the targeted position the motor should go-to.
- The 40 degrees of the original motor position are also now okay, because that aligns with the understanding of
Note: As an alternative: Maybe
APOS is wrongly named 😀. Or maybe we just need a proper documentation.
Practical Usage: Reset Zero
Assume a Technic Model with a steering. Magically it was calibrated to the center of your steer. The motor is at
The question here is: What use does
GotoAbsolutePosition bring? Well, there is the method
PresetEncoder. It resets
POS to zero. Applied here,
GotoAbsolutePosition can now comfortable control the steering around the middle position (0) without doing complicated math otherwise needed when using
Naming is hard. Documentation is sometimes a good idea.
Appendix: Users of SharpBrick.PoweredUp
The mentioned modes and commands are exposed using the following methods: