mirror of
https://github.com/sinseman44/PyCNC.git
synced 2026-01-11 02:30:05 +00:00
unit tests
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from __future__ import division
|
||||
import math
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class GCode(object):
|
||||
return default
|
||||
return float(self.params[argname]) * multiply
|
||||
|
||||
def getXYZ(self, default, multiply):
|
||||
def coordinates(self, default, multiply):
|
||||
""" Get X, Y and Z values as Coord object.
|
||||
:param default: Default values, if any of coords is not specified.
|
||||
:param multiply: If value exist, multiply it by this value.
|
||||
@@ -44,7 +44,7 @@ class GCode(object):
|
||||
z = self.get('Z', default.z, multiply)
|
||||
return Coordinates(x, y, z)
|
||||
|
||||
def isXYZ(self):
|
||||
def has_coordinates(self):
|
||||
""" Check if at least one of the coordinates is present.
|
||||
:return: Boolean value.
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import division
|
||||
import time
|
||||
import logging
|
||||
|
||||
@@ -69,6 +70,15 @@ class GMachine(object):
|
||||
d = Coordinates(-self._position.x, -self._position.y, 0)
|
||||
self._move(d, STEPPER_MAX_VELOCITY_MM_PER_MIN)
|
||||
|
||||
def position(self):
|
||||
""" Return current machine position (after the latest command)
|
||||
Note that hal might still be moving motors and in this case
|
||||
function will block until motors stops.
|
||||
This function for tests only.
|
||||
"""
|
||||
hal.join()
|
||||
return self._position
|
||||
|
||||
def do_command(self, gcode):
|
||||
""" Perform action.
|
||||
:param gcode: GCode object which represent one gcode line
|
||||
@@ -78,15 +88,15 @@ class GMachine(object):
|
||||
logging.debug("got command " + str(gcode.params))
|
||||
# read command
|
||||
c = gcode.command()
|
||||
if c is None and gcode.isXYZ():
|
||||
if c is None and gcode.has_coordinates():
|
||||
c = 'G1'
|
||||
# read parameters
|
||||
if self._absoluteCoordinates:
|
||||
coord = gcode.getXYZ(self._position, self._convertCoordinates)
|
||||
coord = gcode.coordinates(self._position, self._convertCoordinates)
|
||||
coord = coord + self._local
|
||||
delta = coord - self._position
|
||||
else:
|
||||
delta = gcode.getXYZ(Coordinates(0.0, 0.0, 0.0), self._convertCoordinates)
|
||||
delta = gcode.coordinates(Coordinates(0.0, 0.0, 0.0), self._convertCoordinates)
|
||||
coord = self._position + delta
|
||||
velocity = gcode.get('F', self._velocity)
|
||||
spindle_rpm = gcode.get('S', self._spindle_rpm)
|
||||
@@ -118,7 +128,7 @@ class GMachine(object):
|
||||
self._absoluteCoordinates = False
|
||||
elif c == 'G92': # switch to local coords
|
||||
self._local = self._position - \
|
||||
gcode.getXYZ(Coordinates(0.0, 0.0, 0.0), self._convertCoordinates)
|
||||
gcode.coordinates(Coordinates(0.0, 0.0, 0.0), self._convertCoordinates)
|
||||
elif c == 'M3': # spinle on
|
||||
self._spindle(spindle_rpm)
|
||||
elif c == 'M5': # spindle off
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from __future__ import division
|
||||
import logging
|
||||
import time
|
||||
|
||||
|
||||
13
runtests.sh
Executable file
13
runtests.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo '**********************************************************************'
|
||||
echo '* Testing PyCNC modules. *'
|
||||
echo '* Hint: pass -v to this script arguments to see more verbose output. *'
|
||||
echo '* Note: HAL tests should be run manually on corresponding board. For *'
|
||||
echo '* example Raspberry Pi tests is tests/rpgpio_test.sh which should be *'
|
||||
echo '* run with RPi board with connected to pin GPIO21 LED. LED should *'
|
||||
echo '* light up on pullup, set, and DMA test events. *'
|
||||
echo '**********************************************************************'
|
||||
python -m unittest discover "$@" --pattern="test_*.py"
|
||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
123
tests/test_coordinates.py
Normal file
123
tests/test_coordinates.py
Normal file
@@ -0,0 +1,123 @@
|
||||
import unittest
|
||||
|
||||
from cnc.coordinates import *
|
||||
|
||||
|
||||
class TestCoordinates(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.default = Coordinates(96, 102, 150)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_constructor(self):
|
||||
# constructor rounds values to 10 digits after the point
|
||||
self.assertRaises(TypeError, Coordinates)
|
||||
c = Coordinates(1.00000000005, 2.00000000004, -3.5000000009)
|
||||
self.assertEquals(c.x, 1.0000000001)
|
||||
self.assertEquals(c.y, 2.0)
|
||||
self.assertEquals(c.z, -3.5000000009)
|
||||
|
||||
def test_zero(self):
|
||||
c = Coordinates(0, 0, 0)
|
||||
self.assertTrue(c.is_zero())
|
||||
|
||||
def test_aabb(self):
|
||||
# aabb - Axis Aligned Bounded Box.
|
||||
# original method checks if point belongs aabb.
|
||||
p1 = Coordinates(0, 0, 0)
|
||||
p2 = Coordinates(2, 2, 2)
|
||||
c = Coordinates(1, 1, 1)
|
||||
self.assertTrue(c.is_in_aabb(p1, p2))
|
||||
self.assertTrue(c.is_in_aabb(p2, p1))
|
||||
c = Coordinates(0, 0, 0)
|
||||
self.assertTrue(c.is_in_aabb(p1, p2))
|
||||
c = Coordinates(2, 2, 2)
|
||||
self.assertTrue(c.is_in_aabb(p1, p2))
|
||||
c = Coordinates(2, 3, 2)
|
||||
self.assertFalse(c.is_in_aabb(p1, p2))
|
||||
c = Coordinates(-1, 1, 1)
|
||||
self.assertFalse(c.is_in_aabb(p1, p2))
|
||||
c = Coordinates(1, 1, 3)
|
||||
self.assertFalse(c.is_in_aabb(p1, p2))
|
||||
|
||||
def test_length(self):
|
||||
c = Coordinates(-1, 0, 0)
|
||||
self.assertEquals(c.length(), 1)
|
||||
c = Coordinates(0, 3, -4)
|
||||
self.assertEquals(c.length(), 5)
|
||||
c = Coordinates(3, 4, 12)
|
||||
self.assertEquals(c.length(), 13)
|
||||
|
||||
def test_round(self):
|
||||
# round works in another way then Python's round.
|
||||
# This round() rounds digits with specified step.
|
||||
c = Coordinates(1.5, -1.4, 3.05)
|
||||
r = c.round(1)
|
||||
self.assertEquals(r.x, 2.0)
|
||||
self.assertEquals(r.y, -1.0)
|
||||
self.assertEquals(r.z, 3.0)
|
||||
r = c.round(0.25)
|
||||
self.assertEquals(r.x, 1.5)
|
||||
self.assertEquals(r.y, -1.5)
|
||||
self.assertEquals(r.z, 3.0)
|
||||
|
||||
def test_max(self):
|
||||
self.assertEquals(self.default.find_max(), max(self.default.x,
|
||||
self.default.y,
|
||||
self.default.z))
|
||||
|
||||
# build-in function overriding tests
|
||||
def test_add(self):
|
||||
r = self.default + Coordinates(1, 2, 3)
|
||||
self.assertEquals(r.x, self.default.x + 1)
|
||||
self.assertEquals(r.y, self.default.y + 2)
|
||||
self.assertEquals(r.z, self.default.z + 3)
|
||||
|
||||
def test_sub(self):
|
||||
r = self.default - Coordinates(1, 2, 3)
|
||||
self.assertEquals(r.x, self.default.x - 1)
|
||||
self.assertEquals(r.y, self.default.y - 2)
|
||||
self.assertEquals(r.z, self.default.z - 3)
|
||||
|
||||
def test_mul(self):
|
||||
r = self.default * 2
|
||||
self.assertEquals(r.x, self.default.x * 2)
|
||||
self.assertEquals(r.y, self.default.y * 2)
|
||||
self.assertEquals(r.z, self.default.z * 2)
|
||||
|
||||
def test_div(self):
|
||||
r = self.default / 2
|
||||
self.assertEquals(r.x, self.default.x / 2)
|
||||
self.assertEquals(r.y, self.default.y / 2)
|
||||
self.assertEquals(r.z, self.default.z / 2)
|
||||
|
||||
def test_truediv(self):
|
||||
r = self.default / 3.0
|
||||
self.assertEquals(r.x, self.default.x / 3.0)
|
||||
self.assertEquals(r.y, self.default.y / 3.0)
|
||||
self.assertEquals(r.z, self.default.z / 3.0)
|
||||
|
||||
def test_eq(self):
|
||||
a = Coordinates(self.default.x, self.default.y, self.default.z)
|
||||
self.assertTrue(a == self.default)
|
||||
a = Coordinates(-self.default.x, self.default.y, self.default.z)
|
||||
self.assertFalse(a == self.default)
|
||||
a = Coordinates(self.default.x, -self.default.y, self.default.z)
|
||||
self.assertFalse(a == self.default)
|
||||
a = Coordinates(self.default.x, self.default.y, -self.default.z)
|
||||
self.assertFalse(a == self.default)
|
||||
|
||||
def test_str(self):
|
||||
self.assertTrue(isinstance(str(self.default), str))
|
||||
|
||||
def test_abs(self):
|
||||
c = Coordinates(-1, -2.5, -99)
|
||||
r = abs(c)
|
||||
self.assertEquals(r.x, 1.0)
|
||||
self.assertEquals(r.y, 2.5)
|
||||
self.assertEquals(r.z, 99.0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
114
tests/test_gcode.py
Normal file
114
tests/test_gcode.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import unittest
|
||||
|
||||
from cnc.coordinates import *
|
||||
from cnc.gcode import *
|
||||
|
||||
|
||||
class TestGCode(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.default = Coordinates(-7, 8, 9)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_constructor(self):
|
||||
# GCode shouldn't be created with constructor, but since it uses
|
||||
# internally, let's check it.
|
||||
self.assertRaises(TypeError, GCode)
|
||||
gc = GCode({"X": "1", "Y": "-2", "Z":"0", "G": "1"})
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 1.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, -2.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).z, 0.0)
|
||||
|
||||
def test_parser(self):
|
||||
gc = GCode.parse_line("G1X2Y-3Z4")
|
||||
self.assertEquals(gc.command(), "G1")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 2.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, -3.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).z, 4.0)
|
||||
gc = GCode.parse_line("")
|
||||
self.assertIsNone(gc)
|
||||
|
||||
def test_defaults(self):
|
||||
# defaults are values which should be returned if corresponding
|
||||
# value doesn't exist in gcode.
|
||||
default = Coordinates(11, -12, 14)
|
||||
gc = GCode.parse_line("G1")
|
||||
self.assertEquals(gc.coordinates(default, 1).x, 11.0)
|
||||
self.assertEquals(gc.coordinates(default, 1).y, -12.0)
|
||||
self.assertEquals(gc.coordinates(default, 1).z, 14.0)
|
||||
|
||||
def test_commands(self):
|
||||
gc = GCode({"G": "1"})
|
||||
self.assertEquals(gc.command(), "G1")
|
||||
gc = GCode.parse_line("M99")
|
||||
self.assertEquals(gc.command(), "M99")
|
||||
|
||||
def test_case_sensitivity(self):
|
||||
gc = GCode.parse_line("m111")
|
||||
self.assertEquals(gc.command(), "M111")
|
||||
gc = GCode.parse_line("g2X3y-4Z5")
|
||||
self.assertEquals(gc.command(), "G2")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 3.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, -4.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).z, 5.0)
|
||||
|
||||
def test_has_coordinates(self):
|
||||
gc = GCode.parse_line("X2Y-3Z4")
|
||||
self.assertTrue(gc.has_coordinates())
|
||||
gc = GCode.parse_line("G1")
|
||||
self.assertFalse(gc.has_coordinates())
|
||||
gc = GCode.parse_line("X1")
|
||||
self.assertTrue(gc.has_coordinates())
|
||||
gc = GCode.parse_line("Y1")
|
||||
self.assertTrue(gc.has_coordinates())
|
||||
gc = GCode.parse_line("Z1")
|
||||
self.assertTrue(gc.has_coordinates())
|
||||
|
||||
def test_multiply(self):
|
||||
# getting coordinates could modify value be specified multiplier.
|
||||
gc = GCode.parse_line("X2 Y-3 Z4")
|
||||
self.assertEquals(gc.coordinates(self.default, 25.4).x, 50.8)
|
||||
self.assertEquals(gc.coordinates(self.default, 2).y, -6)
|
||||
self.assertEquals(gc.coordinates(self.default, 0).y, 0)
|
||||
|
||||
def test_whitespaces(self):
|
||||
gc = GCode.parse_line("X1 Y2")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 1.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, 2.0)
|
||||
gc = GCode.parse_line("X 3 Y4")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 3.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, 4.0)
|
||||
gc = GCode.parse_line("X 5 Y\t 6")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 5.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, 6.0)
|
||||
gc = GCode.parse_line(" \tX\t\t \t\t7\t ")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 7.0)
|
||||
|
||||
def test_errors(self):
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "X1X1")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "X1+Y1")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "X1-Y1")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "~Y1")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "Y")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "abracadabra")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "G1M1")
|
||||
self.assertRaises(GCodeException, GCode.parse_line, "x 1 y 1 z 1 X 1")
|
||||
|
||||
def test_comments(self):
|
||||
self.assertIsNone(GCode.parse_line("; some text"))
|
||||
self.assertIsNone(GCode.parse_line(" \t \t ; some text"))
|
||||
self.assertIsNone(GCode.parse_line("(another comment)"))
|
||||
gc = GCode.parse_line("X2.5 ; end of line comment")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 2.5)
|
||||
gc = GCode.parse_line("X2 Y(inline comment)7")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 2.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, 7.0)
|
||||
gc = GCode.parse_line("X2 Y(inline comment)3 \t(one more comment) \tz4 ; multi comment test")
|
||||
self.assertEquals(gc.coordinates(self.default, 1).x, 2.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).y, 3.0)
|
||||
self.assertEquals(gc.coordinates(self.default, 1).z, 4.0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
127
tests/test_gmachine.py
Normal file
127
tests/test_gmachine.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import unittest
|
||||
import time
|
||||
|
||||
from cnc.coordinates import *
|
||||
from cnc.gcode import *
|
||||
from cnc.gmachine import *
|
||||
|
||||
|
||||
class TestGMachine(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_reset(self):
|
||||
# reset() resets all configurable from gcode things.
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("G20"))
|
||||
m.do_command(GCode.parse_line("G91"))
|
||||
m.do_command(GCode.parse_line("X1Y1Z1"))
|
||||
m.reset()
|
||||
m.do_command(GCode.parse_line("X3Y4Z5"))
|
||||
self.assertEquals(m.position(), Coordinates(3, 4, 5))
|
||||
|
||||
def test_release(self):
|
||||
# release homes head.
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("X1Y2Z3"))
|
||||
m.release()
|
||||
self.assertEquals(m.position(), Coordinates(0, 0, 0))
|
||||
|
||||
def test_home(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("X1Y2Z3"))
|
||||
m.home()
|
||||
self.assertEquals(m.position(), Coordinates(0, 0, 0))
|
||||
|
||||
def test_none(self):
|
||||
# GMachine must ignore None commands, since GCode.parse_line()
|
||||
# returns None if no gcode found in line.
|
||||
m = GMachine()
|
||||
m.do_command(None)
|
||||
self.assertEquals(m.position(), Coordinates(0, 0, 0))
|
||||
|
||||
def test_unknown(self):
|
||||
# Test commands which doesn't exists
|
||||
m = GMachine()
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G99699X1Y2Z3"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("M99699"))
|
||||
|
||||
# Test gcode commands.
|
||||
def test_g0_g1(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("G0X3Y2Z1"))
|
||||
self.assertEquals(m.position(), Coordinates(3, 2, 1))
|
||||
m.do_command(GCode.parse_line("G1X1Y2Z3"))
|
||||
self.assertEquals(m.position(), Coordinates(1, 2, 3))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G1F-1"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G1F999999"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G1X-1Y0Z0"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G1X0Y-1Z0"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G1X0Y0Z-1"))
|
||||
|
||||
def test_g4(self):
|
||||
m = GMachine()
|
||||
st = time.time()
|
||||
m.do_command(GCode.parse_line("G4P0.5"))
|
||||
self.assertLess(0.5, time.time() - st)
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("G4P-0.5"))
|
||||
|
||||
def test_g20_g21(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("G20"))
|
||||
m.do_command(GCode.parse_line("X3Y2Z1"))
|
||||
self.assertEquals(m.position(), Coordinates(76.2, 50.8, 25.4))
|
||||
m.do_command(GCode.parse_line("G21"))
|
||||
m.do_command(GCode.parse_line("X3Y2Z1"))
|
||||
self.assertEquals(m.position(), Coordinates(3, 2, 1))
|
||||
|
||||
def test_g90_g91(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("G91"))
|
||||
m.do_command(GCode.parse_line("X1Y1Z1"))
|
||||
m.do_command(GCode.parse_line("X1Y1"))
|
||||
m.do_command(GCode.parse_line("X1"))
|
||||
self.assertEquals(m.position(), Coordinates(3, 2, 1))
|
||||
m.do_command(GCode.parse_line("X-1Y-1Z-1"))
|
||||
m.do_command(GCode.parse_line("G90"))
|
||||
m.do_command(GCode.parse_line("X1Y1Z1"))
|
||||
self.assertEquals(m.position(), Coordinates(1, 1, 1))
|
||||
|
||||
def test_g90_g92(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("G92X100Y100Z100"))
|
||||
m.do_command(GCode.parse_line("X101Y102Z103"))
|
||||
self.assertEquals(m.position(), Coordinates(1, 2, 3))
|
||||
m.do_command(GCode.parse_line("G92X-1Y-1Z-1"))
|
||||
m.do_command(GCode.parse_line("X1Y1Z1"))
|
||||
self.assertEquals(m.position(), Coordinates(3, 4, 5))
|
||||
m.do_command(GCode.parse_line("G92X3Y4Z5"))
|
||||
m.do_command(GCode.parse_line("X0Y0Z0"))
|
||||
self.assertEquals(m.position(), Coordinates(0, 0, 0))
|
||||
m.do_command(GCode.parse_line("G90"))
|
||||
m.do_command(GCode.parse_line("X6Y7Z8"))
|
||||
self.assertEquals(m.position(), Coordinates(6, 7, 8))
|
||||
|
||||
def test_m3_m5(self):
|
||||
m = GMachine()
|
||||
m.do_command(GCode.parse_line("M3S" + str(SPINDLE_MAX_RPM)))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("M3S-10"))
|
||||
self.assertRaises(GMachineException,
|
||||
m.do_command, GCode.parse_line("M3S999999999"))
|
||||
m.do_command(GCode.parse_line("M5"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
117
tests/test_pulses.py
Normal file
117
tests/test_pulses.py
Normal file
@@ -0,0 +1,117 @@
|
||||
import unittest
|
||||
import time
|
||||
|
||||
from cnc.coordinates import *
|
||||
from cnc.pulses import *
|
||||
from cnc.config import *
|
||||
from cnc import hal_virtual
|
||||
|
||||
|
||||
class TestPulses(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.v = STEPPER_MAX_VELOCITY_MM_PER_MIN
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_zero(self):
|
||||
# PulseGenerator should never receive empty movement.
|
||||
self.assertRaises(ZeroDivisionError,
|
||||
PulseGeneratorLinear,
|
||||
Coordinates(0, 0, 0), self.v)
|
||||
|
||||
def test_step(self):
|
||||
# Check if PulseGenerator returns correctly single step movement.
|
||||
g = PulseGeneratorLinear(Coordinates(1.0 / STEPPER_PULSES_PER_MM, 0, 0),
|
||||
self.v)
|
||||
i = 0
|
||||
for px, py, pz in g:
|
||||
i += 1
|
||||
self.assertEquals(px, 0)
|
||||
self.assertEquals(py, None)
|
||||
self.assertEquals(pz, None)
|
||||
self.assertEquals(i, 1)
|
||||
g = PulseGeneratorLinear(Coordinates(
|
||||
1.0 / STEPPER_PULSES_PER_MM,
|
||||
1.0 / STEPPER_PULSES_PER_MM,
|
||||
1.0 / STEPPER_PULSES_PER_MM),
|
||||
self.v)
|
||||
i = 0
|
||||
for px, py, pz in g:
|
||||
i += 1
|
||||
self.assertEquals(px, 0)
|
||||
self.assertEquals(py, 0)
|
||||
self.assertEquals(pz, 0)
|
||||
self.assertEquals(i, 1)
|
||||
|
||||
def test_linear_with_hal_virtual(self):
|
||||
# Using hal_virtual module for this test, it already contains plenty
|
||||
# of asserts for wrong number of pulses, pulse timing issues etc
|
||||
hal_virtual.move_linear(Coordinates(1, 0, 0), self.v)
|
||||
hal_virtual.move_linear(Coordinates(25.4, 0, 0), self.v)
|
||||
hal_virtual.move_linear(Coordinates(25.4, 0, 0), self.v)
|
||||
hal_virtual.move_linear(Coordinates(25.4, 0, 0), self.v)
|
||||
hal_virtual.move_linear(Coordinates(TABLE_SIZE_X_MM,
|
||||
TABLE_SIZE_Y_MM,
|
||||
TABLE_SIZE_Z_MM), self.v)
|
||||
|
||||
def test_twice_faster(self):
|
||||
# Checks if one axis moves exactly twice faster, pulses are correct.
|
||||
m = Coordinates(2, 4, 0)
|
||||
g = PulseGeneratorLinear(m, self.v)
|
||||
i = 0
|
||||
for px, py, pz in g:
|
||||
if i % 2 == 0:
|
||||
self.assertNotEquals(px, None)
|
||||
else:
|
||||
self.assertEquals(px, None)
|
||||
self.assertNotEquals(py, None)
|
||||
self.assertEquals(pz, None)
|
||||
i += 1
|
||||
self.assertEquals(m.find_max() * STEPPER_PULSES_PER_MM, i)
|
||||
|
||||
def test_pulses_count_and_timings(self):
|
||||
# Check if number of pulses is equal to specified distance.
|
||||
m = Coordinates(TABLE_SIZE_X_MM, TABLE_SIZE_Y_MM, TABLE_SIZE_Z_MM)
|
||||
g = PulseGeneratorLinear(m, self.v)
|
||||
ix = 0
|
||||
iy = 0
|
||||
iz = 0
|
||||
t = -1
|
||||
for px, py, pz in g:
|
||||
if px is not None:
|
||||
ix += 1
|
||||
if py is not None:
|
||||
iy += 1
|
||||
if pz is not None:
|
||||
iz += 1
|
||||
v = list(x for x in (px, py, pz) if x is not None)
|
||||
self.assertEquals(min(v), max(v))
|
||||
self.assertLess(t, min(v))
|
||||
t = max(v)
|
||||
self.assertEquals(m.x * STEPPER_PULSES_PER_MM, ix)
|
||||
self.assertEquals(m.y * STEPPER_PULSES_PER_MM, iy)
|
||||
self.assertEquals(m.z * STEPPER_PULSES_PER_MM, iz)
|
||||
self.assertLessEqual(t, g.total_time_s())
|
||||
|
||||
def test_acceleration_velocity(self):
|
||||
# Check if acceleration present in pulses sequence and if velocity
|
||||
# is correct
|
||||
m = Coordinates(TABLE_SIZE_X_MM, 0, 0)
|
||||
g = PulseGeneratorLinear(m, self.v)
|
||||
i = 0
|
||||
lx = 0
|
||||
for px, py, pz in g:
|
||||
if i == 2:
|
||||
at = px - lx
|
||||
if i == TABLE_SIZE_X_MM * STEPPER_PULSES_PER_MM / 2:
|
||||
lt = px - lx
|
||||
bt = px - lx
|
||||
lx = px
|
||||
i += 1
|
||||
self.assertEquals(round(60.0 / lt / STEPPER_PULSES_PER_MM), round(self.v))
|
||||
self.assertGreater(at, lt)
|
||||
self.assertGreater(bt, lt)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user