CS249r Final Project: The Saga of DeepMimic, Dance Dance Robot, and Quadraped Pose Estimation

This blog post is under construction, pending getting DeepPoseCut to train. For now, please see the posts

http://orangenarwhals.com/hexblog/2019/12/06/CS249r-further-research/

http://orangenarwhals.com/hexblog/2019/12/04/249r/

These are on my secondary blog which consists of me taking notes for myself, essentially, and are not cleaned up, but reflect some of the effort put into this project. They reflect the failed attempts to set up DeepMimic and in particular Motion_Reconstruction from the Skills From Video paper, which relies on several third-party libraries in horrible recursive/nesting structure of poorly documented repositories.

Not super proud of the work, but here’s the poster summarizing it. Just didn’t have time…

Full size Poster:

https://github.com/nouyang/cs249r_finalproject/blob/master/poster.png

Stereo

Annotation

  • “Using DeepLabCut for 3D markerless pose … – bioRxiv.” 24 Nov. 2018, https://www.biorxiv.org/content/10.1101/476531v1. Accessed 9 Dec. 2019.

Closeup of video, dog 1

Dog 2, checkerboard

 

BVH Player / mocap quadraped exists! Loaded data from AI4Animation 2018 SIGGRAPH paper

 

 

Links

  • “AI4Animation/ReadMe.txt at master · sebastianstarke … – GitHub.” https://github.com/sebastianstarke/AI4Animation/blob/master/AI4Animation/Assets/Demo/SIGGRAPH_2018/ReadMe.txt. Accessed 9 Dec. 2019.
  • “BVH player.” http://lo-th.github.io/olympe/BVH_player.html. Accessed 9 Dec. 2019.

 

 

Knitted radios and related knitting magic

Wow this post has spent a year in the drafts bin (since october 2018, and I first looked into this in 2017…), so I’m kicking it out as-is. I’ll update it later with moar pics ™:

In this week’s continued effort to clear out my back log of super-old blog post drafts, today we’ll talk about knitted radios.

You: Wait what, knitted radios?

Me: Yup, you heard me right. Knitted radios! First created in 2012, and then later in 2014 reincarnated as a sweater. Created by Ebru Kurbak and Irene Posch. To clarify, the knitted parts are the resistors, capacitors, and inductors (coils); the non-knit parts are the transistor, battery, and audio source. Since then, I believe they’ve also done work into making textile relays, switches, and logic gates.

Drapery FM 2012  ( Installation description from v2.nl )

Drapery FM (2012) is an audio-tactile installation by Ebru Kurbak and Irene Posch.

Drapery FM consists of a knitted piece of fabric that can electronically communicate the story of how it has been made to and through the surrounding radio receivers. The piece of fabric is essentially a micro FM transmitter that is, for the most part, made from copper wire and wool. Tuned into the right radio frequency, radios within the transmission range of this fabric receive and play out the sound recordings made during its production.

The installation proposes an atmospheric space made of airwaves. In tuning in with their personal radio receivers, moving in space or touching the fabric, participants can explore the spatial boundaries and haptic qualities of the installation. In the presence of a knitted electronic object viewers are invited to fantasize an alternative reality and speculate. What if, instead of purchasing hardware electronics we could directly knit them from scratch in our homes? In an imaginary world of home knitted electronics, how would we relate to our devices? Would we mend them with crossing threads for repair? Would we protect them with lavender sachets instead of silica gel? How would this alternation shift the way we value and prize materials, natural resources, geographical locations, personality traits, physical skills, and qualifications.

Technically, the underlying circuit is an adaption from Tetsuo Kogawa’s schematic of the “Simplest Radio FM Transmitter”. However, distinctively, electronic parts used as capacitors, resistors and the coil are made by knitting ordinary yarns together with electronically conductive yarns in deliberate configurations and patterns. Visually, the textile contains references to the ancient radio grill clothes that covered antique radios in the early 20th century.

Materials: Wool, Cotton, Copper, Silver, Stainless Steel, Silk, BC337 Transistor, 12V Power Supply, Audio Source, Radios.

Source: http://v2.nl/archive/works/drapery-fm

 

More about Drapery FM

A lot of pictures: http://v2.nl/files/2012/works/drapery-fm-documentation

General experiments

For more details, we turn to websites specific to the project.

Stitching Worlds is an artistic research project funded by the Austrian Science Fund (FWF): AR 284-G21 in the Programme for Arts-Based Research (PEEK).The project was carried out between May 2014 and June 2018 at the Department of Industrial Design 2, University of Applied Arts Vienna.

http://www.stitchingworlds.net/category/experimentation/

Email to MITERS I compiled this in, for my reference

social media unhappiness and the pleasure of ghosting

I. Up until yesterday, I was going to be a teaching assistant for the Science of Happiness. Part of the “why” for teaching the class that the professor gave was that, since 2012, there seems to be accelerating levels of anxiety and stress in the undergraduate population. Still, I’ve done the readings for the first few lectures,

II. I thought I’d escaped the “social media anxiety” clusterfk, since I almost never check Facebook, instead sticking to Messenger and other 1-on-1 conversations.

III. News articles reported that reading other people’s happy stories made people unhappy; my responsive was to aggressively share all my failures. I felt validated when I saw that other people were in fact forming spontaneous gatherings to share startup failures.

IV. Yesterday a friend told me that I was basically live-tweeting my life at them, and it was stressing them out.

Turns out I was causing other people anxiety — I was contributing to the social media anxiety circle! This caused me to take a step back and realize I was also feeling a great deal of anxiety talking to all my friends online. Somehow my rat brain had decided that if someone had read a message (per read receipt) and didn’t respond within an hour or twelve, PROBABLY THEY HATED ME FOREVER.

VI. With any sort of introspection, I’d probably say my anxiety about communication frequency mismatches started with my first pseudo-relationship (my first love!) where my ex just ghosted me instead of being up-front and ending the relationship.

But you know what? We’re still friends, and pretty good ones at that, some years later.

So even if my friends read all my posts and yet never respond to me, we’re almost certainly still friends and would be warm toward each other in real life.

To be fair, it wasn’t just my ex ghosting me, —
actually, I won’t post what other bad things have happened to me, since I can feel my own anxiety levels rising just thinking about them.

VII. Earlier today I impulsively uninstalled or otherwise hid all my chat apps (signal, hangouts, whatsapp, and my two messenger accounts I use in mobile browsers) from my phone today. I also uninstalled pidgin on my laptop, which is my conduit to hangouts and messenger on desktop.

(I did forget to get my Signal passcode before I impulsively uninstalled it, so my 2GB backup file is worthless now. But, who really needs that history anyway!)

And wow! I’ve found ghosting people to be really pleasant and enjoyable on the other side. It’s really nice to clear my head of six ongoing asychronous conversations and their respective statuses in my head, and feel the solid bedrock of my friendships with people underneath all the noise.

To be fair, I’m not sure how pleasant this would be outside of classes. As school has started, I’ve gotten a lot more in-person social time with people I actually enjoy hanging out with. The regularity of that contact, as well as the camaraderie of working together in classes, has been really nice for me. I realized I haven’t had that in my actual work (research), and was constantly flailing around anxiously in search of it.

Yea, it actually feels really, really nice to have hours of regular, pleasant, in-person human interaction replace my anxiety-riddled online texting of friends.

VIII. Here’s a nice song summarizing this blog post:
“Lewberger – Facebook Break Official Music Video”

In particular, the “six hours” part 🙂

Keeping my Thinkpad battery ship-shape on Ubuntu (19.10)

Recently, I felt like my laptop battery (Lenovo Thinkpad) was draining a lot faster than before. I’m not sure if something triggered a particular spike, but I looked into it and found it’s really easy for me to adopt better battery practices on Ubuntu.

First, to find out just how sad my battery is, I used the command

upower -i $(upower -e | grep '/battery')
  native-path:          BAT0
  vendor:               LGC
  model:                01AV457
  serial:               969
  power supply:         yes
  updated:              Wed 07 Aug 2019 01:56:41 PM ADT (40 seconds ago)
  has history:          yes
  has statistics:       yes
  battery
    present:             yes
    rechargeable:        yes
    state:               discharging
    warning-level:       none
    energy:              28.85 Wh
    energy-empty:        0 Wh
    energy-full:         40.02 Wh
    energy-full-design:  56 Wh
    energy-rate:         7.468 W
    voltage:             15.958 V
    time to empty:       3.9 hours
    percentage:          72%
    capacity:            70.8929%
    technology:          lithium-polymer
    icon-name:          'battery-full-symbolic'
  History (charge):
    1565197001	72.000	discharging
  History (rate):
    1565197001	7.468	discharging

My full battery is 56 Wh, and now it’s only 40 Wh two years in! Nearly a (16/56) = 30% decrease!

Whew. That means if I had 6.5 hours of battery life before, now I have only 5 hours.

So, I looked up online. The key things to do are

1) Change the threshold for starting/stopping battery charging, to stop the battery from charging to 100%
2) Keep the laptop plugged in more, and
3) Keep the laptop cool

Guess I need to figure out a way to use my laptop in bed without setting it on the blankets. Or, get a proper desk and table.

Here’s the deets.

From https://forums.lenovo.com/t5/Welcome-FAQs-Knowledge-Base/How-can-I-increase-battery-life-ThinkPad/ta-p/244800:

For maximum lifespan if you rarely use the battery, set Custom charge thresholds to start charging at 40% capacity and stop at 50%, and keep the ThinkPad cool. The thresholds can be adjusted in the Battery Maintenance settings of the Lenovo Power Manager.

If you do use your battery somewhat frequently, set the start threshold at say 85% and stop at 90%. This will still give a good lifespan benefit over keeping it charged to 100%.

The simplest way to optimize for battery lifespan is to select Automatic in the Power Manager Battery Maintenance settings, and let it manage your battery charge thresholds for you.

And from https://forums.lenovo.com/t5/Lenovo-IdeaPad-1xx-3xx-5xx-7xx/maintaining-battery-capacity-on-ideapad-530s-laptop/td-p/4282652:

About battery discharge, it is better not to allow battery to reach full discharge before recharging it. Best care for Li battery is keeping it between 20-80 %. Avoid low discharge and overcharge . Battery drain should only be done to calibrate wrong battery recognition or if there is a battery problem.
Now, how to do this in Ubuntu? Turns out it’s really easy for thinkpads.
https://linrunner.de/en/tlp/docs/tlp-linux-advanced-power-management.html

Note: TLP and ThinkPad-related packages below are available via the official Ubuntu repository. Nevertheless it is recommended to use the PPA to stay with the latest TLP version.

sudo add-apt-repository ppa:linrunner/tlp
sudo apt-get update 
sudo apt-get install tlp tlp-rdw 
sudo apt-get install tp-smapi-dkms acpi-call-dkms
rui@chaiX1YG2:~$ sudo tlp setcharge 70 90 BAT0
Setting temporary charge thresholds for BAT0:
  stop  = 90
  start = 70
rui@chaiX1YG2:~$ sudo tlp start
TLP started in battery mode

Or, for a permanent change, edit the file “/etc/default/tlp

rui@chaiX1YG2:~$ sudo vi /etc/default/tlp

And uncomment the lines (around line 273)

START_CHARGE_THRESH_BAT0=75                                                   
STOP_CHARGE_THRESH_BAT0=80

setting the thresholds to whatever you think is best.

Shortly before I head out, I’ll probably run
sudo tlp setcharge 70 80 BAT0
since 3 to 4 hours of battery life is plenty for me. But I do want to be conservative since my power button no longer works, so if it completely dies then I have to unscrew the back cover and unplug the battery + CMOS battery briefly, then plug in/screw in/plug in power charger in order to start it again. I really only have myself to blame, not thinkpad — I’m sure it has something to do with shorting 24V / 3 amps through the USB port when I was working on motor controller things for my final project in underactuated robotics. Yea… that wasn’t great, and I’m really impressed the laptop survived and the USB port even still works!

[END]

Bash timer script (for pomodoro / general use)

Whew every so often I feel very self conscious about my blog, especially the previous very messy half-notes post, so here is a nice clean code snippet to refresh the palate:

From 1 minute timer

 

# script to create timer in terminal
# Jason Atwood
# 2013/6/22

# Edited: Nouyang, 2019/08/05
# Added bell sound, speech of "your time is up", & popup notification
# Added bigger font option, window resizing
# And changed colors: red background by default, flashing green for time's up 
# Usage: `./terminalTimer.sh 25` & set terminal to "always on top" and "always on visible workspace"

# start up 
#echo "starting timer script ..." 
#sleep 1 # seconds

# get input from user
if [[ $1 ]]; then
    DURATION=$1
else
    read -p "Timer for how many minutes? (Default 25) " -e DURATION 
    #read -p "Timer for how many minutes? " -i 25 -e DURATION 
    if [[ !DURATION ]]; then
        DURATION=25
    fi
fi
DURATION=$(( $DURATION*60 )) # convert minutes to seconds

# get start time
START=$(date +%s)
			
setterm -term linux -back red -fore white # use setterm to change background color
printf '\e[8;4;1t'

# infinite loop
while [ -1 ]; do

	# do math	
	NOW=$(date +%s)				# get time now in seconds
	DIF=$(( $NOW-$START ))			# compute diff in seconds
	ELAPSE=$(( $DURATION-$DIF ))		# compute elapsed time in seconds
	MINS=$(( $ELAPSE/60 ))			# convert to minutes... (dumps remainder from division)
	SECS=$(( $ELAPSE - ($MINS*60) )) 	# ... and seconds

	# conditional
	if [ $MINS == 0 ] && [ $SECS == 0 ]	# if mins = 0 and secs = 0 (i.e. if time expired)
	then 					# blink screen
        clear;
        #zenity --info --text "$(date);$(pwd)"
        notify-send "Time's up! $((DURATION/60)) minutes"
        #spd-say ""
        #spd-say "Your time is up! $((DURATION/60)) minutes"
        echo "Your time is up! $((DURATION/60)) minutes" | festival --tts

        play "./Computer_Magic.wav"
		for i in `seq 1 180`;    		# for i = 1:180 (i.e. 180 seconds)
		do
			clear					# flash on
			setterm -term linux -back green -fore white # use setterm to change background color
			echo "00:00                             		" # extra tabs for visibiltiy

			sleep 0.5

			clear					# flash off
			setterm -term linux -default		# clear setterm changes from above 
			echo "00:00" 				# (i.e. go back to white text on black background)
			sleep 0.5	
		done  					# end for loop 
		break					# end script

	else 					# else, time is not expired
        OUTPUT=$(clear; echo "$MINS:$SECS" | toilet -f future --filter crop ) # display time
        #OUTPUT=$(clear; echo "$MINS:$SECS" | toilet -f mono12 --filter crop ) # display time
        echo "$OUTPUT"
		sleep 1 # sleep 1 second
	fi					# end if
done	# end while loop	

To run, use

$ ./terminalTimer 25 # in minutes

What it looks like while running:

From 3 minute timer

Replicating the Visual Pushing and Grasping Paper Pt 1: Calibration

Quick note: This post is more a build log of how I got the calibration and grasping parts of the code base working, moreso than replication of the results; as I am not working with the pushing part.

 

I’m working on a summer project [1] building on a project by some Princeton folks called TossingBot. The idea is nice: combine a simple physics model with a network that learns a residual to add (or subtract) onto the single control parameter (thrown velocity), in order to toss arbitrary objects into a desired bin.

Anyway, although the code for the tossing bot paper is not available yet, the same authors released a nice, well commented / documented code repository for their earlier paper, the visual pushing and grasping paper. (I guess, it seemed like they completed part of it during a google internship, so I feel better that I’m being paid far less and cannot spend much time on releasing quality code).

And I actually got it to work! Wow, replicable work. Okay, so I didn’t get it to work in full — but I do have a vastly simplified version of their code working on my ur5, with a d415 camera, and a different gripper — and by using their pre-trained model out of the box! It outputs grasp predictions, and the ur5 moves to different locations where there are actually objects, picks them up, and then drops them.

I had to solve a few issues to get to this point, so I’ll outline here and explain in more detail later (hopefully — again time is short). Perhaps the most broadly applicable is my understanding of their calibration code.

Relevant links:
https://tossingbot.cs.princeton.edu/
http://vpg.cs.princeton.edu/
https://github.com/andyzeng/visual-pushing-grasping

What I did the last 10 days:

SOFTWARE

  1. Installed 18.04.1 on the lab computer
  2. Installed ROS — This is actually not needed for the VPG code, which has removed ROS as a dependency

Re: ROS, I also learned a hard lesson — checkout the right branch for your ROS packages. e.g. Kinetic Karma or Melodic whatever.  Otherwise will get a ton of errors.

GRIPPER

I used a different gripper than the one used in the paper, so I needed to rewrite portions of the code.

1. Attached robotiq gripper to the robot arm, and got it functional.
1a. Required low profile screws of a short length (8mm) that I couldn’t find in the lab at first.

1b. Got it working directly with the teach pendant.
1b. There is a serial to USB converter which for me happened to be inside the ur5 control box. I unplugged that and plugged it into my desktop (presumably, you could control the gripper directly from the ur5 interface when it’s plugged into the ur5 usb ports).
1c. Got it working with ROS. To be hones, this was a majoorrr pain. I kept getting all sorts of weird errors.
ow, instead, I talk to it directly in python, bypassing ROS entirely. Read the robotiq manuals which give a clear command example.

Relevant links:
https://blog.robotiq.com/controlling-the-robotiq-2f-gripper-with-modbus-commands-in-python
(mostly, just something like `ser.write(“\x09\x03\x07\xD0\x00\x03\x04\x0E”)` )

REALSENSE

Due to using a different version of Ubuntu, I had to a bit of experimenting to install the realsense drivers (which are from Intel, and separate from the VPG codebase).

First off, I had a Realsense D435, and opted to buy a D415 as in the paper, since the D415 is better for static scenarios where precision is more important. And it does seem to perform a lot better on the tabletop by default.

 

 

1. Attempted to install realsense-viewer on my ubuntu 19.10 install. Apparently the deb install only works with a much older version of the linux kernel — thus, started patching things and compiling from source. Did things like patch the patches, since the patches were for 18.04.2 and not… 19.10… I did get it working, but my main lesson was to install 18.04.1 on the ur5 desktop.

Relevant links:

  • Debug log http://orangenarwhals.com/hexblog/2019/06/11/realsense/
  • Start here https://github.com/IntelRealSense/librealsense/blob/development/doc/distribution_linux.md
  • Fail, start to compile from source https://github.com/IntelRealSense/librealsense/blob/development/doc/installation.md
  • See patch script files https://raw.githubusercontent.com/leggedrobotics/librealsense/7183d63720277669aaa540fba94b145c03d864cf/scripts/patch-ubuntu-kernel-4.18.sh

I did also switch from the D435 to the D415 out of a desire to change as little as possible from their setup. (Also, on the Intel website I read that the D435 is better for detecting motion and D415 better for static setups).

UR5

1. Plugged it in
1b. Major lesson: Pendant shows coordinates, the ones in VIEW are different the ones which are reported over serial / you send via python. Have to use dropdown to select BASE.
Additionally, there are two ways to specify configurations which can not be directly mixed and matched. joint config = angle of each of the 6 joints. And the other one is the coordinates (which presumably ur5 has a built-in IK solver and path planner to move to), but note that the final tool position is in axis-angle coordinates, not in rotation of each joint!!! This was super confusing to debug.
2. Learned to use ROS ur_modern_driver and get test_move.py working; ignore the other package — eventually, did not use this since codebase did not need ROS

VPG code

The calibration program outputs the pose of the camera, with which we can transform (shear, rotate, etc.) the acquired depth image into a “birds eye” depth image view.

I learned: use python-urx for debugging (due to upgrade of UR5 firmware itself, from universal robots, the serial communication code of VPG is a bit flaky). The calibrate.py parameters specify checkerboard offset from “tool center” which is defined by the UR5 (by default middle of the outward face of last joint). I documented my work in this github issue. Use the teach pendant to set workspace limits. Use foam to offset z height from table for safety purposes.

Calibration — as copied from github issue —

I’m not sure this is correct, but:

  1. Using the pendant, the limits are the X, Y, Z as displayed under the “TCP” box (it is displayed in mm; the code is in meters).
    e.g.
[[0.4, 0.75], [-0.25, 0.15], [-0.2 + 0.4, -0.1 + 0.4]])  [1]
[minx, max x], [miny, max y], [minz, max z]
  1. This is also just experimentally measured. I’m least certain on this part, but I think it is what the tool would need to do to move to the checkerboard center. So if it needs to move +20cm X – 0.01cm Z to the center of the checkerboard. Presumably the tool center = the middle area of the gripper fingers.

EDIT: Wow not sure what I was thinking, but it’s to the “tool center” of the robot (what is reported on the pendant / over TCP from the UR). And as to the sign of the offset — it’s really checkerboard_pos = tool_pos + offset, so define the offset appropriately. Well, that’s my current belief based on inspecting the code, but maybe I will update the belief tomorrow, who knows. end edit

The readme implies this calibration isn’t so important if you’re using the Intel D415 realsense. For what it’s worth the format of the files is (ignore the actual values)

EDIT: Yup, changed my mind. The calibration actual provides the pose of the camera relative to the robot frame. In this way, the image from the camera, which may be looking at the workspace from the side or at an angle, can be morphed/transformed so that the image is from a perfectly “birds eye” camera. end edit

Also, for starting out, a blank file named camera_depth_scale.txt will suffice to kill errors preventing code run.

real/camera_depth_scale.txt
1.012695312500000000e+00
real/camera_pose.txt
9.968040993643140224e-01 -1.695732684590832429e-02 -7.806431039047095899e-02 6.748152280106306522e-01
5.533242197034894325e-03 -9.602075096454146808e-01 2.792327374276499796e-01 -3.416026459607500732e-01
-7.969297786685919371e-02 -2.787722860809356273e-01 -9.570449528584960008e-01 6.668261082482905833e-01
0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00
  1. Any 4×4 checkerboard will work. I used some online checkerboard generator and then printed it out. e.g. here is one
    4x4

[1] Note that it’s possible the pendant display somehow differs from the actual TCP values — my z-values were 0.07 on the pendant corresponding to 0.47 in python; to debug, can use examples/simple.py https://github.com/SintefManufacturing/python-urx

And more rambling thoughts:
I mostly fussed around with the calibrate.py script for a long time, an entire 1-2 days wasted on the fact that I didn’t realize the pendant coordinates were off by 40 cm on the z axis, so combined with the joint config vs position specification issue, I was confused why the robot was constantly trying to go through the table. I suspected it was something like the z axis issue, but really it was using this library to get the pose out
https://github.com/SintefManufacturing/python-urx/
(such a great library!) that helped me figure it out.

Additionally, the tool offset I wasn’t certain how it worked, until I opened the code. I thought it was literally to where I wanted on the gripper to be the centerpoint, but no, it’s literally to what the UR5 thinks is the centerpoint of its tool, which is what it reports the coordinates of.

I’m currently still having some z-depth issues, so trying to work through the very detailed! parameters given in the paper to see what is going on with that.

USB extension cable — USB 3.0 is quite strange. I spent a long time figuring out that my extension cable looks like a USB 3 cable (blue ends, extra pins) but was behaving as a USB 2.0 extension cable… ordered some off of amazon that did the trick (also lsusb -t was very helpful).

Home position —

It seems that

Here’s a video of what it’s doing for now (I’ll rehost onto youtube for longevity when I get the chance)
https://photos.app.goo.gl/r6vtjPbjLJECjzPd6
And a more exciting dynamic maneuver

And pictures

 

Yesterday, when it was kinda working

Hey look, I selected BASE. T__T

Calibration in progress. With some limits to the movel command, punctuated by “I guess it’s safe *shrug*:

And a blurry picture of my lab. Had to crop out my robot a bit to avoid faces.

Until next time, folks. Hopefully I’ll have a working demo of something of my own soon. Right now, just running a mutilated version of someone else’s code. But happy to working with actual robots again.

conclusion

Okay, that was all a bit rambly. But if anyone has questions, feel free to ask away.

 

Foot notes:

As to my motivation, I’m working on a small summer research project, which I will detail if I end up getting it working in full.

The idea is heavily based off of the tossing bot paper, as I liked the idea of combining a physics baseline with learning of the error (the residuals).

My requirements were:
1. can be finished in 3 months starting from scratch
2. has cool demo (to, for instance, a 10 year old maker faire attendee) — so probably something dynamic, movement-wise
3. research worthy, since my qualification trials are at the end of the summer.

I think I’ll struggle most with the last point, but I’m hoping that in the process of working toward my goal, I’ll think of something that could be tweaked or improved.

Building KiCad 5.1.0 From Source – on Ubuntu 18.04

I encountered quite a few issues compiling KiCad 5.1.0 from source that took me a few hours to debug (some spent napping while things compiled). The whole thing is in the end < 20 lines of bash commands, though compilation took me 2-3 hours.

Here’s a tried-and-true method to get it to install (I tested on a VM). You should probably go straight to “install kicad” section.

From the beginning: Virtualbox

To make sure these instructions worked for 18.04.2, I tested on a clean install inside VirtualBox. Here I write down instructions, since some steps were confusing to me when I used Virtualbox for the first time.

  1. Install virtualbox
    1. I forget which of these I used… either download and double-click the *.deb, from the links at the very top of the page
    2. Or follow the instructions add the PPA and install https://www.virtualbox.org/wiki/Linux_Downloads
  2. Download ubuntu 18.04.2 ISO from https://www.ubuntu.com/download/desktop
  3. Create new VM
    1. Machine > New…
    2. Go though — I used 2048 GB memory and 40 GB virtual (expandable) hard disk
  4. Install Ubuntu into the VM
    1.  Machine > Settings > Storage > Controller: IDE
      1. Click the “+” sign over the CD rom
      2. Choose Disk > Add > (then select your .iso file)
    2. Now click okay. We’re back to the main window — click the big green “Start” arrow.
    3. The VM starts up, and the standard “Install Ubuntu” screen should pop up once booted. Install Ubuntu as normal
      1. Make sure to click “Also install proprietary media” as otherwise “Virtualbox Guest Additions ISO” will later not run
  5. We probably want to copy-paste in commands. Thus, install Guest Additions. This already comes built-in to virtualbox, no need to download anything else
    1. Devices > Insert Guest Additions Add-on Image…
    2. Click “run” when pop-up prompts
      1. If nothing happens, try running from commandline
        cd ~/VBox_GAs_6.0.6
        ./autorun.sh install 
        # This should pop up a second terminal, which asks "Do you wish to continue" > "Yes" 
      2. If not, it’ll probably complain about gcc not being installed; run sudo apt install build-essential
    3. Restart sudo shutdown -r now
    4. Now enable clipboard
      1. Devices > Clipboard > Bidirectional
      2. Also, View > Auto-Resize Display should now work, but I turn it off because if you accidentally resize the window your VM could freeze alarmingly

Install KiCad

First let’s install dependencies

sudo add-apt-repository ppa:js-reynaud/kicad-dev-nightly 
sudo apt-get update
sudo apt-get build-dep kicad

This last command will spit out an error — E: You must put some 'source' URIs in your sources.list — so go to “Software and Updates” and check the “Source Code” on the first tab.  Then again run build-dep, as well as install the other dependencies.

$ sudo apt-get build-dep kicad
$ sudo apt install libglm-dev $ LibGLM
$ sudo apt install liboce-foundation-dev liboce-modeling-dev liboce-ocaf-dev liboce-visualization-dev # OCE files 
$ sudo apt-get install libboost-all-dev #Boost

Install Ngspice from source

This was a pain to figure out, since it would compile for 10 minutes before failing. Basically, can’t skip independently installing the dependencies, even with the build-dep step above. Fortunately easy to install dependencies.

$ sudo apt-get install  autoconf automake bison flex gcc git libtool make  # otherwise get 'yacc' errors
$ cd ~/kicad/scripting/build_tools

$ sudo ./get_libngspice_so.sh 
*** ngspice shared library has been built successfully! 
***Now, to finish the installation run the script as root with 'install' parameter
$ sudo ./get_libngspice_so.sh install
*** Installation completed successfully! *

Note: Why not apt install?  If you just run sudo apt-get install ngspice, later during cmake it will complain about

In file included from /home/lir/kicad/eeschema/sim/ngspice.cpp:28:0:
/home/lir/kicad/eeschema/sim/ngspice.h:31:10: fatal error: ngspice/sharedspice.h: No such file or directory

Probably, there’s some symlink solution, but I’ve spent way too long on this already.

Then, install KiCad itself.

We follow http://docs.kicad-pcb.org/doxygen/md_Documentation_development_compiling.html

git clone -b master https://git.launchpad.net/kicad
cd <your kicad source mirror>
mkdir -p build/release
cd build/release

However, there are some issues (specific to 16.04+ I think) with  wxWidgets and wxPython you really don’t want to. Thus we change the cmake line to add options to ignore scripting and things that require wxWidgets / wxPython:

$ cmake -j2 -DCMAKE_BUILD_TYPE=Release -DKICAD_SCRIPTING=OFF -DKICAD_SCRIPTING_MODULES=OFF -DKICAD_SCRIPTING_WXPYTHON=OFF ../../ 
$ make 
$ sudo make install

Now you should be able to run kicad from the commandline

$ kicad

Pops up a GUI kicad window!

Appendix

make clean

If something isn’t working that you think should, try clearing old files generated by make:

$ make clean # clear files
$ make # then try again 

Note

Useful: You can see what other flags you can provide to cmake (using the -D flag), by peeking at kicad/build/release/CMakeCache.txt

lir@lir-VM:~/kicad/build/release $ vi CMakeCache.txt
[...]
 KICAD_SCRIPTING_WXPYTHON=OFF
[...]

Errors

These are some of the errors I ran into. If you see this, the solution to them is one of the lines above…

ngspice errors

CMake Error at /usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
Could NOT find ngspice (missing: NGSPICE_INCLUDE_DIR)
Call Stack (most recent call first):
/usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
CMakeModules/Findngspice.cmake:57 (find_package_handle_standard_args)
CMakeLists.txt:607 (find_package)

yacc -d -o parse-bison.c parse-bison.y
/bin/bash: yacc: command not found
Makefile:1052: recipe for target 'parse-bison.c' failed
make[3]: *** [parse-bison.c] Error 127
make[3]: Leaving directory '/tmp/libngspice_so/ngspice/src/frontend'
Makefile:773: recipe for target 'install-recursive' failed
make[2]: *** [install-recursive] Error 1
make[2]: Leaving directory '/tmp/libngspice_so/ngspice/src/frontend'
Makefile:1359: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory '/tmp/libngspice_so/ngspice/src'
Makefile:434: recipe for target 'install-recursive' failed
make: *** [install-recursive] Error 1

 

A whole host of wx errors, solved by not using wx ^___^

-- KiCad install dir: </usr/local>
-- Check for installed GLEW -- found
-- Boost version: 1.65.1
-- Found the following Boost libraries:
-- regex
-- Check for installed Python Interpreter -- found
-- Python module install path: lib/python2.7/dist-packages
-- Found wxPython 3.0.2.0/gtk3 (wxWidgets 3.0.2.0)
CMake Error at CMakeLists.txt:780 (message):
Cannot find wxPython.h
    *** Could not run GTK+ test program, checking why...
*** The test program failed to compile or link. See the file config.log for the
*** exact error that occured. This usually means GTK+ is incorrectly installed.
configure: error:
The development files for GTK+ were not found. For GTK+ 2, please
ensure that pkg-config is in the path and that gtk+-2.0.pc is
installed. For GTK+ 1.2 please check that gtk-config is in the path,
and that the version is 1.2.3 or above. Also check that the
libraries returned by 'pkg-config gtk+-2.0 --libs' or 'gtk-config
--libs' are in the LD_LIBRARY_PATH or equivalent.

Error running configure
ERROR: failed building wxWidgets
Traceback (most recent call last):
File "build.py", line 1325, in cmd_build_wx
wxbuild.main(wxDir(), build_options)
File "/tmp/pip-build-v_pIAS/wxpython/buildtools/build_wxwidgets.py", line 373, in main
"Error running configure")
File "/tmp/pip-build-v_pIAS/wxpython/buildtools/build_wxwidgets.py", line 85, in exitIfError
raise builder.BuildError(msg)
BuildError
Finished command: build_wx (4.755s)
Finished command: build (4.755s)
Command '"/usr/bin/python" -u build.py build' failed with exit code 1. [ 78%] Building CXX object pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/swig/pcbnew_scripting_helpers.cpp.o
[ 78%] Building CXX object pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/swig/python_scripting.cpp.o
[ 79%] Built target pcbnew_kiface_objects
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2

wx_python_helpers.cpp:(.text+0x3a1): undefined reference to `PyErr_Occurred'
wx_python_helpers.cpp:(.text+0x5b3): undefined reference to `PyUnicodeUCS4_AsWideChar'
../../pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/__/common/swig/wx_python_helpers.cpp.o: In function `Py2wxString(_object*)':

wx_python_helpers.cpp:(.text+0x929): undefined reference to `PyErr_Clear'
collect2: error: ld returned 1 exit status
qa/pcbnew/CMakeFiles/qa_pcbnew.dir/build.make:929: recipe for target 'qa/pcbnew/qa_pcbnew' failed
make[2]: *** [qa/pcbnew/qa_pcbnew] Error 1
CMakeFiles/Makefile2:3908: recipe for target 'qa/pcbnew/CMakeFiles/qa_pcbnew.dir/all' failed
make[1]: *** [qa/pcbnew/CMakeFiles/qa_pcbnew.dir/all] Error 2
home/lir/kicad/eeschema/dialogs/dialog_spice_model.cpp: In member function ‘bool DIALOG_SPICE_MODEL::addPwlValue(const wxString&, const wxString&)’:
/home/lir/kicad/eeschema/dialogs/dialog_spice_model.cpp:809:70: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
m_pwlValList->SetItemData( idx, *reinterpret_cast<long*>( &timeF ) );
^
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/widgets/tuner_slider.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/widgets/tuner_slider_base.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/dialogs/dialog_page_settings.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/base_screen.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/base_units.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/eda_text.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/page_info.cpp.o
[ 41%] Built target eeschema_kiface_objects
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2 [ 34%] Built target idfcyl
[ 35%] Built target idfrect
[ 36%] Built target dxf2idf
In file included from /home/lir/kicad/eeschema/sim/ngspice.cpp:28:0:
/home/lir/kicad/eeschema/sim/ngspice.h:31:10: fatal error: ngspice/sharedspice.h: No such file or directory
#include <ngspice/sharedspice.h>
^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
eeschema/CMakeFiles/eeschema_kiface_objects.dir/build.make:4709: recipe for target 'eeschema/CMakeFiles/eeschema_kiface_objects.dir/sim/ngspice.cpp.o' failed
make[2]: *** [eeschema/CMakeFiles/eeschema_kiface_objects.dir/sim/ngspice.cpp.o] Error 1
CMakeFiles/Makefile2:1087: recipe for target 'eeschema/CMakeFiles/eeschema_kiface_objects.dir/all' failed
make[1]: *** [eeschema/CMakeFiles/eeschema_kiface_objects.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 37%] Built target kicad2step_lib
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2

Thanks

I figured most of this out from two forum posts:

https://bugs.launchpad.net/kicad/+bug/1804771

https://forum.kicad.info/t/wxpython-3-1-error-building-kicad-from-source-ubuntu-18-04/11431

$ make clean # clear files
$ make # then try again 

Note

Useful: You can see what other flags you can provide to cmake (using the -D flag), by peeking at kicad/build/release/CMakeCache.txt

lir@lir-VM:~/kicad/build/release $ vi CMakeCache.txt
[...]
 KICAD_SCRIPTING_WXPYTHON=OFF
[...]

Errors

These are some of the errors I ran into. If you see this, the solution to them is one of the lines above…

ngspice errors

CMake Error at /usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
Could NOT find ngspice (missing: NGSPICE_INCLUDE_DIR)
Call Stack (most recent call first):
/usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
CMakeModules/Findngspice.cmake:57 (find_package_handle_standard_args)
CMakeLists.txt:607 (find_package)

yacc -d -o parse-bison.c parse-bison.y
/bin/bash: yacc: command not found
Makefile:1052: recipe for target 'parse-bison.c' failed
make[3]: *** [parse-bison.c] Error 127
make[3]: Leaving directory '/tmp/libngspice_so/ngspice/src/frontend'
Makefile:773: recipe for target 'install-recursive' failed
make[2]: *** [install-recursive] Error 1
make[2]: Leaving directory '/tmp/libngspice_so/ngspice/src/frontend'
Makefile:1359: recipe for target 'install-recursive' failed
make[1]: *** [install-recursive] Error 1
make[1]: Leaving directory '/tmp/libngspice_so/ngspice/src'
Makefile:434: recipe for target 'install-recursive' failed
make: *** [install-recursive] Error 1

 

A whole host of wx errors, solved by not using wx ^___^

-- KiCad install dir: </usr/local>
-- Check for installed GLEW -- found
-- Boost version: 1.65.1
-- Found the following Boost libraries:
-- regex
-- Check for installed Python Interpreter -- found
-- Python module install path: lib/python2.7/dist-packages
-- Found wxPython 3.0.2.0/gtk3 (wxWidgets 3.0.2.0)
CMake Error at CMakeLists.txt:780 (message):
Cannot find wxPython.h
    *** Could not run GTK+ test program, checking why...
*** The test program failed to compile or link. See the file config.log for the
*** exact error that occured. This usually means GTK+ is incorrectly installed.
configure: error:
The development files for GTK+ were not found. For GTK+ 2, please
ensure that pkg-config is in the path and that gtk+-2.0.pc is
installed. For GTK+ 1.2 please check that gtk-config is in the path,
and that the version is 1.2.3 or above. Also check that the
libraries returned by 'pkg-config gtk+-2.0 --libs' or 'gtk-config
--libs' are in the LD_LIBRARY_PATH or equivalent.

Error running configure
ERROR: failed building wxWidgets
Traceback (most recent call last):
File "build.py", line 1325, in cmd_build_wx
wxbuild.main(wxDir(), build_options)
File "/tmp/pip-build-v_pIAS/wxpython/buildtools/build_wxwidgets.py", line 373, in main
"Error running configure")
File "/tmp/pip-build-v_pIAS/wxpython/buildtools/build_wxwidgets.py", line 85, in exitIfError
raise builder.BuildError(msg)
BuildError
Finished command: build_wx (4.755s)
Finished command: build (4.755s)
Command '"/usr/bin/python" -u build.py build' failed with exit code 1. [ 78%] Building CXX object pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/swig/pcbnew_scripting_helpers.cpp.o
[ 78%] Building CXX object pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/swig/python_scripting.cpp.o
[ 79%] Built target pcbnew_kiface_objects
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2

wx_python_helpers.cpp:(.text+0x3a1): undefined reference to `PyErr_Occurred'
wx_python_helpers.cpp:(.text+0x5b3): undefined reference to `PyUnicodeUCS4_AsWideChar'
../../pcbnew/CMakeFiles/pcbnew_kiface_objects.dir/__/common/swig/wx_python_helpers.cpp.o: In function `Py2wxString(_object*)':

wx_python_helpers.cpp:(.text+0x929): undefined reference to `PyErr_Clear'
collect2: error: ld returned 1 exit status
qa/pcbnew/CMakeFiles/qa_pcbnew.dir/build.make:929: recipe for target 'qa/pcbnew/qa_pcbnew' failed
make[2]: *** [qa/pcbnew/qa_pcbnew] Error 1
CMakeFiles/Makefile2:3908: recipe for target 'qa/pcbnew/CMakeFiles/qa_pcbnew.dir/all' failed
make[1]: *** [qa/pcbnew/CMakeFiles/qa_pcbnew.dir/all] Error 2
home/lir/kicad/eeschema/dialogs/dialog_spice_model.cpp: In member function ‘bool DIALOG_SPICE_MODEL::addPwlValue(const wxString&, const wxString&)’:
/home/lir/kicad/eeschema/dialogs/dialog_spice_model.cpp:809:70: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
m_pwlValList->SetItemData( idx, *reinterpret_cast<long*>( &timeF ) );
^
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/widgets/tuner_slider.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/widgets/tuner_slider_base.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/dialogs/dialog_page_settings.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/base_screen.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/base_units.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/eda_text.cpp.o
[ 41%] Building CXX object eeschema/CMakeFiles/eeschema_kiface_objects.dir/__/common/page_info.cpp.o
[ 41%] Built target eeschema_kiface_objects
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2 [ 34%] Built target idfcyl
[ 35%] Built target idfrect
[ 36%] Built target dxf2idf
In file included from /home/lir/kicad/eeschema/sim/ngspice.cpp:28:0:
/home/lir/kicad/eeschema/sim/ngspice.h:31:10: fatal error: ngspice/sharedspice.h: No such file or directory
#include <ngspice/sharedspice.h>
^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
eeschema/CMakeFiles/eeschema_kiface_objects.dir/build.make:4709: recipe for target 'eeschema/CMakeFiles/eeschema_kiface_objects.dir/sim/ngspice.cpp.o' failed
make[2]: *** [eeschema/CMakeFiles/eeschema_kiface_objects.dir/sim/ngspice.cpp.o] Error 1
CMakeFiles/Makefile2:1087: recipe for target 'eeschema/CMakeFiles/eeschema_kiface_objects.dir/all' failed
make[1]: *** [eeschema/CMakeFiles/eeschema_kiface_objects.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 37%] Built target kicad2step_lib
Makefile:162: recipe for target 'all' failed
make: *** [all] Error 2

Thanks

I figured most of this out from two forum posts:

https://bugs.launchpad.net/kicad/+bug/1804771

https://forum.kicad.info/t/wxpython-3-1-error-building-kicad-from-source-ubuntu-18-04/11431

Hands-on with Probabilistic Programming Languages

The past week with one of my graduate classes, we read a few papers on probabilistic programming lanugages (PPLs). A few fellow students presented on the papers, and included a little hands-on demo of PPLs. They’re much more approachable than I thought!

At least in the “hello world” cases, they’re pretty much like normal programming languages with the addition of a few primitives to allow for reasoning about probabilities. In the example of CHURCH, this is the flip primitive. CHURCH uses LISP-like syntax. [1]

Without further ado here are some of the examples given.

CHURCH

Here we use the online compiler at http://v1.probmods.org/play-space.html.

[2]

The first line, display(flip), shows one coin flip (50/50) – in this case we get a` #f, or false. If we run the program again, we might get a #t. Near the end, we see that we can also call flip 0.7 which will return true with 70% likelihood. We then run this 100 times and draw a histogram (I had to right-click and view the image in a new window to see it). Here we can see that we actually got about 78%-22% on this run. If we run the program again, we get a different histogram, and with more flips we get closer to the true 70% distribution.

Prolog

To see an example of how we can use PPLs to perform inference, let’s see an example in prolog.

Follow along here.
https://rextester.com/l/prolog_online_compiler

Here we defined some facts (amy is a parent of bob, and bob is a parent of cathy). Then we defined some rules (what does it mean to be a grandparent?). Finally, at the bottom, I typed in some queries to find out of cathy is a parent of amy (no) and if amy is a grandparent of cathy (yes). Then I clicked Run it and got the output at the bottom.

In this way we see prolog has “reasoned” and created a causal chain from our question to the axioms we have.

We can also write our queries directly into the program, and print them all out.

The code for these examples can be found at these links or the bottom of this post.

I’m not sure why prolog doesn’t have this concept of printing query results. I had a lot of issues with the program not stopping (TIMEOUT) and not being sure where I should type in the queries (marked with ?- in online tutorials), versus typing in the program itself.

Other thoughts

I also learned that they’re not just toy languages for computer science people, and there are statistical researcher who use these on a daily basis.

Footnotes

[1] The instructor said something like “Yea I feel like all these probabilistic programming languages and always in some obscure language. For instance CHURCH targets the niche that knows both LISP and the relevant statistical concepts. They’re mostly useful for the authors.”

[2] Note: Like LISP, the strange operator order is Polish notation.

Appendix

CHURCH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(display(flip))

(display(+ 2 2))
(display(equal? #f #t))

(define x (list 1 2 3))
(define (square x)
(* x x)
(display (square 6))

(define (flip-biased-coin)
(flip 0.7))

(hist (repeat 100 flip-biased-coin))

Prolog 1

This should be input in their entirety into the coding area, and then run.

1
2
3
4
5
6
7
8
9
10
11
% Facts
parent(amy, bob).
parent(bob, cathy).

% Rules
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Z) :- parent(X, Z), ancestor(X, Z).

% Run program with ?- prompt
?- writeln(‘hello world’), nl.

Prolog 2

This should be input in their entirety into the coding area, and then run.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
program :- write(‘Hello, world!’), nl.
parent(amy, bob).
parent(bob, cathy).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).

printqueries :-
forall(query(Q), (Q -> writeln(yes:Q) ; writeln(no:Q))).

query(parent(amy, cathy)).
query(parent(bob, cathy)).
query(grandparent(amy, cathy)).
query(ancestor(amy, cathy)).

:- program.
:- printqueries.