Archive for the ‘Fun’ Category

Converting spreadsheet data to Markdown

I find it’s a lot easier to prepare a table with Numbers than by hand. I was using this today and thought I’d share the how-to.

Step 1: Select the material you want to table-ize.

Step 2: Paste it into text edit. Numbers uses tab delimiters (at least it does for me).

Step 3: Use find/replace to replace all tabs with a vertical pipe symbol (|). Copy any of your tabs to populate the find field.

Step 4: Use find/replace to replace all newlines with the sequence pipe symbol – newline -pipe symbol. Copy a newline from your text to the find field and in the replace field type |, then paste the newline again, and then type | again.

Step 5: Add pipe signs to the start and end of your file. Before:

After:

Step 6: Duplicate the first line and replace all text between bars with dashes:

Step 7: If you have an empty left-top-corner like I do, add at least 3 dashes to the 2nd line between the first set of pipes:

And you’re done.

Pushing the gist envelope: gists with pics and zips

People often don’t realize how powerful GitHub’s gist pasting service is. It’s more than just a “paste” site. Gist offers a full version control system extension to GitHub’s main site. I’ve been working on developing version control training materials and gist is a great way to introduce the fundamentals.

Many gist users know that the site offers you pushbutton convenience to paste one or more files. You can create open gists and “secret” ones hidden from public view. Gist also lets you fork, revise, and explore diffs between revisions.

For example, you can work in groups when writing. Collaborators can fork and make changes to offer content feedback. You can then use diffs to see what edits were made.

Here are some diffs from a recent Raw String proposal I worked on:

And this is the corresponding “rich diff”, which is slightly prettier:

And there’s a lot more you can do with gist. That’s because gists, as version control repositories, can be cloned to your computer, modified, and pushed back to GitHub. This means you can, for example, set up albums of pictures or host an easy-to-distribute zip file.

Each gist URL is a repository’s address:

git clone https://gist.github.com/erica/7cd24c6ab2f737735a9ab2b95628c549

As a gist’s owner, you have commit privileges, allowing you to edit your gist from your computer.

The command line enables you to add binary files that you can’t from the web interface. I grabbed a bunch of kitten pictures from Pexels and added them to my gist. A nice way to create simple albums:

If you click “Download ZIP” at the top right, GitHub zips up the repository contents (in this case five kitten PNGs) and copies them to your computer. This is not cloning; the zip file just stores the source files, not the full git repo.

It’s just as easy to host an archive file. When you have an Xcode project or playground that you need to share, Gist provides a great intermediate service alternative to iCloud or Dropbox. If you need privacy, use the “secret gist”  button when creating the gist.

This isn’t, of course, the end of what you can do with gists. Because each gist is a git repository, you can perform all the same commands you would in any git repo. Gist, of course, has a limited interface, so you won’t be able to, for example, switch between branches from the gist website. On the other hand, you can perform other tasks that don’t depend on a GitHub UI like listing diffs:

% git diff cb9271da5070f11602d3ab436a05fb9705409fd2
diff --git a/raw.md b/raw.md
index 8ed7306..ea4b5ed 100644
--- a/raw.md
+++ b/raw.md
@@ -104,9 +104,8 @@ Escaping hinders readability and interferes with inspection, especially in the l
 
 ### Candidates
 
-A good candidate for raw strings:
+A good candidate for raw strings is non-trivial and is burdened by escaping because it:
 
-* Is non-trivial.
 * Is obscured by escaping. Escaping actively harms code review and validation.
 * Is already escaped. Escaped material should not be pre-interpreted by the compiler.
 * Requires easy transport between source and code in both directions, whether for testing or just updating source.

I think GitHub’s gists are pretty awesome. And now, at least for me, they’ve gone from handy but mindless pastes to something really special.

Do you have a special way to use gists? I’d love to hear about unconventional ways to use this utility site to push boundaries and introduce new functionality. Drop a comment or an email and let me know.

Advent day 3, part 1

Are you playing along with Advent of Code? I got started a little late this year, so I’m doing a couple of days each day until I catch up.

The basis of Advent of Code isn’t so much the beauty of your code as it is the correctness. Because of this, a lot of my code is hideously ugly, with design choices best described as “questionable”. For example, at one point, I used flatMap.count on returned optionals instead of returning zeroes and ones and reducing them with +. I’m using Swift because that’s the language that’s currently dominant in my brain, although a lot of the memory manipulation would have been easier with straight C.

I wanted to share my solution for the first half of day 3. The challenge stipulates a squared spiral pattern of numbers in a grid and then asks you to calculate the distance from each number to the center. The approach I came up with for part I proved completely useless for the second half of day 3, where I had to start over from scratch. (Normally, you just modify the first code with an extra function and you go from part I to part II pretty easily.)

I took a road with part I that really didn’t fit the mindset of the challenge givers. For me, I was thinking geometrically, noticing that this was a degenerate case of a series of concentric circles. However instead of calculating the distance with a sin-cos solution, the concentric squares created a stepped triangle wave instead. Because of this, I built my solution to traverse the triangle wave and deduce the distance as the radius + the phase of the wave for any given number.

I thought I’d share my code for this because it’s pretty short and I think it’s pretty unusual for the problem domain.

for n in [1024, 12, 23, 312051] {
    for i in sequence(first: 1, next: { $0 + 2 }) {
        // Find least bounding square that contains number
        let boundingSize = i * i
        if boundingSize >= n {
            // Start of the outer edge sequence
            let firstValue = (i - 2) * (i - 2) + 1
            
            // Calculate distance to center
            let radius = (i - 1) / 2
            
            // The first number is always positioned at the
            // bottom right, one up from the bottom
            var current = radius - 1
            
            // The `direction` differential is the basis of
            // the triangle wave generator. It flips at the
            // minimum (-radius) and maximum (radius) offsets
            var direction = -1
            
            // One trip through the outer edge will be
            // sufficient to find the value
            for value in firstValue ... boundingSize {
                if value == n {
                    print("Result for \(n) is \(radius + abs(current))")
                    break
                }
                
                // Generate the next value in the triangle
                // wave pattern to determine the distance
                // from the center
                current += direction
                if abs(current) == radius { direction *= -1 }
            }
            break
        }
    }
}

Needless to say, my solution for part II had nothing to do with this wave approach. Instead, I actually constructed the 2D array, populated it with numbers and then used those as an addressing scheme to collect sums. Outside the addressing, it was basically applying a 3×3 sum filter in an address-driven convolution. Much longer, not pretty, but reasonably effective.

In the end, if I had done my “fill then look up locations” approach I used for part II for the first puzzle, it would have provided a much quicker solution although I don’t think it would have been as short or, in my opinion, nifty.

What approach did you end up using for day 3? And what made you go with that design?

Building automatic `OptionSet` entries

Last night Zev Eisenberg was asking about option sets. “Do you still have to specify 1 << _n_ manually for OptionSet conformance? There’s no magic?” So I decided to build him some magic. There’s really no reason you should have to manually put in numbers like this:

public struct Traits: OptionSet {
    public typealias RawValue = Int
    public var rawValue = 0
    public init(rawValue: Traits.RawValue) {
        self.rawValue = rawValue
    }
    
    public static let bolded = 1 << 0
    public static let italicized = 1 << 1
    public static let monospaced = 1 << 2
    public static let underlined = 1 << 3
    public static let outlined = 1 << 4
}

This approach requires unnecessary bookkeeping. You have to keep track of the bits you’ve used, especially if you add or insert new options, or reorder the options  you have. It gives unnecessary prominence to the implementation detail values. There should be a more magic way.

So I decided to write him a solution that automatically generated the bit flags and hid those details from the implementation. The result looks like this:

 public static let bolded = generateOption()
 public static let italicized = generateOption()
 public static let monospaced = generateOption()
 public static let underlined = generateOption()
 public static let outlined = generateOption()

You can move things around, add new items, delete old items. It really doesn’t make a difference from a code maintenance point of view (assuming you’re doing this all during development, not after deployment, where you’d want to use availability and deprecations).

To get here, I needed to create a function that would add type-specific options to any type that conforms to OptionSet. I created a global dictionary to store option counts:

private var _optionSetDict: [AnyHashable: Int] = [:]

To be honest, I hate unparented globals like this. However, Swift does not allow adding static stored values in extensions. I couldn’t think of another better way to handle this. I also built a second global to ensure this dictionary would prevent concurrent access, so my counts would be secure:

private var _optionSetAccessQueue = DispatchQueue(
    label: "sadun.OptionSetGeneration", attributes: [.concurrent])

I needed to box my type references since Swift doesn’t allow types to conform to Hashable. They won’t work out of the box with dictionaries. This solution let me use types as keys:

/// Wraps a type to enable it for use as a dictionary key
public struct TypeWrapper<Wrapped>: Hashable {
    private let type: Wrapped.Type
    public init(_ type: Wrapped.Type) {
        self.type = type
    }
    
    /// Conforms to Equatable
    public static func ==(lhs: TypeWrapper, rhs: TypeWrapper) -> Bool {
        return lhs.type == rhs.type
    }
    
    /// Conforms to Hashable
    public var hashValue: Int {
        return ObjectIdentifier(type).hashValue
    }
}

To create a hashable type entry, I just instantiate TypeWrapper with the type.

Sven Weidauer points out I can use ObjectIdentifier directly
Here’s the OptionSet extension that implements the generateOption() magic:

public extension OptionSet where RawValue == Int {
    public static func generateOption() -> Self { 
        let key = ObjectIdentifier(Self.self)
        return _optionSetAccessQueue.sync(flags: [.barrier]) {
            // This should be locked so there's a guarantee that
            // counts are unique for each generated option
            let count = _optionSetDict[key, default: 0]
            _optionSetDict[key] = count + 1
            return .init(rawValue: 1 << count)
        }
    }
}

I’m not sure that I’d ever actually use this approach in code but it was a fun exercise in problem solving. Sven W. adds “Another thing to keep in mind is that statics are initialised the first time they are used. So in different runs of the program the values can differ. Better not persist OptionSets created by this technique.”

You can see the full implementation over at Github. And if you’re curious, you can go back through the change history to see some earlier takes on the problem.

Like it? Hate it? Got suggestions and improvements? (I always mess something up, so there’s a pretty much 100% chance there’s room for improvement.) Drop a note, a tweet, an email, or a comment.

Thanks to Ian Keen, who suggested extending OptionSet directly.

Four Lessons from Circle Intersection

Yesterday, a fairly simple discussion of circle intersection came up: how do you subtract one circle from another to form a “cut out” Bezier path. This allows you to add an affordance or decoration to a circle, but add some space between the primary figure and the secondary bubble.

Exploring this question provided some interesting lessons that I thought I’d share in a quick post.

Embrace Core Graphics Types

When working with basic geometry, redirect your mathematics to Core Graphics. Bezier paths, points, rects, and other core geometric features use CGFloat, not Double. You minimize your pain by extending CGFloat as needed to address common geometric concerns such as exponentiation or mathematical constants rather than switching back and forth between Swift.Double and CGFloat:

/// Exponentiation operator
infix operator **: HighPrecedence

extension CGFloat {
    /// Returns base ^^ exp
    /// - parameter base: the base value
    /// - parameter exp: the exponentiation value
    public static func **(base: CGFloat, exp: CGFloat) -> CGFloat {
        return CGFloat(pow(Double(base), Double(exp)))
    }
    
    /// Tau
    public static var tau = CGFloat(Double.pi * 2.0)
}

Construct utility types

It helps to think about the kinds of types that will support your geometric challenge. For this example, I built two new types: a line segment (2 end points) and a circle (a center and a radius). Bringing these under the Core Graphics umbrella unified my representations with the tools they need to express their geometry:

/// 2-point representation of line segment
public struct Segment {
    public let (p1, p2): (CGPoint, CGPoint)
    var dx: CGFloat { return p2.x - p1.x }
    var dy: CGFloat { return p2.y - p1.y }
    public var length: CGFloat { 
        return sqrt(dx ** 2 + dy ** 2) 
    }
}

/// Center/Radius circle representation
public struct Circle {
    public let center: CGPoint
    public let radius: CGFloat
}

Being Core Graphic native enables you to leverage constructors using the appropriate types. For example, my circle can construct a path for drawing to a UIKit-compatible context:

/// Returns a Bezier path sweeping between two angles
public func path(from startAngle: CGFloat = 0, to endAngle: CGFloat = CGFloat.tau, 
    clockwise: Bool = true) -> UIBezierPath {
    return UIBezierPath(arcCenter: center, radius: radius,
                        startAngle: startAngle, endAngle: endAngle,
                        clockwise: clockwise)
}

This path method allows me to express each circle as a path, hiding the details of a UIBezierPath constructor. When I want to throw up a visual reference point, I just construct a circle at that point and fill it:

let p1 = Circle(center: segment.p1, radius: 2.5)
p1.path().fill()

Very handy.

Let the math be the math

When you’re working with standard algorithms, it helps to step back from your standard Swift key paths and use the terms of art you’re translating into code. For example, it can be convenient to break down some basic Swift into algorithm-specific terms:

let (x1, y1, r1) = (self.center.x, self.center.y, self.radius)
let (x2, y2, r2) = (other.center.x, other.center.y, other.radius)

It may not be “Swifty”, but doing so leads to easier inspection when comparing your implementation to the how-to reference in a book or paper.

Draw It

Playgrounds are great when it comes to testing drawing algorithms because you can use real data and get immediate results to see whether your assumptions and expectations are properly met.

In this example, the first two circles intersect, allowing the construction of the “chunked out” major circle and a condensed minor circle. The original circles are outlined and the two red points indicate the overlap points.

The second pair does not intersect, so it’s left simply as two outlines.

If you want to play around with this rough implementation, I left the code for this over at github. Feel free to expand or improve upon my approach, as it was very much an off-hand “here’s more or less how you can do this” exercise.

Bluetooth Lessons I: Manager and Scanning

Last June, Izzy inspired me to do something with Bluetooth and playgrounds but honestly, I haven’t had the time and I couldn’t afford a Sphereo. I’ve wrapped up Swift Style. Attempting to write meaningfully about drawing while the Denver Public School system has for reasons I cannot begin to comprehend released my child to my recognizance for two entire weeks seems unlikely. (Another child has half days. Fun.)

To prepare, I purchased one of the cheapest BLE devices I could find, a Mi wristband (Amazon cost under $20 shipped), which has a reverse engineered API that lets you control vibration. A friend of mine just purchased the hugely expensive Buzzies for Autism bands. I’m  hoping I can mimic some of that functionality with a playground, a low-rent BLE device, and a full-price child.

Have I mentioned recently how awesome playgrounds are for playing around with and learning about new tech? They really are, especially because you can integrate just one concept at a time, and then test it live before expanding to the next.

I decided to go with Cocoa for my BLE exploration instead of iOS, although the tech is more or less the same on both platforms. When you work in Cocoa, using a macOS playground, the startup speed is phenomenal because you don’t have to work with a simulator.

My first project simply sets up a central manager (CBCentralManager), monitors its state, and lists any devices it finds. I’m pretty happy for this as a first day, not many hours to spend on it, playing around and doing something marginally useful result.

The CoreBluetooth documentation is pretty dire. For example, this is the Swift docs for CBManagerStatePoweredOn.  After SE-0005, the constant is actually .poweredOn, as you see in the following sample code, not CBManagerStatePoweredOn. And there’s no documentation in that documentation.

Nonetheless, I persevered and my first child-full day produced a basic helper class. You really need to work in NSObject land for this because of all the delegation. So I set up an objc-friendly class, set it as a manager delegate, and implemented the one required callback method, which follows the manger state.

Try sticking the Bluetooth icon in your system menu bar.  (System Preferences > Bluetooth > Show Bluetooth in menu bar.) It’s a lot of fun to toggle it on and off and watch your playground keep tabs on that state.

Next, I added a basic peripheral scan. You need to scan only when the manager achieves poweredOn state.

Apple writes, “Before you call CBCentralManager methods, the state of the central manager object must be powered on, as indicated by the CBCentralManagerStatePoweredOn constant. This state indicates that the central device (your iPhone or iPad, for instance) supports Bluetooth low energy and that Bluetooth is on and available to use.”

That’s why I added the scan to the playground’s “update state” callback. You’ll want to stop scans when the BLE powers off.

Finally, I implemented one more callback, which asynchronously lists discovered peripherals. It picked up nicely on my Apple TV and when I enabled and disabled a hotspot on my iPhone. Great fun.

Here’s the code involved. You can see how very short it is. The struggle wasn’t in the lines of code or complexity, it’s mostly about how very badly documented most everything seems to be.

I’ll post more as time allows.

https://gist.github.com/erica/d249ff13aec353e8a8d72a1f5e77d3f8

That API thing

Today, Nikita Voloboev was trying to wrap his head around how this whole Cocoa/Cocoa Touch API thing worked. The conversation started when he asked, “Is UIKit part of Cocoa?” The docs weren’t really giving him an idea of how it all worked. After a few minutes back and forth, he derived this concept using the tools at mindnode.com:

It was a good first guesstimate even though it doesn’t exactly capture Apple’s API design. I hopped into Preview and sketched out this diagram instead. (And yes, some day I may write a book about all the cool things you can do for free in Preview):

I explained how the API families shared certain frameworks but that the frameworks weren’t uniformly implemented across all the platforms within that family. Cocoa and Cocoa Touch, I tried to explain, were the API families specific to four operating systems: macOS, iOS, watchOS, and tvOS.

I pointed him to this definition, which I pulled up by a web search for define cocoa apple:

Cocoa is Apple’s native object-oriented application programming interface (API) for their operating system macOS. For iOS, tvOS, and watchOS, a similar API exists, named Cocoa Touch, which includes gesture recognition, animation, and a different set of graphical control elements.

He then threw that definition into another mind map, which he uses to keep notes. This was a cool and unexpected way of exploring new knowledge:

 

I’m fascinated by his learning toolset, which includes both mind mapping and Anki Decks (see https://apps.ankiweb.net and this explanation of Spaced repetition.) I tend to turn to paper and pen, or other familiar tools, to take notes or to share.

What kind of tools do you use to explore and explain new areas of learning?

My first Cozmo game: Hide and Seek

In my continuing exploration of the Cozmo SDK, I’ve written my first  game. “Hide and Seek” is not particularly complex or challenging. I’m still pretty new to both Python and the SDK tools and my wrapper code is still pretty basic.

“Hide and Seek” goes like this. You place a light cube near Cozmo out of his direct line of sight. He searches until he finds it, picks it up, moves it to a new location, and drops it. He then turns around, with his back to the cube and says “Let’s play again”.

Although this is a first take, I think my wrapper approach remains pretty simple and readable. I’m trying to emphasize learning programming concepts, using Python, which means that Cozmo access needs to be encapsulated and procedural:

# run, cozmo, run
def actions(cozmoLink):
    '''Specify actions for cozmo to run.'''
    
    # Fetch robot
    coz = Cozmo.robot(cozmoLink)
    coz.say("Hide and seek!")

    # Look for a cube
    if not coz.findACube():
        coz.say("No cube")
        return

    # Found one!
    coz.say("I found a cube")
    coz.takeCube() # Pick it up
    coz.say("I have the cube")
    coz.drive(time = 3, direction = Direction.forward) # Drive
    coz.dropCube() # Place the cube
    coz.turn(degrees = 180) # Turn around
    coz.say("Let's play again")

Cozmo.startUp(actions)

The most complex concept here is searching for a block (coz.findACube()) and acting on a Boolean return value. I’m not completely in love with how I established this notion. Maybe something more along the lines of “ask to look and find” instead of just “find” would better indicate conditionality.

Under the covers, the Cozmo class now stores both a cube of interest and a list of cubes within view. I’m not sure I’m going to stay with this specific design but this new feature is what allows you to omit mentioning the cube instance in the latter half of the game. I think I probably need to step back and refactor to evolve a Cozmo’s “world” class, to describe what he sees, and better mirror the world in the direct APIs.

Here’s a video of the “Hide and Seek” gameplay:

My immediate goals are to encapsulate all the asynchronous and exception-handling code into very simple call styles. I want to model the world, the robot, and the interactions in a more human-based way, to support simple programming concepts: procedure, state, condition, iteration, and eventually functions.

Even though I’m directly interested in teaching, at the back of my mind, I want to eventually get to the point where I can introduce some emotion programming, which I think is perfect for Cozmo.

I wouldn’t have to start from scratch. There’s some GPL licensed work done in the Facemoji project. Facemoji harvests an emotion dataset, classifies the emotions, and then matches incoming video against the data set. Wouldn’t it be great if Cozmo could react to your face beyond recognition, playing off happiness, sadness, etc?

Programming Cozmo

Anki has been kind enough to let me play with their new Cozmo unit and explore their SDK. Cozmo is a wonderful device, developed by people who understand a lot of core principles about human interaction and engagement.

Cozmo is adorable. When it recognizes your face, it wriggles with happiness. It explores its environment. When it’s bored, it sets up a game to play with you. It can get “upset” and demand attention. It’s one of the most personable and delightful robots I’ve played with.

At its heart is a well-chosen collection of minimal elements. The unit can move around the room, with a 4-wheel/2-tread system. It includes an onboard forklift that can rise and fall, an OLED “face” that expresses emotion, and a camera system that ties into a computer vision system, which I believe is based on PIL, the Python Image Library. (Anki tells me that Cozmo’s vision system “does not use PIL or Python in any way, though the Python SDK interface uses PIL for decoding jpegs, drawing animations, etc.”)

Three lightweight blocks with easily-identified markings complete the Cozmo package, which Cozmo can tap, lift, stack, and roll.

Between its remarkable cuteness and its vision-based API, it’s a perfect system for introducing kids to programming. I was really excited to jump into the SDK and see how far I could push it.

Here is Anki’s “Hello World” code (more or less, I’ve tweaked it a little) from their first developer tutorial:

import sys
import cozmo

'''
Hello Human
Make Cozmo say 'Hello Human' in this simple
Cozmo SDK example program.
'''

def run(sdk_conn):
    robot = sdk_conn.wait_for_robot()
    robot.say_text("Hello Human").wait_for_completed()
    print("Success")

if __name__ == '__main__':
    cozmo.setup_basic_logging()    
    try:
        cozmo.connect(run)
    except cozmo.ConnectionError as err:
        sys.exit("Connection error ????: %s" % err)

Although simple, this “Hello World” includes quite a lot of implementation details that can scare off young learners. For comparison, here’s the start of Apple’s tutorial on Swift “Learn to Code”:

screen-shot-2016-12-12-at-11-45-24-am

There’s such a huge difference here. In Apple’s case, everything that Byte (the main character) does is limited to easy-to-understand, simple calls. The entire implementation is abstracted away, and all that’s left are instructions and very directed calls, which the student can put together, re-order, and explore with immediate feedback.

In Anki’s code, you’re presented with material that’s dealing with set-up, exceptions, asynchronous calls, and more. That is a huge amount of information to put in front of a learner, and to then say “ignore all of this”. Cozmo is underserved by this approach. Real life robots are always going to be a lot more fun to work with than on-screen animations. Cozmo deserved as simple a vocabulary as Byte. That difference set me on the road to create a proof of concept.

In this effort, I’ve tried to develop a more engaging system of interaction that better mirrors the way kids learn. By creating high level abstractions, I wanted to support the same kind of learning as “Learn to Code”. Learn to Code begins with procedural calls, and then conditional ones, and moving on to iteration and functional abstraction, and so forth.

My yardstick of success has been, “can my son use these building blocks to express goals and master basic procedural and conditional code?” (I haven’t gotten him up to iteration yet.) So far, so good, actually.  Here is what my updated “Hello World” looks like for Cozmo, after creating a more structured entry into robot control functionality:

from Cozmo import *

# run, cozmo, run
def actions(cozmoLink):
    '''Specify actions for cozmo to run.'''
    
    # Fetch robot
    coz = Cozmo.robot(cozmoLink)

    # Say something
    coz.say("Hello Human")

Cozmo.startUp(actions)

Not quite as clean as “Learn to Code” but I think it’s a vast improvement on the original. Calls now go through a central Cozmo class. I’ve chunked together common behavior and I’ve abstracted away most implementation details, which are not of immediate interest to a student learner.

Although I haven’t had the time to really take this as far as I want, my Cozmo system can now talk, drive, turn, and engage (a little) with light cubes. What follows is a slightly more involved example. Cozmo runs several actions in sequence, and then conditionally responds to an interaction:

from Cozmo import *
from Colors import *

# Run, Cozmo, run
def actions(cozmoLink):
    '''Specify actions for cozmo to run.'''
    
    # Fetch robot
    coz = Cozmo.robot(cozmoLink)

    # Say something
    coz.say("Hello")

    # Drive a little
    coz.drive(time = 3, direction = Direction.forward)
    
    # Turn
    coz.turn(degrees = 180)
    
    # Drive a little more
    coz.drive(time = 3, direction = Direction.forward)

    # Light up a cube
    cube = coz.cube(0)
    cube.setColor(colorLime)
    
    # Tap it!
    coz.say("Tap it")    
    if cube.waitForTap():
        coz.say("You tapped it")
    else:
        coz.say("Why no tap?")
    cube.switchOff()

Cozmo.startUp(actions)

And here is a video showing Cozmo executing this code:

If you’d like to explore this a little further:

  • Here is a video showing the SDK feedback during that execution. You can see how the commands translate to base Cozmo directives.
  • I’ve left a bit of source code over at GitHub if you have a Cozmo or are just interested in my approach.

As you might expect, creating a usable student-focused learning system is time consuming and exhausting. On top of providing controlled functionality, what’s missing here is a lesson plan and a list of skills to master framed into “Let’s learn Python with Cozmo”. What’s here is just a sense of how that functionality might look when directed into more manageable chunks.

Given my time frame, I’ve focused more on “can this device be made student friendly” than producing an actual product. I believe my proof of concept shows that the right kind of engagement can support this kind of learning with this real-world robot.

The thing that appeals most to me about Cozmo from the start has been its rich computer vision capabilities. What I haven’t had a chance to really touch on yet is its high level features like “search for a cube”, “lift it and place it on another cube”, all of which are provided as building blocks in its existing API, and all of which are terrific touch points for a lesson plan.

I can easily see where I’d want to develop some new games with the robot, like lowering reaction time (it gets really hard under about three quarters of a second to tap that darn cube) and creating cube-to-cube sequences of light. I’d also love to discover whether I can extend detection to some leftovers my son brought home from our library’s 3D printer reject bin.

Cozmo does not offer a voice input SDK. It’s only real way to interact is through its cameras (and vision system) and through taps on its cubes. Even so, there’s a pretty rich basis to craft new ways to interact.

As for Anki’s built-ins, they’re quite rich. Cozmo can flip cubes, pull wheelies, and interact in a respectably rich range of physical and (via its face screen) emotional ways.

Even if you’re not programming the system, it’s a delightful toy. Add in the SDK though, and there’s a fantastic basis for learning.