Import LinuxCNC source tree
This commit is contained in:
2
tests/hard-limits/.gitignore
vendored
Normal file
2
tests/hard-limits/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
rs274ngc.var
|
||||
rs274ngc.var.bak
|
||||
4
tests/hard-limits/README
Normal file
4
tests/hard-limits/README
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
This test reproduces Issue #117. It homes an id-kins machine, starts
|
||||
a jog, and then (while moving) trips a limit switch (ie a hard limit).
|
||||
|
||||
4
tests/hard-limits/checkresult
Executable file
4
tests/hard-limits/checkresult
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# Success or failure of this test is handled in the test.sh script, if we
|
||||
# get this far it's a success.
|
||||
exit 0
|
||||
15
tests/hard-limits/hard-limits.hal
Normal file
15
tests/hard-limits/hard-limits.hal
Normal file
@@ -0,0 +1,15 @@
|
||||
loadrt [KINS]KINEMATICS
|
||||
loadrt [EMCMOT]EMCMOT servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
|
||||
|
||||
addf motion-command-handler servo-thread
|
||||
addf motion-controller servo-thread
|
||||
|
||||
net xpos joint.0.motor-pos-cmd => joint.0.motor-pos-fb
|
||||
net x-neg-lim-sw => joint.0.neg-lim-sw-in
|
||||
|
||||
net ypos joint.1.motor-pos-cmd => joint.1.motor-pos-fb
|
||||
|
||||
net zpos joint.2.motor-pos-cmd => joint.2.motor-pos-fb
|
||||
|
||||
net estop-out <= iocontrol.0.user-enable-out
|
||||
net estop-out => iocontrol.0.emc-enable-in
|
||||
85
tests/hard-limits/hard-limits.ini
Normal file
85
tests/hard-limits/hard-limits.ini
Normal file
@@ -0,0 +1,85 @@
|
||||
[EMC]
|
||||
# The version string for this INI file.
|
||||
VERSION = 1.1
|
||||
|
||||
MACHINE = hard-limits
|
||||
#DEBUG = 0
|
||||
DEBUG = 0x7fffffff
|
||||
|
||||
[DISPLAY]
|
||||
DISPLAY = ./test-ui.py
|
||||
|
||||
[EMCMOT]
|
||||
EMCMOT = motmod
|
||||
COMM_TIMEOUT = 4.0
|
||||
SERVO_PERIOD = 1000000
|
||||
|
||||
[TASK]
|
||||
TASK = milltask
|
||||
CYCLE_TIME = 0.010
|
||||
|
||||
[HAL]
|
||||
HALFILE = hard-limits.hal
|
||||
|
||||
[TRAJ]
|
||||
AXES = 3
|
||||
COORDINATES = X Y Z
|
||||
LINEAR_UNITS = inch
|
||||
ANGULAR_UNITS = degree
|
||||
DEFAULT_LINEAR_VELOCITY = 0.10
|
||||
MAX_LINEAR_VELOCITY = 1.00
|
||||
|
||||
[KINS]
|
||||
KINEMATICS = trivkins
|
||||
JOINTS = 3
|
||||
|
||||
[AXIS_X]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
|
||||
[JOINT_0]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
FERROR = 0.05
|
||||
MIN_FERROR = 0.01
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_OFFSET = 0.0
|
||||
|
||||
[AXIS_Y]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
|
||||
[JOINT_1]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
FERROR = 0.05
|
||||
MIN_FERROR = 0.01
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_OFFSET = 0.0
|
||||
|
||||
[AXIS_Z]
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
|
||||
[JOINT_2]
|
||||
TYPE = LINEAR
|
||||
HOME = 0.0
|
||||
MAX_VELOCITY = 1.0
|
||||
MAX_ACCELERATION = 30.0
|
||||
FERROR = 0.05
|
||||
MIN_FERROR = 0.01
|
||||
MIN_LIMIT = -10.0
|
||||
MAX_LIMIT = 10.0
|
||||
HOME_OFFSET = 0.0
|
||||
278
tests/hard-limits/test-ui.py
Executable file
278
tests/hard-limits/test-ui.py
Executable file
@@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import linuxcnc
|
||||
import hal
|
||||
|
||||
import time
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
import signal
|
||||
import glob
|
||||
import re
|
||||
|
||||
|
||||
def print_status(status):
|
||||
status.poll()
|
||||
print("status.axis[0]: {}".format(status.axis[0]))
|
||||
print("status.axis[1]: {}".format(status.axis[1]))
|
||||
print("status.joint[0]: {}".format(status.joint[0]))
|
||||
print("status.joint[1]: {}".format(status.joint[1]))
|
||||
print("status.current_vel: {}".format(status.current_vel))
|
||||
print("status.echo_serial_number: {}".format(status.echo_serial_number))
|
||||
print("status.enabled: {}".format(status.enabled))
|
||||
print("status.estop: {}".format(status.estop))
|
||||
print("status.exec_state: {}".format(status.exec_state))
|
||||
print("status.inpos: {}".format(status.inpos))
|
||||
print("status.interp_state: {}".format(status.interp_state))
|
||||
print("status.interpreter_errcode: {}".format(status.interpreter_errcode))
|
||||
print("status.limit: {}".format(status.limit))
|
||||
print("status.motion_mode: {}".format(status.motion_mode))
|
||||
print("status.motion_type: {}".format(status.motion_type))
|
||||
print("status.position: {}".format(status.position))
|
||||
print("status.state: {}".format(status.state))
|
||||
print("status.task_mode: {}".format(status.task_mode))
|
||||
print("status.task_state: {}".format(status.task_state))
|
||||
print("status.velocity: {}".format(status.velocity))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def assert_wait_complete(command):
|
||||
r = command.wait_complete()
|
||||
print("wait_complete() returns {}".format(r))
|
||||
assert((r == linuxcnc.RCS_DONE) or (r == linuxcnc.RCS_ERROR))
|
||||
|
||||
|
||||
#
|
||||
# connect to HAL
|
||||
#
|
||||
|
||||
comp = hal.component("test-ui")
|
||||
comp.newpin("x-neg-lim-sw", hal.HAL_BIT, hal.HAL_OUT)
|
||||
comp.ready()
|
||||
|
||||
hal.connect('test-ui.x-neg-lim-sw', 'x-neg-lim-sw')
|
||||
|
||||
|
||||
#
|
||||
# connect to LinuxCNC
|
||||
#
|
||||
|
||||
c = linuxcnc.command()
|
||||
s = linuxcnc.stat()
|
||||
e = linuxcnc.error_channel()
|
||||
|
||||
|
||||
#
|
||||
# Come out of E-stop, turn the machine on, switch to Manual mode, and home.
|
||||
#
|
||||
|
||||
c.state(linuxcnc.STATE_ESTOP_RESET)
|
||||
c.state(linuxcnc.STATE_ON)
|
||||
c.mode(linuxcnc.MODE_MANUAL)
|
||||
c.home(0)
|
||||
c.home(1)
|
||||
c.home(2)
|
||||
c.wait_complete()
|
||||
|
||||
# wait for homing to complete
|
||||
start_time = time.time()
|
||||
s.poll()
|
||||
all_homed = s.homed[0]+s.homed[1]+s.homed[2]
|
||||
while (all_homed != 3) and (time.time() - start_time < 5):
|
||||
time.sleep(0.100)
|
||||
s.poll()
|
||||
all_homed = s.homed[0]+s.homed[1]+s.homed[2]
|
||||
|
||||
if all_homed != 3:
|
||||
print("failed to home")
|
||||
print("s.homed: {}".format(s.homed))
|
||||
sys.exit(1)
|
||||
|
||||
c.teleop_enable(0)
|
||||
|
||||
|
||||
#
|
||||
# run the test: start a jog on X, then trip a limit switch
|
||||
#
|
||||
|
||||
# jog arguments are: (jog_type, joint_flag, axis, velocity)
|
||||
c.jog(linuxcnc.JOG_CONTINUOUS, 1, 0, -0.1)
|
||||
|
||||
# verify that we're starting to move
|
||||
s.poll()
|
||||
old_x = s.position[0]
|
||||
start_time = time.time()
|
||||
while (old_x == s.position[0]) and (time.time() - start_time < 5):
|
||||
time.sleep(0.1)
|
||||
s.poll()
|
||||
|
||||
if old_x == s.position[0]:
|
||||
print("no jog movement")
|
||||
sys.exit(1)
|
||||
|
||||
print("x started moving (%.6f to %.6f)" % (old_x, s.position[0]))
|
||||
print_status(s)
|
||||
|
||||
# verify that Status reflects the situation
|
||||
assert(s.joint[0]['min_soft_limit'] == False)
|
||||
assert(s.joint[0]['min_hard_limit'] == False)
|
||||
assert(s.joint[0]['max_soft_limit'] == False)
|
||||
assert(s.joint[0]['max_hard_limit'] == False)
|
||||
assert(s.joint[0]['inpos'] == False)
|
||||
assert(s.joint[0]['enabled'] == True)
|
||||
|
||||
assert(not (1 in s.limit))
|
||||
assert(s.inpos == False)
|
||||
assert(s.enabled == True)
|
||||
|
||||
# trip the limit switch
|
||||
comp['x-neg-lim-sw'] = True
|
||||
|
||||
# let linuxcnc react to the limit switch
|
||||
expected_error = 'joint 0 on limit switch error'
|
||||
start_time = time.time()
|
||||
while (time.time() - start_time < 5):
|
||||
error = e.poll()
|
||||
if error != None:
|
||||
if error[1] == expected_error:
|
||||
break
|
||||
else:
|
||||
print("linuxcnc sent other error %d: %s" % (error[0], error[1]))
|
||||
time.sleep(0.1)
|
||||
|
||||
if error == None or error[1] != expected_error:
|
||||
print("no limit switch error from LinuxCNC")
|
||||
sys.exit(1)
|
||||
|
||||
print("linuxcnc sent error %d: %s" % (error[0], error[1]))
|
||||
print_status(s)
|
||||
|
||||
# verify that we're stopping
|
||||
s.poll()
|
||||
start_time = time.time()
|
||||
while (s.joint[0]['velocity'] != 0.0) and (time.time() - start_time < 5):
|
||||
time.sleep(0.1)
|
||||
s.poll()
|
||||
|
||||
if s.joint[0]['velocity'] != 0.0:
|
||||
print("limit switch didn't stop movement")
|
||||
sys.exit(1)
|
||||
|
||||
print("x stopped moving (pos=%.6f, vel=%.6f)" % (s.position[0], s.joint[0]['velocity']))
|
||||
print_status(s)
|
||||
|
||||
# verify that Status reflects the situation
|
||||
assert(s.joint[0]['min_soft_limit'] == False)
|
||||
assert(s.joint[0]['min_hard_limit'] == True)
|
||||
assert(s.joint[0]['max_soft_limit'] == False)
|
||||
assert(s.joint[0]['max_hard_limit'] == False)
|
||||
assert(s.joint[0]['inpos'] == True)
|
||||
assert(s.joint[0]['enabled'] == False)
|
||||
|
||||
assert(s.limit[0] == 1)
|
||||
assert(s.inpos == True)
|
||||
assert(s.enabled == False)
|
||||
|
||||
# turn the machine back on with Override Limits enabled
|
||||
c.override_limits()
|
||||
time.sleep(1)
|
||||
s.poll()
|
||||
print_status(s)
|
||||
print("command.serial: {}".format(c.serial))
|
||||
# this fails in 2.6.12 due to the stat RCS message having a status of
|
||||
# RCS_EXEC... as if though the override_limits command didn't set status
|
||||
# back to RCS_DONE when it finished.
|
||||
# assert_wait_complete(c)
|
||||
|
||||
c.state(linuxcnc.STATE_ON)
|
||||
assert_wait_complete(c)
|
||||
|
||||
# verify that Status reflects the new situation
|
||||
s.poll()
|
||||
assert(s.joint[0]['min_soft_limit'] == False)
|
||||
assert(s.joint[0]['min_hard_limit'] == True)
|
||||
assert(s.joint[0]['max_soft_limit'] == False)
|
||||
assert(s.joint[0]['max_hard_limit'] == False)
|
||||
assert(s.joint[0]['inpos'] == True)
|
||||
assert(s.joint[0]['enabled'] == True)
|
||||
|
||||
assert(s.limit[0] == 1)
|
||||
assert(s.inpos == True)
|
||||
assert(s.enabled == True)
|
||||
|
||||
# jog X in the positive direction, off the negative limit switch
|
||||
c.jog(linuxcnc.JOG_CONTINUOUS, 1, 0, 1)
|
||||
|
||||
# verify that we're starting to move
|
||||
s.poll()
|
||||
old_x = s.position[0]
|
||||
start_time = time.time()
|
||||
while (old_x == s.position[0]) and (time.time() - start_time < 5):
|
||||
time.sleep(0.1)
|
||||
s.poll()
|
||||
|
||||
if old_x == s.position[0]:
|
||||
print("no jog movement")
|
||||
sys.exit(1)
|
||||
|
||||
print("x started moving (%.6f to %.6f)" % (old_x, s.position[0]))
|
||||
print_status(s)
|
||||
|
||||
# un-trip the limit switch
|
||||
comp['x-neg-lim-sw'] = False
|
||||
|
||||
# let linuxcnc react to the limit switch untripping
|
||||
start_time = time.time()
|
||||
while (time.time() - start_time < 5):
|
||||
s.poll()
|
||||
if (s.joint[0]['min_hard_limit'] == False) and (s.limit[0] == 0):
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
||||
# verify that Status reflects the new situation
|
||||
assert(s.joint[0]['min_soft_limit'] == False)
|
||||
assert(s.joint[0]['min_hard_limit'] == False)
|
||||
assert(s.joint[0]['max_soft_limit'] == False)
|
||||
assert(s.joint[0]['max_hard_limit'] == False)
|
||||
assert(s.joint[0]['inpos'] == False)
|
||||
assert(s.joint[0]['enabled'] == True)
|
||||
|
||||
assert(s.limit[0] == 0)
|
||||
assert(s.inpos == False)
|
||||
assert(s.enabled == True)
|
||||
|
||||
# stop the jog
|
||||
c.jog(linuxcnc.JOG_STOP, 1, 0)
|
||||
|
||||
# verify that we're stopping
|
||||
s.poll()
|
||||
old_x = s.position[0]
|
||||
start_time = time.time()
|
||||
while (old_x != s.position[0]) and (time.time() - start_time < 5):
|
||||
time.sleep(0.1)
|
||||
s.poll()
|
||||
|
||||
if old_x != s.position[0]:
|
||||
print("JOG_STOP didn't stop movement")
|
||||
sys.exit(1)
|
||||
|
||||
print("x stopped moving (%.6f)" % s.position[0])
|
||||
print_status(s)
|
||||
|
||||
# verify that Status reflects the new situation
|
||||
assert(s.joint[0]['min_soft_limit'] == False)
|
||||
assert(s.joint[0]['min_hard_limit'] == False)
|
||||
assert(s.joint[0]['max_soft_limit'] == False)
|
||||
assert(s.joint[0]['max_hard_limit'] == False)
|
||||
# FIXME: another bug
|
||||
#assert(s.joint[0]['inpos'] == True)
|
||||
assert(s.joint[0]['enabled'] == True)
|
||||
|
||||
assert(s.limit[0] == 0)
|
||||
# FIXME: another bug
|
||||
#assert(s.inpos == True)
|
||||
assert(s.enabled == True)
|
||||
|
||||
# success!
|
||||
sys.exit(0)
|
||||
6
tests/hard-limits/test.sh
Executable file
6
tests/hard-limits/test.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -f rs274ngc.var rs274ngc.var.bak
|
||||
|
||||
linuxcnc -r hard-limits.ini
|
||||
|
||||
Reference in New Issue
Block a user