Squashing bugs in SpikeMark (part 1 of 3)

If you’ve been paying attention to the updates on our site, you may have noticed a flurry of activity recently. We added some new features to SpikeMark which I’ll discuss in another post, but we also have been tracking down some nasty little bugs. The latest rash of bug squashing has been centered around a theme, because multiple performances in various venues have been experiencing similar problems involving tight sequences of linked cues.
Scenario A:
A winch track dragging a pallet onstage with a Stagehand FX running a tab curtain. When the winch is within 1′ of the curtain, a position trigger raises the curtain and the winch continues through. Once the winch is clear of the tab curtain, the FX lowers the curtain. Seems simple right?
Winch onstage to position 120″
|
|___FX Raise curtain when winch is at position 6″
|
|___FX Lower curtain when winch is at position 24″
Unfortunately, what really happens is once the wagon is clear of the curtain and the second link fires, the FX goes crazy and ping-pongs between link #1 and link #2 making the tab curtain look like possessed window shade in a haunted house as it oscillates up and down rapidly.
What the heck! Well, it stinks, but it will make sense if I explain some of SpikeMark’s internals.
Links are tricky beasts (aka the bane of my existence). Each flavor of link has it’s own can of worms, but position triggered links are perhaps the most devious. It sounds deceptively simple right? When the winch is at position 6″ just fire the next cue. Sure. But that doesn’t work almost ever. SpikeMark doesn’t get to witness every position increment on a motor while it’s moving. SpikeMark sends out requests for status updates from all the motors on the network once every 125ms by default. So, it only gets fresh information regarding the motors position, limits, speed, and e-stop 8 times per second. A motor moving at 24″/sec will travel 3″ in between status updates. SpikeMark might see the motor at position 2″, 5″, & 8″. If we waited to see 6″ the link would never execute. Hmm, what do we do?
Well, it’s simple and probably obvious to you. A position trigger is constantly listening to the parent cue. When the cue’s status changes to “running”, the link starts listening to the pertinent motor’s position. If the motor is moving forward and the position is greater than or equal to the link trigger position, it executes. If the motor is moving in reverse and the position is less than or equal to the motor trigger position, it executes. Sounds good right? Pretty close. However, we need another rule layered onto this logic. If the link is anything except “idle”, don’t execute. Why? Well, if we didn’t add that check into the mix the link would keep executing over and over because it would see position 9″ and think “OK, we’ve passed the trigger point, GO”. And then at position 12″ it would think “OK, we’ve passed the trigger point, GO.” And then at position 15″…. well you get the idea. A link should not execute if it is already running, complete or faulted.
You with me so far? Good. So how does a cue transition from “complete” to “idle”, since having an “idle” status sounds so central to making sure links run at the appropriate time and stay dormant all other times. Well, whenever a motor from a completed cue is loaded with another cue, the “complete” cue transitions to “idle”. In other words, a cue is “complete” until one of its motors is taken by another cue, then it’s in limbo or “idle”. If you see the root of this bug, congratulations! Please write to me, we may have a job for you ![]()
So lets step through the cue process logically for this ugly little scenario.
- The winch cue is running
- Link #1 waits until the winch reaches at least 6″ (or any position greater than 6″) and then starts running
- Link #1 completes
- Link #2 waits until the winch position meets or exceeds 24″
- Link #2 starts to run. Ah hah! When link #2 starts running, link #1 becomes idle because link #1 has lost control of it’s Stagehand to link #2
- Link #1 now sees that the winch has exceeded position 6″ and the link is idle (not complete any more) so it executes
- Link #2 transitions to idle, since it has lost control of its Stagehand to link #1
- Link #2 sees that the winch has exceeded position 24″ and the link is idle so it executes
- and the vicious cycle continues until the winch complete…
The root of the problem is that cues don’t have any record of when they were last run so links can’t tell if they’ve already executed for this sequence or if this is a new run-through (like when you move back in tech rehearsal). Instead, links are always watching for the proper conditions to be met and will then execute. This has, for the most part, proved the most reliable and simplest mechanism for links. As the paraphrased quote goes, “the solution should be as simple as possible, but no simpler.” Perhaps we are just a tad too simple in this instance. I think we need to add some tracking ID to cues so that each time they are run they get stamped with an identifier that links can use to distinguish one run-through from the next and mix that logic into their conditional checks. Of course, that’s a pretty big/deep change and will need to be well tested for other unseen problems before we can release it. And, it probably warrants a little more contemplation before even writing the code just to make sure that it’s the most logical model before making such a structural change.
What’s the workaround? For now, the show has to use two winch cues that both run to the same target:
Winch onstage to position 120″
|
|___FX raise curtain
||___Winch onstage to position 120″
|
|___FX lower curtain
Since motors don’t need to stop between cues, this behaves perfectly well, but it’s cludgy and unintuitive to write.
Stay tuned for more tales of weirdo link bugs when we dig into timing issues next.