In no particular order:

  • Template metaprogramming is still evil, and C++11/14 hasn't fixed anything about it. People argue metaprogramming enables "clean, elegant code," as if a home built on a garbage dump won't smell like garbage. If anyone else needs to repair or extend the foundation of your home they'll need to parse through your garbage pile to make changes. Template metaprogramming as a rule should simply never be done outside low-level libraries.
  • auto is too easy to abuse. Oh but, "the IDE makes auto easier to read!" Go back to Java. auto does have a few good uses, clang-tidy provides excellent guidance on where its effective, its guidance should be followed.
  • Large lambdas harm readability. They make the control flow of the program harder to parse and discourage self documenting code. Lambdas should be limited to 2-3 statements. And please, if you write a lambda, mean it: don't write a lambda where you could have just as easily written a standalone function.
I recently got a new BBQ smoker, after a 10+ year hiatus from BBQ. Temperature controlled, pellet fed.

I had to try a brisket first. But since I was rusty at smoking meats, I read a few articles online about making the "ultimate brisket" and was a little surprised by what I found. In summary, there are a lot of recipes out there that will keep you busy by your smoker rubbing, basting, spraying, turning and poking for 16+ hours. It sounded like a lot of work, and much of it sounded unnecessary.

Humans have been smoking meat for thousands of years. The recipe has always been salt+smoke. How hard can this be? After a few texts and calls to a good friend and avid barbecuer, I decided to try something simpler. Much simpler. For science.

The results turned out great. Not <your favorite BBQ joint> great, but pretty darn great given I put basically zero effort into this.

BBQ people of the Internet, I present the world's simplest BBQ brisket recipe.

  1. Pat dry your brisket.
  2. Trim some fat off, but leave at least 1/4" fat where you can. The fat makes a good moisture insulator. Or don't. A dry crust tastes great too! For this experiment I trimmed the fat off one half of mine and left the fat on the other half; I liked both!
  3. Make a dry rub of 2 parts rock salt to about 1 part ground black pepper. Eyeball it. Rub it into the meat and let the brisket sit out for an hour.
  4. Set your smoker to 150°F and wait for it to stabilize at 150.
  5. Place the brisket in the smoker and cook for at least 1 hour per pound.
  6. DO NOT OPEN YOUR SMOKER. "If you're looking, you're not cooking." Go look at something else: Look up at the sky, your significant other, whatever. There's plenty of interesting things to look at. Don't risk fiddling with the internal temp of your smoker.
  7. Shut the smoker off, wrap in foil and let rest for 60+ minutes before serving.
That's it! Brisket, salt, pepper, smoke.. This is not complicated. My brisket came out with a perfect bark, a 3/8" smoke ring and was oozing liquid when I cut into it. Tasted amazing. I noted that the internal temp of the fat side was 154°F, so my smoker--even though it was set to 150--was overshooting a little.

If you want the "ultimate brisket" keep scouring the Internet, but you should try this first :)

Update (a few weeks later): I've cooked about 4 more briskets since writing this and have learned a bit more about how to achieve the "ultimate brisket". 160°F is the temperature at which the connective tissue collagen begins to break down (Link). If you want falls-apart-under-a-plastic-fork-tender brisket, you need to get the brisket above this temperature. The problem is this higher temp also comes with higher moisture loss.

The solution is a trick called the "Texas Crutch": after slow-smoking the brisket at 150°F for 10+ hours, tightly wrap it in foil and then throw it in the oven at 175°F and let it go for another 6+ hours. You'll lose the crispy bark but the trade is a super-moist melt-in-your-mouth brisket.

This isn't quite as simple as I initially advertised but it's worth the effort. I've been doing this as an 16 hour recipe: Start smoking at 8PM, at 8AM wrap it in foil and stick it in the oven and you've got great BBQ for lunch. The same technique works great with chicken legs. For pork butt, instead of wrapping in foil, stick it in a dutch oven and it's ready to pull right away!

Ultimate omelet

| No Comments
MASTERS OF BREAKFAST: Episode 1

The trick to the perfect omelet is to borrow a technique from frittatas: broil the omelet under high heat before you flip it. Broiling causes the egg to rapidly expand, yielding a fluffier, moister omelet. And it has the added benefit of decreasing the overall cook time.

Since we're placing the omelet pan in an oven under a 500°F broiler, you'll want to use a carbon steel or cast iron pan for this recipe. A 9" pan with a 45° edge is ideal if you plan to flip the omelet like a pro.

  1. Pre-heat your broiler to 500°F.
  2. Pre-heat your omelet pan to about 275°F (medium).
  3. Sauté your diced veggies (onion, bell pepper, etc.) in a little oil until desired texture. (If you're making a batch of omelets you may want to do this ahead of time).
  4. Add your meats (bacon, ham, sausage, etc.) and sauté for another minute. Shake pan to make sure nothing is sticking--if its sticking add a little more oil.
  5. Whip 2 eggs with a splash of water until frothy and pour over sautéd meats and veggies.
  6. Cook for one minute on stove (should be bubbling very slowly).
  7. Move pan to oven and place under broiler for 1-2 minutes.
  8. Watch omelet carefully, remove from oven when sides begin to curl up and top is a very light golden brown.
  9. Flip omelet over and place pan back on hob.
  10. Add shredded cheese to one side of omelet and fold omelet over. Cook for another 30 seconds.
  11. Flip folded omelet again and place back on hob for another 30 seconds.
  12. Serve.
IMG_0068.JPG





I recently picked up a YPG-235 off Craigslist. One of the reasons I sought it out was for the "lesson mode" (or "Yamaha Education Suite") where it helps you learn songs by displaying the notes and pausing the song for you until you hit the notes. You can do the same with a PC/iPad now, but I was hoping for a more offline experience. Sadly, the process to get new songs onto the keyboard is less-than-straightforward.. As I was unable to find a tutorial online on how to do this, here are the basic steps for you, Internet.

You'll need a PC running Windows, as Yamaha's music transfer software only runs on Windows. Install the USB MIDI driver for your keyboard and verify you can transfer midi files to it using their "Musicsoft Downloader" program.

Regular midi files will play on Yamaha keyboards, but they won't work in lesson mode. The trick for getting files to play in lesson mode is to put the music you want to play yourself on Track 0 with the right hand on Channel 0 and the left hand on Channel 1. The file must also be in MIDI Type 0 file format.

Some free software for Windows that can help you out with a conversion: try MidiEditor to rearrange the tracks/channels and GN1:0 to convert MIDI Type 1 format files into MIDI Type 0.

Once you have the file in the right format you should be able to transfer it to the keyboard, reboot and it will appear in the song list and be playable in lesson mode. If you're looking for free midi files try midiworld.com or hymnary.org. Good luck!


You can rip a sequence of images into an mp4 and display it inline in an ipython notebook using a function like this:

import matplotlib.pyplot as plt
from matplotlib import animation
from IPython.display import display, HTML

def plot_movie_mp4(image_array):
    dpi = 72.0
    xpixels, ypixels = image_array[0].shape[0], image_array[0].shape[1]
    fig = plt.figure(figsize=(ypixels/dpi, xpixels/dpi), dpi=dpi)
    im = plt.figimage(image_array[0])

    def animate(i):
        im.set_array(image_array[i])
        return (im,)

    anim = animation.FuncAnimation(fig, animate, frames=len(image_array))
    display(HTML(anim.to_html5_video()))
However there's a disadvantage with this method: You have no control over the encoding settings so you're likely to get a video with a lot of artifacts.

If you would like a video without artifacts, check out JSAnimation. This sends the sequence of images to the browser along with some javascript to play through them. This looks much better and is much easier to control than an html5 video control:

from JSAnimation import IPython_display

def plot_movie_js(image_array):
    dpi = 72.0
    xpixels, ypixels = image_array[0].shape[0], image_array[0].shape[1]
    fig = plt.figure(figsize=(ypixels/dpi, xpixels/dpi), dpi=dpi)
    im = plt.figimage(image_array[0])

    def animate(i):
        im.set_array(image_array[i])
        return (im,)

    anim = animation.FuncAnimation(fig, animate, frames=len(image_array))
    display(IPython_display.display_animation(anim))

16.04 uses gcc 5.4 by default. You'll need to install gcc 4.9 and configure OpenCV to use 4.9 instead:

sudo apt-get install g++-4.9
cmake -DCMAKE_C_COMPILER=/usr/bin/gcc-4.9 -DCMAKE_CXX_COMPILER=/usr/bin/g++-4.9 .

If you have CUDA installed you may want to disable compiling the CUDA libraries as well, or else suffer another hour+ of compilation time. Add -DWITH_CUDA=OFF to disable CUDA.

Cheater chashu ramen

| No Comments
I've been on a quest this last year to find a home ramen recipe that's easy, fast, and tastes somewhat authentic. So far my conclusion is such a thing doesn't exist! Really good chashu takes 12+ hours (and requires a cut of pork belly--not always easy to find) and a rich broth takes 12-24+ hours. You can speed the process with a pressure cooker but it needs to be carefully monitored and thus loses on the easy criteria.

But I continue to keep trying. Here's a technique that I think is worth sharing: This hardly tastes authentic at all but it's relatively fast and very simple. I've made ramen this way a few times and it's always been a big hit with the family. The trick is using a regular pork loin or pork chops (which we usually have in the freezer) in a slow cooker. Cooking time is 8-10 hours with about 15 minutes of prep time in the morning and another 30 minutes of activity towards the end before you serve it.

Ingredients:

  • 1.5-2 lb pork loin (cut into 1" sections) or pork chops
  • 1 cup soy sauce
  • 1" fresh ginger, sliced
  • 5-10 cloves fresh garlic
  • 1/2 lb fresh mushrooms
  • 1 lb baby bok choy
  • 2 things of dry ramen noodles
Place the pork, ginger and garlic in a small slow cooker and cover with 1 cup soy sauce and ~1 cup water, set on low. Cook for 8+ hours.

Pull the pork out of the slow cooker and cut into thin slices (or just separate it like pulled pork if you don't care about the texture).

Take the broth from the slow cooker and pour into a large pot. Dilute the broth with 1-2 cups water (to taste), add the mushrooms and bring to a boil. Reduce heat to low, add the baby bok choy and simmer for 30+ minutes.

15 minutes before service, bring another pot of water to a boil and cook the ramen noodles. Drain and rinse.

Serve the pork, noodles and broth together in a bowl. Enjoy!

** What about the soft-boiled egg?? You can prepare eggs anytime and have them ready to go in the fridge. Bring eggs to a boil then set a timer for 5 minutes. When the timer goes off quickly rinse them in cold water. Peel, then cover with a mixture of 50/50 soy sauce and water with a splash of rice vinegar, then marinade in the fridge.


The process is actually quite easy, but the installation docs don't provide the right hints. I found some posts online suggesting others had battled with this, so I share this here in case others get tripped up as well.

1. Install Docker. Create a docker group, add yourself to it, then log out and back in. Verify you can run the "hello docker" sample as yourself.

2. Run the TensorFlow GPU image:

$ docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow:latest-gpu

3. Visit http://172.17.0.1:8888 and verify you can execute the "hello tensorflow" samples. These will run without the GPU--you'll see errors on the console about not finding the CUDA libraries. Close the docker instance.

4. Install the latest nvidia binary display driver for your system. The simplest way to do this is through the Software & Updates GUI, Additional Drivers. Select "using NVIDIA binary driver," apply changes and restart. You can verify you're running the nvidia display driver by running nvidia-settings from the command line.

5. Install CUDA. On 16.04 the easiest way to do this is directly from apt:

$ sudo apt-get install nvidia-cuda-dev nvidia-cuda-toolkit

6. Install cuDNN v4. This needs to be installed manually. See instructions here. (You need to register for an nvidia developer account).

7. Run the TensorFlow GPU image, but this time give it access to the CUDA devices located at /dev/nvidia*. The easiest way to do this is with a script. The one the TensorFlow docs reference doesn't work with 16.04, so use mine.

8. Visit http://172.17.0.1:8888 again. This time when you run the samples you shouldn't see any CUDA errors.

I often catch myself telling people how much I hate mailing lists. It's usually around the point in the conversation when I realize they're giving me the "you're a crazy person" look.

Before you give me the same look, hear me out! How often have you said or heard:

  • Who's on this list?
  • What is this list for?
  • Who should be on this list?
  • Should I be on this list?
  • Can you add me to this list?
  • What should we name this list?
  • Who do I talk to create this list?
  • How do I add someone to this list?
  • Can I get permission to add someone to this list?
  • Who has permission to add someone to this list?
Or the worst: "Sorry you missed that super important email--I assumed you were on that mailing list!"

The social dynamic mailing lists create bothers me the most. The inclusion felt by those on the list, the exclusion felt by those not on the list... Creating mailing lists are quick way to silo an organization.

But it's not all bad. Mailing lists are nice when you have a very large number of people that you want to broadcast a message too. They're great for one-way communication like announcements.

Is there a middle ground? I believe if organizations followed some simple guidelines they could derive benefits from mailing lists and avoid most of the negative side effects. If I was so bold as to propose some guidelines for adopting mailing lists, they would be something like the following:

  1. Don't create mailing lists for small groups. I think a good rule of thumb is about 10 people starts to warrant a mailing list. Anything less than that and you can remember their names. If you can't remember their names then don't bother them with an email!
  2. Let anyone join your mailing lists. Don't do "ask to join" or keep the mailing list a secret. If you're tempted to share secret stuff on a mailing list you probably should be mailing people directly anyways.
  3. Let anyone read your mailing lists. Maintain a public, searchable archive for all of your mailing lists. If your IT administrator complains tell them it's the 90's--web indexes for mailing lists have been in existence since the beginning of the web.
The OBDLink SX is an inexpensive USB OBDII scantool marketed by ScanTool.net. It's sold as a Windows-only scantool and comes packaged with some very simple OBDII software.

Not much exists on MacOS X for CAN monitoring, but I was still curious if I could access my car through my Mac. The System Information app told me the OBDLink SX had the vendor ID for Future Technology Devices International, a manufacturer of popular USB<->Serial bridges like the ones in the Beaglebone Black. Once I had that established it was just a matter of guessing the baud rate to see what was connected to it, and a few minutes later I discovered the OBDLink SX is actually the common ELM327 OBD to RS232 Interpreter, for which a great deal of software already exists.

So here's how you can chat with the OBDLink SX USB on MacOS X:
  • Connect the OBDLink and check if the device appears at /dev/tty.usbserial-000012FD. The Console will also say FTDIUSBSerialDriver: start - ok. If you don't see the device or this message then you may need to install the FTDI USB kext from here or here.
  • Open a screen session 115200 baud, 8 bits, no stop bits, parity.
  • Type ATZ <enter> to reset the device, at which point you can chat with it.
  • If you want to be able to see what it's saying back send the ATL1 command to enable line feeds.
Happy hacking.

$ screen /dev/tty.usbserial-000012FD 115200,cs8,-cstopb,parity
> ATZ
ELM327 v1.3a
> ATL1
OK

>AT@1
SCANTOOL.NET LLC

Myself

Projects

Find recent content on the main index or look in the archives to find all content.

Monthly Archives