TestIcePAPTraj.py 10.9 KB
Newer Older
1 2 3 4 5 6 7
# -*- coding: utf-8 -*-
#
# This file is part of the bliss project
#
# Copyright (c) 2016 Beamline Control Unit, ESRF
# Distributed under the GNU LGPLv3. See LICENSE for more info.

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
import unittest
import sys
import os
import optparse
import re
import signal
import gevent
import pdb


"""
Bliss generic library
"""
sys.path.insert(
    0,
    os.path.abspath(
24 25 26
        os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)
    ),
)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

import bliss


"""
IcePAP specific library
"""
"""
sys.path.insert(
    0,
    os.path.abspath("/segfs/bliss/source/hardware/IcePAP/client/python/"))
"""


"""
Example of Bliss configuration
"""
config_xml = """
<config>
    <controller class="IcePAP" name="test">
        <host value="%s"/>
        <libdebug value="1"/>
        <axis name="mymot">
            <address        value="%s"/>
            <steps_per_unit value="200"/>
            <backlash       value="0.01"/>
            <velocity       value="20"/>  // unit is mm/sec
            <accleration    value="80"/>  // unit is mm/sec2
            <encoder_steps_per_unit value="1000"/>
        </axis>
        <axis name="mymot2">
            <address        value="%s"/>
            <steps_per_unit value="200"/>
            <backlash       value="0.01"/>
            <velocity       value="20"/>   // unit is mm/sec
            <acceleration   value="80"/>   // unit is mm/sec2
        </axis>
    </controller>

    <controller class="IcePAPTraj" name="mytraj">
        <axis name="mypar">
            <axislist       value="mymot mymot2"/>
            <velocity       value="1"/>    // unit is par/sec
        </axis>
    </controller>
</config>
"""


"""
77
            <acceleration   value="4"/>    // unit is par/sec2
78 79 80
Global resources, yes, I know it's bad
"""
hostname = ""
81
address = ""
82 83 84 85 86 87
address2 = ""

"""
"""


88
# def signal_handler(signal, frame):
89 90 91 92 93
def signal_handler(*args):
    print "\nAbort request taken into account\n"
    finalize()

    # needed to stop unittest sequence of tests
94
    # raise KeyboardInterrupt()
95 96 97 98


def finalize():
    mymot = bliss.get_axis("mymot")
99
    # mymot.controller.log_level(bliss.common.log.INFO)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    # needed to stop threads of Deep module
    mymot.controller.finalize()


"""
UnitTest list of tests
"""


class TestIcePAPController(unittest.TestCase):
    global hostname
    global address
    global address2

    # called for each test
    def setUp(self):
        bliss.load_cfg_fromstring(config_xml % (hostname, address, address2))

    # called at the end of each individual test
    def tearDown(self):
        pass

    # as the test are ordered, this method will be executed first
    def test_hardware_axes_preparation(self):

        # If motors are moving, the power can not be switched on
        # therefore hide exception
127
        mymot = bliss.get_axis("mymot")
128
        mymot2 = bliss.get_axis("mymot2")
129
        # mymot.controller.log_level(bliss.common.log.INFO)
130 131
        mymot.controller.stop(mymot)
        mymot2.controller.stop(mymot2)
132
        # mymot.controller.log_level(bliss.common.log.ERROR)
133 134 135 136

        # NOTE MP: 2015Mar17: the current eMotion doesn't call the
        # controller stop() if it doesn't know that a motion is taking
        # place on the hardware. Therefore bypass eMotion
137
        while mymot.state() == "MOVING":
138
            gevent.sleep(0.1)
139
        while mymot2.state() == "MOVING":
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
            gevent.sleep(0.1)

        # the IcePAP will move, therefore put it close to the
        # target position to avoid long wait
        mymot.dial(0)
        mymot.position(0)
        mymot2.dial(0)
        mymot2.position(0)

    def test_axis_creation(self):
        mypar = bliss.get_axis("mypar")
        self.assertTrue(mypar)

    def test_set_parameter(self):
        mypar = bliss.get_axis("mypar")
        par_list = range(100)
        mypar.set_parameter(par_list)
        self.assertEqual(mypar.get_parameter(), par_list)

    def test_drain_trajectory(self):
        mypar = bliss.get_axis("mypar")
        par_list = range(100)
        mypar.set_parameter(par_list)
        mypar.drain()
        self.assertEqual(len(mypar.get_parameter()), 0)

    def test_set_parameter_nonempty(self):
        mypar = bliss.get_axis("mypar")
        par_list = range(100)
        mypar.set_parameter(par_list)
        self.assertRaises(ValueError, mypar.set_parameter, par_list)

    def test_set_trajectory(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)

    def test_set_trajectory_wrongrange(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(10)
        mypar.set_parameter(par_list)
        self.assertRaises(ValueError, mypar.set_trajectory, mymot, pos_list)

    def test_set_trajectory_overwrite(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        self.assertRaises(ValueError, mypar.set_trajectory, mymot, pos_list)
196

197 198 199 200
    def test_load_trajectory(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
201
        pos_list = [x * 10 for x in range(100)]
202 203 204 205 206
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        mypar.load()

    def test_load_multi_axes_trajectory(self):
207 208
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
209 210 211 212 213
        mymot2 = bliss.get_axis("mymot2")

        par_list = range(100)
        mypar.set_parameter(par_list)

214 215 216
        pos_list = [x * 10 for x in range(100)]
        mypar.set_trajectory(mymot, pos_list)
        pos_list = [x * 20 for x in range(100)]
217 218 219 220 221
        mypar.set_trajectory(mymot2, pos_list)

        mypar.load()

    def test_put_all_axes_on_trajectory(self):
222 223
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
224 225 226 227 228
        mymot2 = bliss.get_axis("mymot2")

        par_list = range(100)
        mypar.set_parameter(par_list)

229 230 231
        pos_list = [x * 1.5 for x in range(100)]
        mypar.set_trajectory(mymot, pos_list)
        pos_list2 = [x * 2 for x in range(100)]
232 233 234 235 236 237 238
        mypar.set_trajectory(mymot2, pos_list2)

        mypar.load()

        # IcePAP motors will move, blocking call
        mypar.sync(1)

239
        self.assertEqual(mymot.position(), pos_list[1])
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
        self.assertEqual(mymot2.position(), pos_list2[1])

    def test_get_parameter_velocity_empty(self):
        mypar = bliss.get_axis("mypar")
        vel = mypar.velocity()

    def test_get_parameter_velocity(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        mypar.load()

        vel = mypar.velocity()

    def test_set_parameter_velocity_empty(self):
        mypar = bliss.get_axis("mypar")
        vel = 1
        self.assertEqual(mypar.velocity(vel), vel)

    def test_set_parameter_velocity(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        mypar.load()

        vel = 1
        self.assertEqual(mypar.velocity(vel), vel)

    def test_get_parameter_acctime_empty(self):
        mypar = bliss.get_axis("mypar")
276
        vel = mypar.acctime()
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306

    def test_get_parameter_acctime(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        mypar.load()

        acc = mypar.acctime()

    def test_set_parameter_acctime_empty(self):
        mypar = bliss.get_axis("mypar")
        acc = 0.250
        self.assertEqual(mypar.acctime(acc), acc)

    def test_set_parameter_acctime(self):
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
        par_list = range(100)
        pos_list = range(100)
        mypar.set_parameter(par_list)
        mypar.set_trajectory(mymot, pos_list)
        mypar.load()

        acc = 0.250
        self.assertEqual(mypar.acctime(acc), acc)

    def test_move_all_axes_on_trajectory(self):
307 308
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
309 310 311 312 313
        mymot2 = bliss.get_axis("mymot2")

        par_list = range(100)
        mypar.set_parameter(par_list)

314 315 316
        pos_list = [x * 1.5 for x in range(100)]
        mypar.set_trajectory(mymot, pos_list)
        pos_list2 = [x * 2 for x in range(100)]
317 318 319 320 321 322 323 324
        mypar.set_trajectory(mymot2, pos_list2)

        mypar.load()
        mypar.sync(1)

        # IcePAP motors will move, blocking call
        mypar.move(2)

325
        self.assertEqual(mymot.position(), pos_list[2])
326 327 328
        self.assertEqual(mymot2.position(), pos_list2[2])

    def test_stop_move(self):
329 330
        mypar = bliss.get_axis("mypar")
        mymot = bliss.get_axis("mymot")
331 332 333 334 335
        mymot2 = bliss.get_axis("mymot2")

        par_list = range(100)
        mypar.set_parameter(par_list)

336 337 338
        pos_list = [x * 1.5 for x in range(100)]
        mypar.set_trajectory(mymot, pos_list)
        pos_list2 = [x * 2 for x in range(100)]
339 340 341 342 343 344 345 346 347 348 349 350
        mypar.set_trajectory(mymot2, pos_list2)

        mypar.load()
        mypar.sync(1)

        mypar.move(2, wait=False)
        mypar.stop()


"""
Main entry point
"""
351
if __name__ == "__main__":
352 353

    # Get arguments
354
    usage = "Usage  : %prog hostname motor_address motor_address\n"
355 356 357 358 359 360 361 362 363 364 365 366
    usage += "Example: python %prog iceeu2 2 3"
    parser = optparse.OptionParser(usage)
    argv = sys.argv
    (settings, args) = parser.parse_args(argv)

    # Minimum check on arguements
    if len(args) <= 3:
        parser.error("Missing mandatory IcePAP hostname and motor address")
        sys.exit(-1)

    # Mandatory argument is the IcePAP hostname
    hostname = args[1]
367
    address = args[2]
368 369 370 371 372 373 374 375 376
    address2 = args[3]

    # Avoid interaction of our arguments with unittest class
    del sys.argv[1:]

    # Intercept the <ctrl-c> to get out of infinite loops
    gevent.signal(signal.SIGINT, signal_handler)

    # Launch the tests sequence
377
    print '\nTesting IcePAP control on system "%s"\n' % hostname
378 379 380 381
    print "\n".rjust(70, "-")

    # Change the default unittest test sequence order from cmp() to line number
    loader = unittest.TestLoader()
382
    ln = lambda f: getattr(TestIcePAPController, f).im_func.func_code.co_firstlineno
383 384 385 386
    lncmp = lambda a, b: cmp(ln(a), ln(b))
    loader.sortTestMethodsUsing = lncmp

    # NOTE: unittest.main(verbosity=2) not supported under Python 2.6
387
    suite = loader.loadTestsFromTestCase(TestIcePAPController)
388 389 390 391
    unittest.TextTestRunner(verbosity=3).run(suite)

    # normal end
    finalize()