Meepo Mini 2 vs. Archos SK8

Having never skateboarded before, I saw the Archos SK8 electric skateboard for about 80€ at a sale and thought why not give it a try. This got me into this whole electric skateboarding thing.

Table of Contents

Now that I have some more time at home during the summer, I upgraded to the Meepo Mini 2 and after having driven with it more than 100km, I thought I write down my experiences with the two boards and why I should have gotten the Meepo board from the start.

The competitors

The Meepo Mini 2 and the Archos SK8 are not really competing here, which should be clear looking at their price difference. But for completeness, also take a look at the specs of these two boards:

Meepo Mini 2Archos SK8
Max. speed46 km/h15 km/h
Max. range18 km7 km
Max. Weight136 kg80 kg
Motor2 x 540 W1 x 150 W
Battery144 Wh50.4 Wh
Weight7.4 kg3.9 kg
Specs comparison

Actually, you can swap the Archos SK8 by any of the unbranded “cheap” Chinese boards that share the same design as the ones sold by Oppikle and Hiriyt.

Here, you might wonder how many Watts you actually need. For this I direct you to the Wikpedia article on bicycle performance that contains some sample calculations (and the formulae) which should roughly hold for electric skateboards as well.

Similarities

Before we dig into the differences, lets first note the similarities aka. the choices I made when picking these specific boards in the first place:

First, both boards are hub-motor driven. I made this choice on purpose, as electric skateboards are not road-legal where I live and hub motors are barely noticeable to the non-practiced eye. This reduces my risk of getting fined for riding one.
However, I would probably generally recommend hub-motors over belt-driven motors nowadays as they require less maintenance (no moving parts), while offering a larger range and allowing pushing the board (belt driven block due to the gear ratio). The latter is especially nice, when you have run out of battery or if you do not want to draw any attention.
When electric skateboards were first introduced by boosted, hub-motors were vastly inferior power-wise but that has changed now.

Next, both boards are of so-called “cruiser-style”. This is a size in between a regular skateboard and a long-board. They share a stiff deck and a kicktail with the former, while the use the wheels of the latter.
At this point I should note that I mainly use the boards for leisure instead of a daily commute. This means that I value versatility of the board over comfort of ride.
Here, having a kicktail is a must and rules out long-boards. It allows doing sharp turn, “wheelies” and you are more agile with the short board.
However, you do notice the quality of the pavement very clearly in your feet and being out of the skating age my ankle did hurt the first couple of rides before it got used to it.
So if you want to commute large distances, you should probably get a long-board with a flexi-deck that can cushion away most of the bumps.

Differences

Both boards are of similar length, however the Meepo Mini 2 is considerable wider and heavier. It also has a larger wheel-base.

This results in a better grip and you also feel much more stable on the board. Flipping the board around, you see that the SK8 only uses a single-hub motor while the Mini 2 has two and each of them offers more than 3x the power.

If you do not expect the power or if you enable the pro-mode without being one, the Mini 2 can easily throw you off the board when accelerating or breaking. You can tame it though by using the beginner riding mode if you need to learn how to skate first. You can set the modes for acceleration and breaking separately and I would recommend always using at least the pro mode for breaking and learning to deal with it. In case of an emergency you want to be able to stop in time.

Turning to the SK8, the acceleration is.. meh and so are the breaks – in both of the two riding-modes. The difference between them is merely that the top speed is capped at 10km/h in the low-mode.
But I must say that if you are a beginner this is sufficent; if you do not know how to ride being able to get going and to break are your two primary concerns and the SK8 does deliver here. The main drawback of the Archos SK8 is its tiny battery.

Aside: Li-Ion batteries

At this point we should probably briefly discuss Li-Ion battery technology. Mainly, the following two properties:

  • As you discharge the battery its Voltage drops, which is related to power (the Watts number) as P = V \cdot I, where I is the current in amps.
    So the more you discharge the battery, the fewer Watts you get out of your motors.
  • A full discharge (down to 0%) of the battery severely reduces its live-span. For maximal durability, you should always keep its charge between 40%-80%. Typically, the displayed range is clipped by the controller to help here.

So where does this leave us with the SK8? I did about 7 rides, fully-discharging the board (you do not want to stop after 10min, right?). And now the second riding-mode is essentially gone: when I try to accelerate the motors draw so much current, that the voltage drops below a critical level and the board turns off. Depending on what state the controller was in, I have to pair the remote again afterwards.
But it also shows in the first mode: while the board initially could get me up a slight slope, it now immediately starts beeping due to critical voltage – again the motors need more voltage then the already worn down battery can give.

Remotes & charging indicators

Having covered the drive train, lets turn to the remotes. Both Archos and Meepo use a similar pistol-grip like design, where you control the motors with the thumb switch.

As one would expect, the Meepo remote is more sophisticated and offers detailed telemetry data on a nicely readable LCD display. There you find your current speed, drive mode and board charging level as well as the max. speed of the current ride.

On the Archos remote you only find 4 LEDs. Those are used quite well though: when you turn on the remote, they show the remote charging level. As soon as the board is connected, they indicate the board charging level, which is actually the most important information you need while riding.

Similarly to the remotes, there are only 4 LEDs on the Archos Battery for the charging level, while you find a numeric LED-display on the Meepo board.

An actually noticeable feature on the Meepo Mini 2 is push-to-start; that is, you only have to push the board to turn it on – no need to bend down for flipping a switch.

Verdict

So why do I say you should go straight with the Meepo Mini 2 even as a beginner? On paper the Archos SK8 has everything it takes to be a nice beginner board.
It is really the battery that kills it. With only 5-10 rides it is simply not worth the money, no matter how cheap it is.
Looking at the price difference between the Meepo Mini 2 and the ER version that solely differ in the battery, you grasp that the battery is the crucial part in an electric skateboard. And the Archos SK8 is cheap, precisely because of the bad battery.

With the Meepo Mini 2 on the other hand you get a board that can “grow with you”: as you get more confident you can bump up the riding mode to get more power. Even if you decide that skateboarding is not for you, you can sell the Mini 2 as it will retain lots of its value – in contrast to just producing electric waste with the Archos SK8.

Riding the Meepo Mini 2

The Meepo Mini 2 is specified to go up to 46 km/h. Whether you can go that fast depends on your weight, the wind and the slope (see the Wikipedia link, mentioned above). In case you are fat and/ or there are lots of slopes where you live, you might also consider the ER version of the Mini 2, which comes with doubled battery capacity. As mentioned above this not only means that you can get further, but also that you have more power in the mid-range.

How fast can you go?

Having only previous experience on a Snowboard, I am a rather cautious rider. So far my max. speed (according to the remote) was 30 km/ h which I did uphill – in hope that stopping is easier that way.
Going downhill (only using the motors for breaking), I feel comfortable until around 22 km/ h.
I typically ride for about 30-45 min and the lowest the battery got was 40%, which means it should last for quite some time.
Note, that I do not go straight uphill for 30min and that I usually push to get rolling, as this is where most energy is used.

A suitable helmet

When lifting the board, the remote showed that the ESC only limits the speed at 50 km/h. When riding a skateboard at anything above 10 km/h without a cushion-zone and no nothing, I would highly recommend you to at least wear a helmet.
However, you should consider that a “normal” skate helmet is only specified (EN1078) up to 19.5 km/h impact speed – if you ride faster it does not guarantee protection.

Fortunately, one does not have to resort to heavy motorcycle helmets (ECE2205) as there is a specification (ASTM F1952) for downhill bike helmets, which was designed with speed in mind. It is specified for an impact speed of 22.3 km/h and typically the helmets provide full-face protection.
Recently, even variants for downhill longboarding started to pop-up, which should be even a better fit style-wise.

Addendum: replaced NTA8776 by ASTM F1952 in the last paragraph

Lecture on Augmented Reality

Due to the current circumstances, I had to record the lectures on augmented reality, which I am typically holding live. This was much more work than anticipated..
On the other hand, this means that I can make them available via Youtube now.

So, if you ever wanted to learn about the basic algorithms behind Augmented Reality, now is your chance.

The lecture is structured in two parts

  • Camera Calibration, and
  • Object Pose Estimation.

You can click on the TOC links below to directly jump to a specific topic.

Camera Calibration

Object Pose Estimation

Are we dead yet?

I am quite frustrated with corona graphs in the news, since most reporters seem to have skipped math classes back then. For instance, just plotting the number of confirmed infections at the respective dates does not tell you anything due to the different time point of outbreak. So lets see whether I can do better:

https://paroj.github.io/arewedeadyet/

With the site above, I tried to improve on a few things:

  • the Charts are live: they update themselves each time you load the site.
  • The curves are normalized by the time-point of outbreak so you can compare the course in different countries.
  • You can select the countries that you want to compare.
  • Different metrics are computed that allow comparing the corona countermeasures and impact across countries with different population size.

Fast wire-frame rendering with OpenCV

Lets say you have mesh data in the typical format, triangulated, vertex buffer and index buffer. E. g. something like

>>> vertices

[[[ 46.27500153  19.2329998   48.5       ]]

 [[  7.12050009  15.28199959  59.59049988]]

 [[ 32.70849991  29.56100082  45.72949982]]

 ..., 

>>> indices

[[1068 1646 1577]
 [1057  908  938]
 [ 420 1175  237]
 ..., 

Typically you would need to feed it into OpenGL to get an image out of it. However, there are occasions when setting up OpenGL would be too much hassle or when you deliberately want to render on the CPU.

In this case we can use the OpenCV to do the rendering in two function calls as:

img = np.full((720, 1280, 3), 64, dtype=np.uint8)

pts2d = cv2.projectPoints(vertices, rot, trans, K, None)[0].astype(int)
cv2.polylines(img, pts2d[indices], True, (255, 255, 255), 1, cv2.LINE_AA)

See the documentation of cv2.projectPoints for the meaning of the parameters.

Note how we only project each vertex once and only apply the mesh topology afterwards. Here, we just use the numpy advanced indexing as pts2d[indices] to perform the expansion.

This is pretty fast too. The code above only takes about 9ms on my machine.

In case you want filled polygons, this is pretty easy as well

for face in indices:
    cv2.fillConvexPoly(img, pts2d[face], (64, 64, 192))

However, as we need to a python loop in this case and also have quite some overdraw, it is considerable slower at 20ms.

Of course you can also combine both to get an image like in the post title.

From here on you can continue to go crazy and compute face normals to do culling and shading.

Xiaomi AirDots Pro 2 / True Wireless Earphones 2S Review

So after having made fun of people for “wearing toothbrushes”, I finally came to buy such headphones for myself.

Having used non-true wireless Bluetooth headphones before I was curious what the usability advantage would feel like.

Here I went for the Xiaomi AirDots Pro 2 aka True Wireless Earphones 2S which I could grab for 399 Yuan which is about 51€, which seems like the right price-point for this kind of accessory.

Table of Contents

Keep in mind that the built-in battery only survives so many charging cycles and once it dies you can throw them away.

The initial feeling of using true wireless headphones is surprisingly relieving – there is simply no cord to untangle or to be aware of while wearing.
This is especially true during phone calls, where one needs to keep the microphone aligned.

The downside is that the headphones are too small to accommodate any buttons for volume and playback control.

The Air 2 kind of make up for it by automatically connecting to your phone once you put them on and by automatically pausing the music when you put one out of the ear. This is achieved by a built-in brightness sensor.

Furthermore you have double-tap actions, which default to play/ pause on the right headphone and launching the voice assistant (e.g. Google Assistant) on the left headphone.

The battery life is stated with 4 hours per-charge with 2 extra charges in the case. I could confirm those on a long distance flight.

Compared to the Airpods 2

Looking at the feature-list above or simply at the images, the similarity to the Apple Airpods is apparent.

Out of curiosity I borrowed some from friend for comparison. The most important point is probably sound quality. Here we found the two virtually in-distinguishable. But keep in mind that we only did a quick test and did not use them extensively.

The second point is likely the form. Here, both earphones have the same ear-part and only differ by the shaft. So if one fits your ear, so should the other.

The shaft however is considerably wider on the Airdots. This is less apparent when viewed from the side as the thickness is similar.

For me, the more important difference is being able to control the headphones from my Android smartphone. This is currently not possible with the Airpods, while there is some way for the Airdots;

Companion app & Software integration

To control the earphones, you have to sideload the Xiao Ai Lite App. The main purpose of it is to provide the Xiaomi voice assistant and the Air2 options likely just ended up there instead of Xiaomi Home as they offer an always-on assistant integration just like the Airpods.

It handles firmware updates and allows you to configure the douple-tap action per earphone as well as displaying the charging status of the earphones and the case. By default android will only display the charging status of the least charged earphone.

Furthermore, you can use the fast-paring if the app is running. Here, it is sufficient to hold the earphone case close to the phone and just open it. The app will ask for confirmation. This is only slightly more convenient then holding the pairing button and using the normal bluetooth pairing procedure.

The downside is that the app is currently only available in Chinese and consequently the voice assistant only works with Chinese.

Addendum: “mauronfrio” translated most of the app and provides a modifed APK with english language support at XDA Developers. So there is no need to fiddle with google lens any more.

Below you find some views of the earphone related settings translated with google lens

I tried out some voice commands via google translate and everything works as it should. However if you are not fluent in chinese it is far from practical. Most people should disable the assistant in the settings to avoid accidentally triggering it.

A serious advantage of Xiomi/ Huawei phones is the availability of the LHDC Bluetooth Codec which offers a superior bandwidth and latency.
While I am fine with the bandwidth provided by AAC when listening to music, there is still a noticeable and annoying delay when watching videos and playing games.

Noise Shielding

The firmware upgrade to v2.6.9.0 significantly improved the acoustic pattern of the headphones by tuning up the low bands (base) and thus general sound quality.

This results in a very noticeable noise reduction compared to v2.6.2.0 – especially in the lower frequencies; things like your footsteps get filtered out. Higher frequencies like car motor sounds are still perceivable though. This is however a good compromise for me.

Addendum: previously I stated that the headphones provide active noise cancellation. They do not. I was mistaken by the significantly improved noise shielding through the tuned up bases.

Compared to True Wireless Earphones 2 Basic / Air 2 SE (Addendum)

Ultimately my left earphone died (see below) – likely due to a deep discharge. The second pair of the Air 2 still works though. I will update this review when I find out whether I just had bad luck or whether there is a systematic issue.

Anyway.. as a replacement I ordered myself the Air2 SE earphones, given my phone does not support LHDC and other online reviews described them as “the Air2 without LHDC”.

Well, I guess some sites try to sell an unboxing story as a review..

As you can see on the image above the Air 2 SE are considerably longer than the normal Air 2 and also have different vents.

While they are slightly too long now for my taste, my largest complaint is the sound quality. Basically, the bases which improved sound quality and shielding on the Air2 after the firmware update are missing here. So we have no shielding and a noticeably worse sound quality here.
Next, the microphones on the Air 2 SE are noticeable less sensitive and I had to raise my voice from normal level so my callees could here me.
Finally, the Air2 SE are not supported by the XiaoAI app, so you get no firmware updates and no configurable tap-actions.

Given the small pricing difference between the Air 2 and the Air 2 SE, I therefore recommend to always go for the former.

Also, if you encounter some sites that tell you the Air2 and Air2 SE are the same, please enable your adblocker. Especially if they jabber about different touch zones, even though the marketing material makes it quite clear that up/ middle/ down means you can touch the single zone at any position.

Charging issues

Over time I noticed that the left earphone consistently runs out of battery before the right one.
The issue seems to be that it discharges while stored inside the case. Putting it in and out resolves the issue – but only until it is fully charged. This makes keeping the earphones pre-charged and ready quite an issue.

Hopefully this can be addressed with a future firmware update. (reproduced with firmwares up to v2.7.1.0)

Addendum: the replacement pair (see above) do not have any charging issues. Therefore I guess the issue is just a singular manufacturing defect.

calibDB: easy camera calibration as a web-service

This image has an empty alt attribute; its file name is overlay1.jpg

Camera calibration just got even easier now. The pose calibration algorithm mentioned here is available as web-service.

This means that calibration is no longer restricted to a Linux PC – you can also calibrate cameras attached to Windows/ OSX and even mobile phones.
Furthermore you will not have to calibrate at all if your device is already known to the service.
The underlying algorithm ensures that the obtained calibrations are reliable and thus can be shared between devices of the same series.

Aggregating calibrations while providing on-the-fly calibrations for unknown devices form the calibDB web-service.

In the future we will make our REST API public so you can transparently retrieve calibrations for use with your computer vision algorithms.
This will make them accessible to a variety of devices – without you having to worry about the calibration data.

Beyond the Raspberry Pi for Nextcloud hosting

When using Nextcloud it makes some sense to host it yourself at home to get the maximum benefit of having your own cloud.

If you would use a virtual private server or shared hosting, your data would still be exposed to a third party and the storage would be limited as you would have to rent it.

When setting up a server at home one is tempted to use a Raspberry Pi or similar ARM based device. Those are quite cheap and only consume little power. Especially the latter property is important as the machine will run 24/7.

I was as well tempted and started my self-hosting experience with an ARM based boards, so here are my experiences.

Do not use a Raspberry Pi for hosting

Actually this is true for any ARM based board. As for the Pi itself, only the most recent Pi 4B has a decent enough CPU and enough RAM to handle multiple PHP request (WebCAL, Contacts, WebDAV) from different clients without slowdown.
Also only with the Pi 4B you can properly attach storage over USB3.0 – previously your transfer rates would be limited by the USB2.0 bus.

One might argue that other ARM based computers are better suited. Indeed you could get the decently equipped Odroid U3, long before the Pi 4B was available.
However, non-pi boards have their own set of problems. Typically, they are based on an Smartphone design (e.g. the Odroid U3 essentialy is a Galaxy Note 2).

This makes them plagued by the Android update issues, as these boards require a custom kernel, that includes some of the board specific patches which means you cannot just grab an Ubuntu ARM build.
Instead you have to wait for a special image from the vendor – and just as with Android, at some point, there will be no more updates.

Furthermore ARM boards are actually not that cheap. While the Pi board itself is indeed not expensive at ~60€, you have to add power-supply housing and storage.

Intel NUC devices are a great choice

While everyone was looking at cheap and efficient ARM based boards, Intel has released some great NUC competitors.
Those went largely unnoticed as typically only the high-end NUCs get news coverage. It is more impressive to report how much power one can cram into a small form-factor.

However one can obviously also put only little power in there. More precisely, Intels tablet celeron chips that range around 4-6W TDP and thus compete with ARM boards power-wise. (Still they are an order of magnitude faster then a Raspberry Pi)

DevicePower (Idle)Power (load)
Odroid U33.7 W9 W
GB-BPCE-3350C4.5 W9.6 W

Here, you get the advantages of the mature x86 platform, namely interchangeable RAM, interchangeable WiFi modules, SATA & m2 SSD ports and notably upstream Linux compatibilty (and Windows for that matter).

As you might have guessed by the hardware choice above, I made the switch already some time ago. On the one hand you only get reports for the by now outdated N3350 CPU – but on on the other hand it makes this a long term evaluation.

Regarding the specific NUC model, I went with the Gigabyte GB-BPCE-3350C, which are less expensive (currently priced around 90€) than the Intel models.

Consequently the C probably stands for “cheap” as it lacks a second SO-DIMM slot and a SD-card reader. However it is fan-less and thus perfectly fine for hosting.

So after 2 Years of usage and a successful upgrade between two Ubuntu LTS releases, I can report that switching to the x86 platform was worth it.

If anything I would probably choose a NUC model that also supports M.2/ M-Key in addition to SATA to build a software RAID-1.

Ubuntu on the Lenovo D330

The Lenovo D330 2-in-1 convertible (or netbook as we used to say) is a quite interesting device. It is based on Intels current low-power core platform, Gemini Lake (GLK), and thus offers great battery-life and a fan-less design.

This similar to what you would from an ARM based tablet. However being x86 based and Windows focused we can expect to get Ubuntu Linux running – without requiring any out-of-tree drivers or custom kernels that never get updated as we are used-to from the ARM world.
This post will be about my experiences on doing so.

For this I will use the most recent Ubuntu 19.04 release as it contains fractional scaling support, which is essential for a 10″ 1920x1200px device. Also the orientation sensor (mostly) works out of the box, when compared to the 18.04 LTS release.

Continue reading Ubuntu on the Lenovo D330

Easy camera calibration on Ubuntu

Camera calibration is an essential step for many computer vision applications as well as computational photography.

If you want to know how far something is away from your camera or even get an undistorted image out of it, it must be calibrated.

Unfortunately existing calibration utilities are cumbersome to use and often not available on linux.

Therefore I am happy to announce that the app from my publication

Efficient Pose Selection for Interactive Camera Calibration

is now available in the snap store:

Get it from the Snap Store

It will guide you through the calibration process by displaying a series of target overlays like you see in the cover image. For details on the pose selection, see the above paper.

Additionally the source code is available for you to inspect on github:

https://github.com/paroj/pose_calib

From Blender to OpenCV Camera and back

In case you want to employ Blender for Computer Vision like e.g. for generating synthetic data, you will need to map the parameters of a calibrated camera to Blender as well as mapping the blender camera parameters to the ones of a calibrated camera.

Calibrated cameras typically base around the pinhole camera model which at its core is the camera matrix and the image size in pixels:

K = \begin{bmatrix}f_x & 0 & c_x \\ 0 & f_y& c_y \\ 0 & 0 & 1 \end{bmatrix}, (w, h)

But if we look at the Blender Camera, we find lots non-standard and duplicate parameters with random or without any units, like

  • unitless shift_x
  • duplicate angle, angle_x, angle_y, lens

Doing some research on their meaning and fixing various bugs in the proposed conversion formula, I could however come up with the following python code to do the conversion from blender to OpenCV

# get the relevant data
cam = bpy.data.objects["cameraName"].data
scene = bpy.context.scene
# assume image is not scaled
assert scene.render.resolution_percentage == 100
# assume angles describe the horizontal field of view
assert cam.sensor_fit != 'VERTICAL'

f_in_mm = cam.lens
sensor_width_in_mm = cam.sensor_width

w = scene.render.resolution_x
h = scene.render.resolution_y

pixel_aspect = scene.render.pixel_aspect_y / scene.render.pixel_aspect_x

f_x = f_in_mm / sensor_width_in_mm * w
f_y = f_x * pixel_aspect

# yes, shift_x is inverted. WTF blender?
c_x = w * (0.5 - cam.shift_x)
# and shift_y is still a percentage of width..
c_y = h * 0.5 + w * cam.shift_y

K = [[f_x, 0, c_x],
     [0, f_y, c_y],
     [0,   0,   1]]

So to summarize the above code

  • Note that f_x/ f_y encodes the pixel aspect ratio and not the image aspect ratio w/ h.
  • Blender enforces identical sensor and image aspect ratio. Therefore we do not have to consider it explicitly. Non square pixels are instead handled via pixel_aspect_x/ pixel_aspect_y.
  • We left out the skew factor s (non rectangular pixels) because neither OpenCV nor Blender support it.
  • Blender allows us to scale the output, resulting in a different resolution, but this can be easily handled post-projection. So we explicitly do not handle that.
  • Blender has the peculiarity of converting the focal length to either horizontal or vertical field of view (sensor_fit). Going the vertical branch is left as an exercise to the reader.

The reverse transform can now be derived trivially as

cam.shift_x = -(c_x / w - 0.5)
cam.shift_y = (c_y - 0.5 * h) / w

cam.lens = f_x / w * sensor_width_in_mm

pixel_aspect = f_y / f_x
scene.render.pixel_aspect_x = 1.0
scene.render.pixel_aspect_y = pixel_aspect