Testing FANUC TP Programs with Ruby

Filed under: FANUC TP Programming Testing

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:

  1. The setup method is called before each test_* method. This gives us a new TP::Runtime instance
  2. There are 4 tests:
    1. Make sure grip.ls turns on the gripper output to close the gripper
    2. Make sure ungrip.ls turns off the same output
    3. Make sure check_grip.ls returns a 1 in the status register when a part is present
    4. Make sure check_grip.ls returns a 0 in the status register when a part if not present

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.


Want posts like this delivered right to your inbox?

If you liked this post, please sign up for my mailing list!