Project Kong: Calibration & Test Drive

The hardware has been assembled. The software has been installed. In this episode, it's time to calibrate that software and take the whole rover for a spin.

This video starts with a quality of life improvement: we move the main power switch for the car itself to a much easier-to-access location. It's been life-changing for the rest of this project. As a part of that section of the video, I show the macroscopic I've used for all the adjustments: “opening up” the car like a book, mounting the custom components to the flat platform, etc.

Also, mounting tape.

After a quick run-through of how to boot everything up, the video walks through the basics of calibration. The original documentation can be found on the Donkey Car website.

Finally, we go for our first test drive! Huzzah!

Attribution

The music in this video includes “Days Like These”, “Golden Hour”, and “In My Dreams” by LAKEY INSPIRED: https://soundcloud.com/lakeyinspired

Project Kong: Installing the Software

With the hardware fully assembled, this episode focuses on installing the software, connecting the car to the local Wi-Fi network, and creating the scaffolding for our Donkey Car project. This is the second of three in this series dedicated to assembling a Donkey Car without modification.

The accompanying documentation can be found on the Donkey Car website, but in particular, the following links will be helpful:

  • The Raspbian image we downloaded in this video can be found here.
  • The Etcher application I used to flash that image to an SD card can be downloaded from their website.
  • Introductory guides to SSH and Nano can be found here and here, respectively.

Attribution

The music in this video is “Elevate” by LAKEY INSPIRED: https://soundcloud.com/lakeyinspired

Project Kong: Assembling the hardware

The first step for Project Kong is to assemble the hardware sent by Arm for the Donkey Car. This video (originally intended for YouTube) walks through that process.

The actual hardware assembly (i.e. not the intro or outro) was the first thing I recorded for this series, and it may show. That said, I think it's a useful supplement to the official Donkey Car docs.

Best of luck, and do get in touch if you have any issues.

Project Kong: Overview

This video introduces the first videographed project: Kong.

Kong is a small, autonomous, beginner-friendly rover designed to help with elopement in children living on the Autism spectrum. It leverages the Donkey Car platform for the car, adding a RedBear Duo for Bluetooth scanning (and some other, wonderful capabilities revealed later).

JavaScriptural Exegesis

This is a recording from OpenSourceBridge 2017 of my talk, JavaScriptural Exegesis.

I had the privilege of giving this talk twice more: at Bellingham Codes later that fall, followed by LibertyJS in front of the biggest audience I've ever had the pleasure of presenting to. It's a flurry of “out of the text” conclusions drawn from the ECMA-262 Specification, and it was a delight to prepare.

Many thanks to both Test Double and Bellingham Codes for all of their support and feedback.

YouTube Shenanigans

I've been working on a simple video series for months. I've been learning how to shoot, organize, edit, practice, re-shoot, re-edit, render, and export video. I've been prototyping the project being recorded, writing scripts, and rebuilding the project as a one man film crew. I have designed and re-designed title cards and social media icons and banners.

And then I uploaded the above to YouTube.

First, I uploaded it to my personal Google Account, but I realized it would be safer to upload it to a separate, branded account. By YouTube's own recommendation, I created a Brand Account for this content. I uploaded the first few episodes, and went to bed.

The next morning, my account was disabled. No explanation.

In their typical tone, Google “helpfully” suggested I could request my account be reinstated. I did, and went back to waiting.

After a week, they disabled my Google Account (not the Brand Account), and reenabled it. Cue pats on the back.

I've gone through that rigamarole twice more, and still no satisfactory solution or explanation. If you've ever heard me say, “Choose a vendor that cares you exist,” this is exactly what I'm talking about. If this project was reliant on YouTube (to make money, it kinda is), it was dead on arrival, and I have no recourse.

Choose a vendor that cares you exist.

Unpub 8 First Thoughts

A week ago, I was excited—but terrified—to attend Unpub 8, my first gaming convention as a game designer. Now, a goal I thought might be unreachable has become Plan B, and a goal I never would have considered is directly within reach.

While in the midst of 31.5 hours (😱) of travel out to Baltimore, I ran out of the patience required to listen to Yet Another Podcast, switched to music, and tried my best to let my brain rest in the middle of all that stress and anxiety. Now traveling westward again, I fired up the interrupted podcast, a sermon from Chris Eltrich of Lettered Streets Covenant Church where Chris shared the following:

Isn't that often the way things are in your life? Jesus comes to us by surprise. We think we know so well what our life is going to be like, what it should be like, and then out of the blue something beyond our control surprises us; forces us to respond to new information, to new circumstances, to new reality.

I'm overwhelmed with how timely and relevant that statement has become. I'll share more specifics as time moves on, but I'll leave you with this: God is good.

(Here is the rest of that sermon recording, in case you're interested.)

Learning Rust

I have this niggling feeling like I still haven't really "learned" Rust. I realized today that this feeling is wrong—I know enough Rust to build whatever I want, which should be the rubric anyone uses to decide they "know" something or not.

I know enough about cooking to prepare any dish I could imagine wanting to prepare—is that enough, or have I still not "learned" how to cook? (After about 10 years of persistent study, I finally feel comfortable saying "I can cook".)

It's so easy to get sucked into the games played by elitists who try to decide who's a "real" programmer and who's not. Who's a "real" Rust programmer? Ruby programmer? JavaScript programmer? CSS programmer? Does it matter?

I've decided I don't want to "learn" something for the label. I know enough. I know Rust.

A note specific to Rust

What's made this transition (from "learning" to "learned") harder with Rust, I think, is that Rust has an intense learning curve up front, and then almost completely gets out of your way. Once you've learned how to tell the language your plan, it quickly gets out of the way, exposing nothing but the problem you're trying to solve. Because I'm using Rust to solve problems I've never solved before, part of my hesitation in saying that I know Rust is that I haven't completely finished those projects. I haven't finished those projects because I haven't solved those problems, not because I'm unfamiliar with the tools I'm using.

Most languages conflate the two, and I appreciate those that have designed Rust otherwise.

Science (Education) is Cool

Science is cool.

No, I don't mean that space is cool, though it is.

No, I don't mean that eclipses are cool, though they are.

No, what I mean is that when everyone else is losing their minds and staring at the sun until their eyes bleed, Googling "diy eclipse glasses", you can recall your "scientific knowledge" that pinhole cameras exist, and go build one in your backyard.

A picture of a hastily made pinhole camera out of a pizza box and some recycling bins.

Science (education) is cool because I've been trained to look at the world around me and realize that the tree in my backyard is really hundreds of pinhole cameras all at once, and that I can see the eclipse hundreds of times, simultaneously.

A picture of the image a tree's shadow made during the eclipse: many tiny images of the eclipsed sun.

The gift of science and the gift of science educators is wonderful because it allows me, not a "scientist", to sit in my science-riddled backyard and enjoy my science-riddled coffee while I experience something uniquely science-riddled and once-in-a-lifetime like a solar eclipse.

Thank you, science teachers.

A picture of the image I got from my pinhole camera of the eclipse.

Creation & Consumption

Kiddo,

Every philosophical discussion with my father includes the following tenet: the subject at hand is really on a pendulum, with each generation destined to rebel and choose the opposite of their parents. Any hope of progressiveness, therefore, is nothing more than rebellion rationalized.

This is not about that tenet or my issues with it. I will, however, borrow it for a moment.

Creation and consumption delimit a similar pendulum—albeit one that swings a bit faster. On one hand, productivity and sharing one's voice. On the other, information and connecting to others'. On the whole, binge-and-bust cycles throw this pendulum back and forth as creators burn out and consumers burn with regret. As with most such pendulums, I can't help but feel like balance must exist somewhere in the middle.

Both creation and consumption are tempting forces easy to rationalize: both "productivity" and "knowledge" (not to mention those seen as "productive" or "knowledgeable") have become worshipped as Gods of the Secular World. Listicles abound of the best ways and places to accomplish or learn more, from the shiniest new tools to the sexiest new podcast. If we just keep adding more weight to the pendulum, surely our cycles of regret, jealousy, and fatigue will be assuaged.

For how many of us is that true? How many of us have found peace and balance by adding more, whether to our to-do list or our inbox?

If we prune away those forms of creation and consumption that are not edifying, not life-giving, we give more space to those that remain to flourish. Each book not read gives the next book more room to grow in our mind. Each project not started leaves the next project more time to be nourished and to nourish us. With enough intention and attention, this pruning will alleviate enough pressure from the pendulum that, though it may swing from time to time, the violence of the swinging will be eased, and the nausea of our hearts likewise.

If we cannot see the sources of creation and consumption in our life, how do we know where to prune? Though it may seem strange at first, we need to take stock of these hidden (or neglected) drains on our time and energy.

This is a far-from-comprehensive list:

  • Friendship — Friendships take time and energy. When each individual provides that time and energy, friendships are inimitable gifts. For how many of your relationships are you always the instigator, or always the follower? Though it may be hard to admit, what does that say about your relationship? Do you actually care about this person? Do they actually care about you?

  • Chores — We all have to eat and dirty clothes do not, with today's technology, clean themselves. It is tempting, however, to so strongly desire food and to loathe laundry that we spend time and energy improving these chores: their process or their product. Do you enjoy trying to shave seconds off of a daily chore routine? Will you still be this excited about kombucha a year from now?

  • Fashion — Fashion is a source of both creation and consumption in our lives, tempting us with dual heads and salacious messages of false beauty and false connection. Feeling confident in your own skin (or second skin) is important, but felling self-important about what brand your wearing (that someone else owns) or how "in" your clothes are (by someone else's definition) is toxic. Would you rather toe the Fifth Avenue line, or build your own persona around a single piece of clothing? Should your "image" change every week, or never?

  • Children — Children take a unique place on this list, in that they shift around on this scale. Newborns make poor conversationalists, requiring you to provide both sides of any discussion you intend to have with them. As kids grow older, however (whether they're yours or not), they transition from sinks of time and energy to well-springs of curiosity.

    Children (and mentees, and younger peers, and …) are also unique among this list in that you may not practically have a choice in whether they require you to invest your time or energy. What would you prune away to enjoy the time you spend with your kids? Would you stop out-delivering your co-workers if it meant you could compassionately mentor those that need it?

  • Meditation — Whether you think of it as your subconscious, the Holy Spirit, or an amorphous, anonymous power pervading the Universe, meditation (or prayer) is an often-deprived form of intense and intentional consumption. Intuition and introspection are powerful, quiet forces the abusers in our lives (ourselves often included) work to drown out. Would you stop reading poetry if it meant better connecting to your own sense of self? Would you start reading poetry if it meant discovering yourself anew?

  • Little imagination is required to continue this list ad nauseum: video games, substances, open source software, home renovations, email, music recommendations, adult kickball leagues, and so forth.

There are no right answers to these questions, but we wrong ourselves by never asking them in the first place. What would you create if you consumed less? What would you learn if you built less? What would you experience if you did less?

P.S. A note about social media

I know it's "hip" to be dropping Twitter these days, (for Mastodon, I guess?) but I will miss Twitter while I'm away. I may still post (a superficial form of creation), but I won't be following my normal routine of reading.

What hurts most about this scenario is knowing that I'm effectively leaving behind a group of people I only see through this form of consumption. Whether I've "met" them or not (for anyone's definition), I've become fond of people like Rami Ismail, Tim Keller, and Gary Bernhardt to whom Twitter is my primary connection. Though it may be a superficial connection, similar have led to my meeting, helping, and bringing into community others before.

Maybe, just maybe, by the time I come back it won't be so thoroughly filled with dangerously inept politicians and eggs.

On-Air: Better Coworking at Home

TL;DR: I made a thing! When my Mac camera is on (presumably because I'm in a meeting), an "On Air" light turns on. This should make co-working at home (between a software engineer and a domestic engineer) much easier.

My home "office" is current co-located with our bedroom. On multiple occasions this week alone, my wife poked her head in during a video call, sheepishly closing the door after discovering me in my mid-morning standup.

This week was different: rather than continuing to chuckle each time it happens, I decided to make use of the growing pile of microcontrollers on my desk and make an Internet-connected "on-air" light.

The microcontroller I chose is the Electric Imp (specifically the imp001). I first considered a custom build with an April board, but decided to use the Hannah instead and build a custom case instead (the unused knob is a bit of an eyesore, but it's significantly easier this way). One cardboard box, a pair of scissors, and some masking tape later, and I had my case. I made a little window in the box for the RGB LED to shine through, covering up the window with a small piece of paper with "ON AIR" written on it.

Since I used an Imp, I took advantage of their excellent community and grabbed some code for the I2C and IO Extender from GitHub, and the rest of the Agent/Device code was incredibly simple. In the end, I had a single URL I could hit to turn the LED on and off: agent.electricimp.com/DEVICE_ID?led=$STATE. This was my original goal: to be able to turn the light on and off from my desk.

Fortunately, that evening was the monthly Bellingham Codes meetup. Talking about my little project with the group, another attendee had a great idea: even if writing plugins for each video conferencing platform would be overly complicated, I could write a script to detect if the camera is in use, and trigger the light entirely based on that.

My first instinct to check camera state was Objective-C, and I spent a few hours to that effect. As it turns out, using a generalized search engine to find sample Obj-C code for detecting the camera state was impossible. Browsing StackOverflow directly, less so. However, I discovered something even better: other solutions to the same problem. While browsing the osx tag, I found this post discussing Chrome's use of the camera. It turns out the camera device shows up via lsof, so I had my hook.

I published the resulting code on GitHub, though it is certainly Mac-only. Let me know what you think!

Keep Schoon Bearded: Recap

In short, "Keep Schoon Bearded" was wonderfully successful. We raised $300 for local missions, forcing me to keep a loofah permanently fixed to my face until Christmas morning—including the initial No-Shave November period, that makes 54 days of Bearded Schoon.

While thinking through the results, I'm led to consider whether I would do this again. Should I do it next year? Should I do this every year? Are there better ways to raise money like this?

If I grow a beard for charity again, I imagine I'd take the same tack as Movember, and make it a group effort. I'm sure I'm not the only developer who loathes both facial hair and the "joke" that we look homeless once it threatens to take over our visage.

I'm considering other charitable ventures, such as a private, catered dinner. While I'm not a professional chef by any means, I have a heart for hospitality, and would be overjoyed to fill my backyard with hungry guests in the stunning Bellingham summer weather, a steady stream of culinary delights pouring out of the house. The margins aren't as good as "do nothing, and let your body do what it wants", so I would only pursue this if the overall revenue would be more significant.

For now, however, I'm content with the success. I set out to raise a little money, and have a little fun at my own expense. With checks cut—and cheeks shaved—that's good enough for now.

Keep Schoon Bearded

TL;DR: Donate here to keep me bearded.

If you need positive motivation, donations help alleviate homelessness in my community. If you need negative motivation, this beard is really itchy.

Mental Health First

In Why I Follow Who I Follow, I gave a list I try to follow when building my Twitter Timeline:

  • Challenge my assumptions
  • Broaden my perspective
  • Check my privilege
  • Help my growth
  • Brighten my day
  • Empower my faith
  • Improve my profession

While this has been true for quite some time, I need to add an addendum: I will follow as much of that list as I can as long as I have the mental headroom to internalize and do something with that information.

At times, that means culling below that bar.

I can be hard on myself, but my mental health needs to come first. From that comes my physical health, the health of my marriage, the health of my family, the health of my career, you name it. It's hard for me, but some times I have to slow down.

Maybe I need to look at my list of projects, too...

JSON API in 5 Minutes

This is a Resource (from http://jsonapi.org/examples/):

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}

HTTP entities that contain a Resource do so with two top-level fields:

  • data - Contains the Resource itself (or an Array of such Resources)
  • included - Contains an Array of other Resources. In the above example, the included data is requested. Additionally, the server may include any unrequested Resources it wants.

Resources themselves have four top-level fields:

  • type - A namespace of sorts for all similar Resources, represented as a String. Example: "widgets"
  • id - An identifier unique to its namespace, represented as a String. Example: "42"
  • attributes - Any properties specific to this Resource, represented as an Object. Example: { "name": "Best Widget Ever" }
  • relationships - Links from this Resource to all related Resources, represented as an Object. Each of these values should be a Resource Identifier, an Array of Resource Identifiers, or null. Example: { "brand": { "type": "companies", "id": "Initech" } }.

Resource Identifiers are, as their name implies, only the identifying properties of a Resource: type and id.

Routes

  • You can fetch a resource with a GET request, which will return the complete Resource as described above. Example: GET /widgets
  • You can create a resource with a POST request, which should include the complete Resource being created in the request body. Example: POST /widgets
  • You can update a resource with a PATCH request, which should include only the attributes and relationships that should be updated, using the structure described above for HTTP entities containing Resources. Example: PATCH /widgets/42
  • You can remove a resource with a DELETE request. Example: DELETE /widgets/42
  • You can replace a relationship with a PATCH request, which should include the entire relationship being replaced (e.g. a Resource Identifier, an Array of Resource Identifiers, or null) under a data field. Example: PATCH /widgets/42/brand
  • You can append to a one-to-many relationship with a POST request, which should include the relationship(s) being appended (e.g. a Resource Identifier or an Array of Resource Identifiers) under a data field. Example: POST /widgets/42/parts
  • You can remove from a one-to-many relationship with a DELETE request, which should include the relationship(s) being removed (e.g. a Resource Identifier or an Array of Resource Identifiers) under a data field. Example: DELETE /widgets/42/parts

Further Reading

Obviously this just skims the surface of what JSON API is, even going so far as to assume you already know why JSON API is a good idea, or how you would go about making that judgement for yourself.

While I understand that the official documentation contains very precise, technical writing, I cannot overstate how valuable that documentation is for understanding the standard.

As for the "why" of things, I'll echo their supposition that JSON API is a valueable anti-bikeshedding tool; this standard is what most teams work toward when they roll their own API design, and few teams ever make it. Starting from a worked standard like JSON API foregoes this process, enabling teams to develop the model and business logic without worrying about PUT vs PATCH, where to put metadata on a route that returns a POJO, etc.

TL;DR: Go read the official spec.

Wat's Going On?

A quick, 5-minute video explaining the JavaScript portions of Gary Bernhardt's infamous "Wat" talk.

Anatomy of a Schoon TODO

In its original Dutch, my nickname, Schoon, means "clean". Doubly-appropriate, perhaps, that my method of TODO comments be called a "Schoon TODO" by former colleagues. It's the cleanest I've seen.

Quick disclaimer, perhaps: I don't know this style to be unique, but I don't know it not to be unique. I've never verified either way, so I won't assert either to be true. Just take this as "the way I do things, and maybe that's helpful."

Remote Meeting Courtesies

With an increasing prevalence of meetings done over Skype, Hangouts, and similar, I feel that everyone (especially remote workers, but this isn't specific to folks who primarily work remotely) should know a few basic courtesies involved with this young form of interaction.

In decreasing order of importance:

  1. Mute yourself unless you are speaking. - I know you're being silent while on the call, and that's fantastic. The problem is that your computer is picking up the faintest sounds, amplifying them, and sending them to the server anyway. Unless you're actually trying to speak to the group, use the mute feature of the software. This always reduces the background noise of the call, even if you're not making any.

...The End.

View Archives