Мудрец, яма и солдат

Однажды мудрец прогуливался по лесу, недалеко от своей деревни, и провалился в яму, вырытую охотниками для большого зверя.

Во время падения он повредил ноги, и потому – не мог выбраться из ямы самостоятельно. Мудрец был стар и слух уже был не тем. Вдобавок яма была глубокой, и  он не мог слышать совершенно ничего, что происходит наверху. Он не мог слышать людей проходящих по дороге, что была неподалеку.

“Ну ничего.” – подумал мудрец, – “Меня знают и уважают во всей деревне. Скоро люди хватятся, что меня нет, и пойдут искать.”

Была середина лета, и как раз в эти дни в деревне  начался праздник по поводу хорошего урожая пшеницы. Люди танцевали, веселились, влюблялись, словом они и думать забыли о несчастном старце, что постоянно гулял где-то в лесу или горах, а сейчас сидел голодный и покалеченный в яме.

На второй день мудрец понял, что его не скоро спасут, и скорее всего он умрет тут от голода и жажды.

Рядом с ямой рос высокий дуб, ветви которого прикрывали яму от прямых лучей, и спасали сидевшего в ней человека от дневного зноя. И вот на второй день, на высокую ветку, склонявшуюся над ямой прилетела птичка. Ей было очень хорошо, и совсем скоро, она начала петь дивную песню, воспевая, красоту земной природы и нежное тепло утренних лучей солнца.

И вдруг внезапно, птица испугалась и улетела. Мудреца осенило – по дороге идут люди! И он начал что есть силы кидать комки земли как можно выше вверх и кричать. Земля падала обратно ему на голову и на плечи, но он, не смотря ни на что, отчаянно кидал землю вверх и кричал, кричал так громко как только мог!

По дороге шел солдат, который услышал тихий странный вой, и повернув голову в сторону доносящихся звуков – увидел грязь, которая вылетала снизу вверх. Он подошел, и увидел яму, и сидящего в ней несчастного старца.

Солдат спас мудреца, напоил водой, накормил и отвел обратно в деревню.

Мораль

Если ты в беде, а где-то рядом идет большой праздник и никто про тебя не вспоминает – значит ты никому не нужен. И тебя никто не выручит. Это – горький факт, знание которого, тем не менее –  может спасти твою жизнь.

Будь ты хоть семи пядей во лбу, но, сидя в яме, едва ли ты увидешь дальше, чем глупая птичка, которая сидит рядом на дереве.

Бывают обстоятельства в которых не важно мудрец ты или нет. Обстоятельства, в которых от тебя лишь требуется – кидать комки грязи вверх и кричать что есть силы.

Мудрец не знал, что по дороге идет солдат, а солдат не знал ни про яму, ни про то, что в ней сидит именно мудрец. Оба поверили в очевидные и независимые явления: один – в испугавшуюся птицу, другой – в землю, которая летит вверх. Сильный аргумент таков, что не важно – кто именно тебе его преподносит, ты веришь в него исходя из логики и собственных знаний.

И наконец шутка! Если на тебя сверху падает грязь – это не всегда плохо!

The Bird Project

Bird OSD

Introduction

You have Raspberry Camera and you need FPV, but you can’t fight 100-200ms latency? Then there is a solution.

Bird OSD turns your Raspberry PI into FPV stream source with OSD overlay.

How?

Since raspberry has Video Composite Output, you can then cast raspberrian screen just like a regular FPV signal over FPV transmitter module!

Raspberry Pi works on broadcomm SoC  with VideoCore processor so that means we can apply OSD overlay to camera stream with really low realtime latencies.

X server is not requried

Bird OSD is a systemd service, it uses raspivid app to grab camera image, and it uses own bird-osd GLES2 application to apply overlay with sensor data on it.

So finally you should see something like this:

(GPS was broken, sorry, still can’t demonstrate in real fly)

Another pic from FPV goggles:

Prerequirements

  1. RPI device with sensors board (navio2 is ok)
  2. Raspberry Camera connected to it.
  3. Something sending MAVLink data to 127.0.0.1:14550(running ardupilot, arducopter, whatever)

How to install

Download .deb package onto your raspberry device:

$ wget http://ppa.dyatkovskiy.com/raspbian/pool/main/b/bird-osd/bird-osd_1.1.2_armhf.deb

And then install it:

$ sudo dpkg -i bird-osd_1.1.2_armhf.deb

Then you should target MAVLink channel to 127.0.0.1:14550

E.g. for arducopter:

$ sudo nano /etc/default/arducopter 

Ensure you have string like this:

TELEM1="-A udp:127.0.0.1:14550"

Or like this:

TELEM2="-C udp:127.0.0.1:14550"

In case you modified /etc/default/arducopterconfig, then you should restart service:

$ sudo systemctl restart arducopter

Finally you should start bird-osdservice with this command:

sudo systemctl start bird-osd

Then on monitor connected to your raspberryyou should see whatever your camera sees + overlay with sensors data!

It is still very first version:

  1. I only tested it on RPI 3, I added dependency to raspividand to bash:
    libraspberrypi-bin (>= 1.20180417-1), bash (>= 4.4-5)
    

    Perhaps dependency versions are higher then it really needs, just had no opportunity to test it on another envs.

  2. Do not to blame me guys for not opening sources. There are such a mess, need to sort them first.
  3. It still consumes too much of CPU time. After holidays I’ll work a bit on optimizations. It uses text atlas, but still builds text layout dynamically. It should render every static text to texture; per profiling survey results, it should improve performance on 30-40% (since most of text labels are static).
  4. Any proposals are welcome.

How enable or disable service

If you want to enable bird-osdon boot, you should run:

$ sudo systemctl enable bird-osd

This command disables service:

$ sudo systemctl disable bird-osd

How to uninstall

And this command removes bird-osdfrom you raspberry device:

$ dpkg -P bird-osd

Relevant topics

Edge detection for text – simple edge detection shader for text-like foreground drawings

Artificial Neural Networks and Puffer Jacket

Let’s imagine that humanity died out, and new civilzation discovered that human beings used puffer jackets to save body heat.

But they didn’t know how it works. So they “disassembled” one of jackets  they found, and discovered that it consists of bird fluff.

And this is how they reproduced heat saver thing. They made a building with walls out of fluffs cemented with clay. And got little progress. So they tried to use glair instead of clay, but still too bad.

Only 128 years later, when they advanced on heat theory, they understood what was wrong, and made building with hollow walls, but filled with flair.

A bit later knowing theory and learned chemistry and gas dynamics they stopped to kill birds, and replaced flair with synthetic heat insulation fiber.

Well, if we advance on how our mind works, we perhaps find a better use of artificial neural networks, or may be replace it with better concept?

Cross compilation for Raspberry from Sierra

In very short

If you need to compile something for raspberry just run this:

path/to/clang --target=arm-linux-gnueabihf --sysroot=/some/path/arm-linux-gnueabihf/sysroot my-happy-program.c  -fuse-ld=lld

In command above “arm-linux-gnueabihf” – is my target triple.

If you don’t like LLVM or just need GCC, read Yuzhou Cheng’s article . Or lookup in nets something like “cross compilation for raspberry”. This may help. Below we describe how to do it with LLVM.

Disclaimer

We assume that reader knows how to deal with command line. If not, don’t worry, it’s ok, not to know some things in our life. Feel free and just ask questions in comments.

Let’s start

Root FS

Of course you still need rootfs. And also you perhaps need gcc binutils, but perhaps you would like to use ones provided by llvm infrastructure. But. You don’t have to build it, just get it, e.f. from Linux package. But actually I’m looking for solution how to make it enough just to mount my raspberry rootfs.

How to get LLVM

At current moment there are precompiled binaries for Mac OS (go to “Pre-Built Binaries” paragraph):

http://releases.llvm.org/download.html

Or for version 7.0.0 you may run this in terminal:

$ wget http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz

Compiling LLVM from sources

Don’t worry this is a bit different from building gcc. Difference is in statistics fact, that it usually successful and you can really drink cup of coffee.

Prerequirements

Below are few brew commands which adds all dependencies we need.

$ brew install swig
$ brew install cmake

Get sources

Get LLVM, Clang, LLD and LLDB sources, once again same link:

http://releases.llvm.org/download.html

Or for 7.0.0:
LLVM
Clang
LLD
LLDB

1. Extract LLVM sources.

2. Extract LLD into llvm/tools/lld

3. Extract LLDB into llvm/tools/lldb

4. Most tricky part: lldb needs to be code signed. This article describes how to to that. Actually you should find it in your lldb sources dir, in lldb/docs/code-signing.txt.

5. Create some binary dir, let say “llvm.darwin-x86_64”, and cd into it.

6. Compile

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release <path to llvm sources>

make -j<num-parallel jobs, for me it is 8>

7. Test it.

make -j8 check

8. Use it!

Post scriptum

Optionally you may use legacy binutils. In this case install them with brew:

$ brew install arm-linux-gnueabihf-binutils

But I prefer just to use single solution.

CMake Toolchain

Below is my cmake toolchain file, which uses clang (built from sources). Hope it will be useful for you.

toolchain.cmake

SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# Custom toolchain-specific definitions for your project
set(PLATFORM_ARM "1")
set(PLATFORM_COMPILE_DEFS "COMPILE_GLES")

# There we go!
# Below, we specify toolchain itself!

SET(TARGET_TRIPLE arm-linux-gnueabihf)

# Specify your target rootfs mount point on your compiler host machine
SET(TARGET_ROOTFS /Volumes/rootfs-${TARGET_TRIPLE})

# Specify clang paths
SET(LLVM_DIR /Users/stepan/projects/shared/toolchains/llvm-7.0.darwin-release-x86_64/install)
SET(CLANG ${LLVM_DIR}/bin/clang)
SET(CLANGXX ${LLVM_DIR}/bin/clang++)

# Specify compiler (which is clang)
SET(CMAKE_C_COMPILER   ${CLANG})
SET(CMAKE_CXX_COMPILER ${CLANGXX})

# Specify binutils

SET (CMAKE_AR      "${LLVM_DIR}/bin/llvm-ar" CACHE FILEPATH "Archiver")
SET (CMAKE_LINKER  "${LLVM_DIR}/bin/llvm-ld" CACHE FILEPATH "Linker")
SET (CMAKE_NM      "${LLVM_DIR}/bin/llvm-nm" CACHE FILEPATH "NM")
SET (CMAKE_OBJDUMP "${LLVM_DIR}/bin/llvm-objdump" CACHE FILEPATH "Objdump")
SET (CMAKE_RANLIB  "${LLVM_DIR}/bin/llvm-ranlib" CACHE FILEPATH "ranlib")

# You may use legacy binutils though.
#SET(BINUTILS /usr/local/Cellar/arm-linux-gnueabihf-binutils/2.31.1)
#SET (CMAKE_AR      "${BINUTILS}/bin/${TARGET_TRIPLE}-ar" CACHE FILEPATH "Archiver")
#SET (CMAKE_LINKER  "${BINUTILS}/bin/${TARGET_TRIPLE}-ld" CACHE FILEPATH "Linker")
#SET (CMAKE_NM      "${BINUTILS}/bin/${TARGET_TRIPLE}-nm" CACHE FILEPATH "NM")
#SET (CMAKE_OBJDUMP "${BINUTILS}/bin/${TARGET_TRIPLE}-objdump" CACHE FILEPATH "Objdump")
#SET (CMAKE_RANLIB  "${BINUTILS}/bin/${TARGET_TRIPLE}-ranlib" CACHE FILEPATH "ranlib")

# Specify sysroot (almost same as rootfs)
SET(CMAKE_SYSROOT ${TARGET_ROOTFS})
SET(CMAKE_FIND_ROOT_PATH ${TARGET_ROOTFS})

# Specify lookup methods for cmake
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# Sometimes you also need this:
# set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Specify raspberry triple
set(CROSS_FLAGS "--target=${TARGET_TRIPLE}")

# Specify other raspberry related flags
set(RASP_FLAGS "-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS")

# Gather and distribute flags specified at prev steps.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")

# Use clang linker. Why?
# Well, you may install custom arm-linux-gnueabihf binutils,
# but then, you also need to recompile clang, with customized triple;
# otherwise clang will try to use host 'ld' for linking,
# so... use clang linker.
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld)

Sometimes you need to run “cmake” twice, for first compilation gives you this:

error: invalid linker name in argument '-fuse-ld=lld;-fuse-ld=lld'

I have no idea why that happens. Rerunning cmake really helps.

Ok, that’s it.

Message me if you feel lonely dude, I’m still on it, it will try to help!

О запрете Telegram, для Павла Дурова и его друзей

Информационный газ

…Или – просто несколько мыслей, в надежде что они всё-таки достигнут адресатов когда-нибудь.
Читатель, стой! Текст может показаться крайне заумным и нудным, а кому-то  еще и банальным.

Формы разума

Наша планета населена как минимум двумя видами существ. Первые – это мы, люди. Вторые – это наши колонии, цивилизации. Колония живых существ включает в себя также и среду обитания. И если среда меняется, то меняется и сама колония. Если среда меняется быстро, то погибает одна колония и через некоторое время на ее месте возникает другая (если только все муравьи люди к этому времени не передохнут).
Застой также вреден, поскольку именно он является причиной будущих резких перемен (октябрь 17-го года?).
Информационный газ. Сам только что придумал 🙂 Если считать каждое отдельное сообщение частицей информации, то совокупность этих частиц с учетом их скорости и направления – информационный газ.
Telegram, и все остальные мессенджеры повышают температуру этого газа. И в конечном счёте, современные правительства , скорее всего, все до единого сварятся в этой новой враждебной для них среде. То, что они пытаются делать сейчас – это контролировать температуру собственного тела. Можно объяснить немного иначе.
Государство как колония обладает своим собственным сознанием, складывающимся из интересов и конфликтов правящих элит, связей между ними, связей со всеми остальными людьми и т.д. Так вот изменение условий приведет к тому, что связь между “остальными” людьми станет такой же тесной как и внутри круга элит. Когда станет невозможным скрывать какую-то правду или преподносить ложь, элита перестанет быть таковой, и колония как единый живой организм будет расщеплена.
В принципе все. Дальше возможны варианты. В настоящий момент вот думаю какой вариант меньше всего навредит людям.

Варианты, “о жизни вселенной и вообще”

Вред и благо понятия субъективные. Лично я считаю благом возможность увеличивать свое знание, находясь при этом в состоянии душевного равновесия. Но в общем случае – это удовлетворение любопытства. К этому стремятся не только ученые, но и блондинки, мечтающие о Бали, по которым гуляли бы сильные кубинцы с толстым кошельком 🙂 Всеми нами в конечном счёте правит любопытство. И по его качеству можно судить о состоянии разума, который его испытывает.
С другой стороны мы снисходительно смотрим на животных которые иногда хотят быть умными, но все равно остаются глупее большинства людей, и презираем людей, которых интересует только секс и еда. Это я к тому что иногда развитие достигает локального максимума, из которого сложно выбраться. Но что есть максимум, а что минимум? Кто лучше: блондинка или искатель истины, или собака?
Кто-то однажды сказал, что каждая форма жизни старается поддерживать сама себя в условиях изменчивой среды. И в этом смысле, блондинки иногда справляются лучше чем мыслители 🙂
Так что выбор направления градиента вещь важная но совсем неоднозначная.

К нашим баранам

Что случится при формировании идеальной среды для общения каждого с каждым. Температура информационного газа вырастет. И колонии начнут перерождаться. И что будет дальше?
1. В одном Температура информационного газа спадет, и мы вернемся к прежнему строю. Интернет умрет.. на время. Благо или вред?
2. Отдельные ткани современных колоний, а может быть и отдельные колонии целиком сумеют приспособиться к новым температурам. Б или В?
3. Первый и второй варианты вперемешку: где-то так, где-то эдак.
В общем я периодически возвращаюсь к мыслям о благе и вреде, и потом обратно к этим трем пунктам.
Писал ночью с телефона, с включенным т9. Так что простите за возможные опечатки.

Machine FP partial invariance issue

Invariance issue

In computer representation:

“a + b + c” and “a + c + b” is not the same!
(and not the samefor multiplicationas well).

Hallelujah! I finally got that simple fact! After so many years of working in IT industry and software development!Well, Ikind of knew this, but never took it seriously until recently
If you guys are curious how ape dealt with getting bananatask
If you are same late as I am, read bellow.

Floating point machine representation

Usuallyfloating point number is represented as follows:
v = m * (be)

Where

m– is the mantissa, an integer with limited range. For example, for decimal numbers it could be in range from 0 to 99. For 24 bit binary numbers it is in range from 0 to (224-1), or from 0 to 16777215.
b– is the base, usually b = 2, an integer value,
e– is exponent, integer, it could take both negative and positive values.
For example in decimal numbers representation 0.5 is represented as:
0.5 = 5 * 10-1 (here m=5, b=10, e=-1)
For binary numbers 0.5 is 2-1 (m=1, b=2, e=-1)

Some people know, that in order to store bigger numbers we need more space in memory. But bigger precision also requires more memory, for we need mantissa of greater width, and thus we also need more bits to store it.

Integer vs float

While working with regular integer numbers we also having data loss and overflow issues, and yet we’re able to control it. We keep in mind minimum and maximum possible integer results, and this know when overflow might happen.
Floating point numbers is different. AFAIK no sane people control mantissa overflow, except perhaps some really rare cases. So here, better to think it just happens all the time.

Inevitable data loss

It is impossible to store numbers with infinite precision, and thus, data loss is inevitable. It’s obvious, but easy to miss if you had never dealt with some cases.
We can’t work with exact real number “N”…
We only able to work with its nearest machine floating pointrepresentation, fp(N) or:
N* = fp(N)

For mantissa in range 0 .. 999 we have next errors.
Number9999will be stored as
v = fp(9999) = 999e+1 = 9990
(here we lost info about most right “9”)

and number1.001will be stored just as
v = fp(1.001)=1
(here we lost info about most right “1”)

a + b + c

Actually v = a + b + c is performed in two steps:
Step 1: x = a + b
Step 2: v = x + c
Or with respect to fp transformation:
Step 1: x = fp(a + b)
Step 2: v = fp(x + c)
By changing the order of sum components, we in fact change what we’re going to loss on each step. And by changing order of band c we get different data loss, just like a final result.

Examples

Let’s demonstrate it on the next example.
  • mantissa can store up to 2 decimal digits, and thus in range 0 .. 99.
  • base is 10.
  • exponent could be any, for it doesn’t matter here really.
Let’s use values:
a = 99 (m=99, e = 0)
b = 10 (m=1, e = 1)
c = 1 (m=1, e = 0)
And consider the difference of “a+b+c” and “a+c+b”:
a + b +c:
fp(a+b) = fp(99+10) = fp(109) = 100
v = fp( fp(a+b) + c ) = fp(100 + 1) = fp(101) = 100

a + c + b:
fp(a+c) = fp(99+1) = fp(100) = 100
v = fp( fp(a+c) + b ) = fp(100 + 10) = fp(110) = 110
Unbelievable for regular people, but so obvious to programmers (and yet unbelievable):
(a + b + c = 100) ≠ (a + c + b = 110)

Well, to be more correct:
( fp(a + b + c) = 100 ) ≠ ( fp(a + c + b) = 110)

Upd:

As one of solutions, wider mantissa should be used for result, and only after all operation items participated in result, it then may be truncated to fp number with thinner mantissa.
If items have mantissa of N bits, then

  • for sum of M+1 items result should have M+N  bits mantissa,
  • for multiplication of M items result should have M*N bits mantissa.

Real example written on C is below.


example.c

#include 

// Helpers declaration, for implementation scroll down
float getAllOnes(unsigned bits);
unsigned getmantissasaBits();

int main() {

// Determine mantissasa size in bits
unsigned mantissasaBits = getmantissasaBits();

// Considering mantissasa has only 3 bits, we would then need:
// a = 0b10 m=1, e=1
// b = 0b110 m=11, e=1
// c = 0b1000 m=1, e=3

float a = 2,
b = getAllOnes(mantissasaBits) - 1,
c = b + 1;

float ab = a + b;
float ac = a + c;

float abc = a + b + c;
float acb = a + c + b;

printf("n"
"FP partial invariance issue demo:n"
"n"
"mantissasa size = %i bitsn"
"n"
"a = %.1fn"
"b = %.1fn"
"c = %.1fn"
"(a+b) result: %.1fn"
"(a+c) result: %.1fn"
"(a + b + c) result: %.1fn"
"(a + c + b) result: %.1fn"
"---------------------------------n"
"diff(a + b + c, a + c + b) = %.1fnn",
mantissasaBits,
a, b, c,
ab, ac,
abc, acb,
abc - acb);

return 1;
}

// Helpers

float getAllOnes(unsigned bits) {
return (unsigned)((1 << bits) - 1);
}

unsigned getmantissasaBits() {

unsigned sz = 1;
unsigned unbeleivableHugeSize = 1024;
float allOnes = 1;

for (;sz != unbeleivableHugeSize &&
allOnes + 1 != allOnes;
allOnes = getAllOnes(++sz)
) {}

return sz-1;
}

Output

FP partial invariance issue demo:

mantissasa size = 24 bits

a = 2.0
b = 16777214.0
c = 16777215.0
(a+b) result: 16777216.0
(a+c) result: 16777216.0
(a + b + c) result: 33554432.0
(a + c + b) result: 33554430.0
---------------------------------
diff(a + b + c, a + c + b) = 2.0

Stepan Dyatkovskiy: experience, vids, articles and other!