[C++] What is copy_elision and why you should know about it

In the C++ world, copy_elision is a compiler optimization.

Prior to C++11, there was no copy_elision, so when you write code like this...

Person makePerson() {
    Person p();
    p.name = "Bob";
    return p;
}

... the compiler creates a Person object in the makePerson stack frame and is copied/moved to the caller's stack after makePerson finshes.

But with with copy_elision, the compiler optimizes the process and rather than a move/copy, compiler sets the address of makePerson's Person directly to the return address. In other words, there is no move/copy.

Explained by the official website https://en.cppreference.com/w/cpp/language/copy_elision

The objects are constructed directly into the storage where they would otherwise be copied/moved to.

This optimization is usually unnoticed.

Great! So what? Why do I need to care about this?

Tl;dr: When you lie to the compiler.

As a general rule: if you lie to the compiler, there lies bugs, undefined behavior, and probably stack smashing.

Let me tell a story about using ROS.

ROS creates a layer of abstraction for inter process communication (IPC) with sockets, in a publisher/subscriber model.

The ROS semantics for a subscriber is very overloaded, as in there are many definitions of "subscribe".

http://docs.ros.org/lunar/api/roscpp/html/classros_1_1NodeHandle.html

Here's what happened.

I defined an Object and created a callback. E.g. Cards object and callback_add_card(Card newCard).

Important: The callback returned an int. E.g. "int callback_add_card".
This leads me to make a mistake... We shall see why later.

I constructed the object and passed that object's callback to ROS subscribe.

But ROS's subscribe definition expected (void*) function pointer.
I.e. void callback_add_card was acceptable but int callback_add_card is not.
So I lied to the compiler and cast this to a void*. Subtle mistake. Won't show up until later.

#define callback_add_card_fn (void (Cards::*)(const Card&))

nodeHandle.subscribe("/cards/add", subscribeQueueSize, callback_add_card_fn &Cards::callback_add_card, &my_cards);

The compiler was happy and compiled. Because the "#define cb_car_speed ..." told the compiler to treat the function as void.

Code mostly worked fine.

Because an int is relatively small (byte), there appears to be no bugs because the stack smashing wasn't obvious.

Sometime later, I changed the return type.
From int callback_add_card to Card callback_add_card.
Because why not just return the Card instead? So I can write some test code and see if the Card is correct.

Well! Now we have big trouble.

The compiler was told this callback_add_card had void return type. So compiler did not allocate any space for a return value. And because of copy_elison, the compiler had generated code for callback_add_card "directly into the storage where they would otherwise be copied/moved to."

In other words, calling callback_add_card smashes the stack of the caller. Because the caller expected void return value, and no spaces was allocated. But the copy_elison code constructed the Card object in the caller's stack frame!

So how do we get around this? How to have a callback that returns some value, but still call the ROS subscribe properly?

Answer: By wrapping the call in a lambda, creating a closure. The lambda returns no value, so it's a void function. But the lambda can capture context. E.g.

nodeHandle.subscribe<Card>("/cards/add", subscribeQueueSize, [&my_cards](Card newCard) {
  cout << "the card added is: " << my_cards.callback_add_card() << "\n";
});

Connect Bose QC35 to Ubuntu 16.04

1 /etc/bluetooth/main.conf

# Restricts all controllers to the specified transport. Default value
# is “dual”, i.e. both BR/EDR and LE enabled (when supported by the HW).
# Possible values: “dual”, “bredr”, “le”
ControllerMode = bredr

Restart bluethooth service afterwards: sudo /etc/init.d/bluetooth restart

After the pairing you may put the config back to “dual”.  Only pairing seems to be affected.

2 Headphones to pair mode

Slide button 2s or use their app (assuming already paired with your phone).

3 Settings -> Bluetooth -> +

Click on PIN options and select Fixed PIN Do not pair.

4 Connect again in side bar

5 Sound setting to High Fidelity

2020 Goals

What do I want to accomplish in 2020?

  • Contribute 1 pull request to PDAL github repo, about lidar processing.
  • Build passive income system.
  • Applied for visas.
  • Read 10 self-improvement books.

3D Face Model Generation

A useful tool was recommended to me by a former coworker who works at this new startup called Bellus3d. They use the depth sensor in the iPhone (with face ID logins) along with the camera and generate this model. Their app looks good. Easy to use.

They had a web UI to view the model in 3D. You can move it around.

I could import this to Autodesk Meshmixer and 3D print it.

There are 46,000 vertices and 90,000 triangles. My 3d printer isn't all that accurate, I get an effective resolution of 1.0mm to 1.5mm, so I am going to reduce complexity. It also helps reduce filament threads. See https://re3d.org/reduce-stl-triangles-using-autodesk-meshmixer/

Edit -> Make Solid. Collapse triangle mesh. I use cell size of 1.8mm and mesh density 1.4mm.

2D Photos to 3D model

Came across some photogrammetry software lately. I had an idea to try them out by taking a bunch of photos and generate a 3d model.

But it's difficult. Tools I tried were COLMAP and visualSFM. Seems to be bad results. I think I had insufficient number of photos, and there weren't enough correlated features.

I thought "well what if I used a video", so I took a video of my mouse, and dump them into images.

But a lot of them were blurry, like this.

So I thought there should be a way to filter out the blurry images. Such as using

  • Fast Fourier Transform
  • Laplace (or LoG) filter

There were some suggestions on StackOverflow that hint OpenCV is a good tool. I found some blurry detector on github https://github.com/indyka/blur-detection but there was some issues. For one, the threshold computed varied too greatly and so I had to manually figure out what were the 80th percentile and better (sharper, higher score) images. But some images contained no content, such as a blank table. It would be classified as sharp... so if going down this method, you might want to remove those blank images.

Install Nvidia GTX 2080 driver on Ubuntu 16.04

  1. sudo vim /etc/default/grub # to change "quiet splash" to "quiet nosplash"
  2. sudo update-grub
  3. reboot
  4. (Press ESC)
  5. Select ubuntu recovery mode, enable networking, then root terminal.
  6. sudo add-apt-repository ppa:graphics-drivers (if you haven't already)
  7. sudo apt purge nvidia* (if you tried installing already)
  8. sudo apt install nvidia-418 (nvidia-430 doesn't work with lightdm yet)
  9. You may need to sudo systemctl stop lightdm
  10. nvidia-smi (check your version is correct)

3D Statue of Liberty

I take aerial lidar point cloud and turn it into a 3D object.
https://www.thingiverse.com/thing:3615141

With Meshmixer, there is a great option in "Edit" > "Make Solid" and it generated this for me. Well done! Exactly what I was looking for. Otherwise it prints as hollow.

Have to fill in holes here

After some sculpting...

The Meshmixer tools are way more intuitive to use than Blender or anything else for that matter!

I didn't notice but the bottom is not completely flat. As I printed this out. There was a power interruption when I used the pressure washer it jumped the breaker. Here's the result.

There are also too many polygons with the original. 83,172 Verticies and 166,308 Faces. Using MeshMixer I could reduce verticies to 21,141 and faces 42,282. This lower poly count object should print cleaner too. Notice the surface.

Obviously the wood print failed. But I am happy with the white result!