I’ve written about testing before, but I still can’t get over the fact that the state of the art method for testing multi-million dollar industrial robot cells is trial and error. That’s why I’ve started working on an environment for reliably testing FANUC TP code.
I’ve basically written a Ruby gem to correctly parse, interpret and execute TP programs within a simulated runtime. With this environment I can use any of Ruby’s great testing tools to make sure the robot does what it’s supposed to do.
Example
Here’s a simple example that uses minitest to test the operation of some gripper macros:
require 'helper'
class TestGripper < MiniTest::Test
def setup
@controller = TP::Runtime.new
end
def test_grip_macro_closes_gripper
run_program 'grip.ls'
assert @controller.get_io(:do, 1)
end
def test_ungrip_macro_opens_gripper
run_program 'ungrip.ls'
assert !@controller.get_io(:do, 1)
end
def test_check_grip_returns_1_in_status_reg_when_part_present
@controller.force_input(:di, 1, true)
run_program 'check_grip.ls'
assert_equal 1.0, @controller.get_numeric_register(4)
end
def test_check_grip_returns_0_in_status_reg_when_part_not_present
@controller.force_input(:di, 1, false)
run_program 'check_grip.ls'
assert_equal 0.0, @controller.get_numeric_register(4)
end
end
If you’re not familiar with Ruby, here’s a quick summary of what’s happening:
- The
setup
method is called before each test_* method. This gives us a newTP::Runtime
instance - There are 4 tests:
- Make sure
grip.ls
turns on the gripper output to close the gripper - Make sure
ungrip.ls
turns off the same output - Make sure
check_grip.ls
returns a 1 in the status register when a part is present - Make sure
check_grip.ls
returns a 0 in the status register when a part if not present
- Make sure
When I run the test, I see this in my console:
$ rake test
Started
4/4: [==================================================100% 00:00:00
Finished in 0.04459s
4 tests, 4 assertions, 0 failures, 0 errors, 0 skips
If any of these had failed, I can go back and fix the TP code (or the test itself if it’s incorrect) and run my tests again to know that I’ve fixed it without unintentionally breaking something else.
Here’s the simple TP code:
/PROG check_grip
/MN
: IF DI[1]=OFF,JMP LBL[500] ;
: R[4:status]=1 ;
: JMP LBL[999] ;
: ;
: LBL[500] ;
: R[4:status]=0 ;
: JMP LBL[999] ;
: ;
: LBL[999] ;
/END
/PROG GRIP
/MN
: DO[1]=ON ;
/END
/PROG UNGRIP
/MN
: DO[1]=OFF ;
/END
“In English, Please”
Testing can also help us communicate and document scope with the client. Cucumber is a behavior driven development (BDD) framework for Ruby that lets you describe how you want the program to behave in plain english, then test that behavior.
Here’s an example of how you might write a Cucumber feature for a machine-tending application:
Feature: Tending Machine A
In order to make parts efficiently
As a manufacturer
I want a robot to tend machine A
Scenario: Loading and unloading the machine
Given the robot is holding a part
And the machine is ready for loading
When the robot tends the machine
Then the cycle time should be less than 30 seconds
Scenario: Error while machining
Given the robot is holding a part
And the machine is ready for loading
When the robot tends the machine
And the machine faults while machining
Then the robot should sound an alarm
And the robot should show an error to the operator
Cucumber works by linking each line of these behaviors with some code that exercises the robot. The tests are to be written in such a way that the client can read and sign off that they correctly express the acceptance criteria for the machine. If the tests pass, you have an acceptable machine.
If a bug pops up, you can write a test to duplicate the issue. Once you fix it, you then have a test to make sure it never pops up again. If you have a comprehensive suite of tests, you can make changes without worrying about breaking things.
Interested?
I still have some development work to do, but please send me a message if this looks interesting to you. I’m not sure how or if I will release this tool for public consumption, but I’m wondering if anyone else out there feels the same way I do about testing.
The other cool thing about having a working TP parser and interpreter is that I can hook it into all sorts of different things: an Arduino robot that runs valid TP code, a simulation tool built in Unity, or an iPhone app for writing programs on the go. Look out for future posts on this subject.