#! /usr/bin/env python
"""
This script tests some of the base functionalities of MORSE.
"""
import sys
import math
from morse.testing.testing import MorseTestCase
from pymorse import Morse
# Include this import to be able to use your test file as a regular
# builder script, ie, usable with: 'morse [run|exec] base_testing.py
try:
from morse.builder import *
except ImportError:
pass
[docs]class OdometryTest(MorseTestCase):
[docs] def setUpEnv(self):
""" Defines the test scenario, using the Builder API.
"""
robot = ATRV()
robot.translate(x = 5.0, y = 2.0)
robot.rotate(z = math.pi / 2)
pose = Pose()
robot.append(pose)
pose.add_stream('socket')
motion = MotionVW('motion')
robot.append(motion)
motion.add_stream('socket')
odo = Odometry()
robot.append(odo)
odo.level('differential')
odo.add_stream('socket')
raw_odo = Odometry()
raw_odo.level("raw")
robot.append(raw_odo)
raw_odo.add_stream('socket')
integ_odo = Odometry()
robot.append(integ_odo)
integ_odo.add_stream("socket")
env = Environment('empty', fastmode = True)
env.add_service('socket')
[docs] def clear_datas(self, x, y, yaw):
self.x = x
self.y = y
self.yaw = yaw
[docs] def record_datas(self, record):
dx = record['dx']
dy = record['dy']
self.yaw += record['dyaw']
# normalise angle
while (self.yaw > math.pi):
self.yaw+= -2 * math.pi
while (self.yaw < -math.pi):
self.yaw+= 2 * math.pi
self.x += dx
self.y += dy
[docs] def odometry_test_helper(self, morse, v, w, t):
self.odo_stream.subscribe(self.record_datas)
self.motion.publish({'v':v, 'w':w})
morse.sleep(t + 0.1)
self.odo_stream.unsubscribe(self.record_datas)
[docs] def verify(self, expected_x, expected_y, expected_yaw):
# Numerical integration is maybe not really good, so test with a
# precision of 0.16
precision = 0.16
pose = self.pose_stream.get()
integ_odo = self.integ_odo_stream.get()
self.assertAlmostEqual(self.x, expected_x, delta=precision)
self.assertAlmostEqual(self.y, expected_y, delta=precision)
self.assertAlmostEqual(self.yaw, expected_yaw, delta=precision)
self.assertAlmostEqual(pose['x'], 5.0 - expected_y, delta=precision)
self.assertAlmostEqual(pose['y'], 2.0 + expected_x, delta=precision)
self.assertAlmostEqual(pose['yaw'], expected_yaw + math.pi/2, delta=precision)
self.assertAlmostEqual(integ_odo['x'], expected_x, delta=precision)
self.assertAlmostEqual(integ_odo['y'], expected_y, delta=precision)
self.assertAlmostEqual(integ_odo['yaw'], expected_yaw, delta=precision)
self.clear_datas(expected_x, expected_y, expected_yaw)
[docs] def test_odometry(self):
""" This test is guaranteed to be started only when the simulator
is ready.
"""
with Morse() as morse:
# Read the start position, it must be (0.0, 0.0, 0.0)
self.pose_stream = morse.robot.pose
self.odo_stream = morse.robot.odo
self.integ_odo_stream = morse.robot.integ_odo
self.motion = morse.robot.motion
self.clear_datas(0.0, 0.0, 0.0)
self.odometry_test_helper(morse, 1.0, 0.0, 2.0)
self.verify(2.0, 0.0, 0.0)
self.odometry_test_helper(morse, -1.0, 0.0, 2.0)
self.verify(0.0, 0.0, 0.0)
self.odometry_test_helper(morse, 1.0, -math.pi/4.0, 2.0)
self.verify(4.0 / math.pi, -4.0/math.pi, -math.pi/2.0)
self.odometry_test_helper(morse, 0.5, -math.pi/8.0, 12.0)
self.verify(0.0, 0.0, 0.0)
# XXX fail Y with 0.11 delta
#self.odometry_test_helper(morse, -2.0, math.pi/2.0, 3.0)
#self.verify(4.0 / math.pi, -4.0/math.pi, -math.pi/2.0)
########################## Run these tests ##########################
if __name__ == "__main__":
from morse.testing.testing import main
main(OdometryTest)