This file is indexed.

/usr/lib/python3/dist-packages/morse/sensors/imu.py is in python3-morse-simulator 1.4-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 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
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
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
127
128
129
130
131
132
133
134
135
136
137
138
139
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
import logging; logger = logging.getLogger("morse." + __name__)
import math
import morse.core.sensor
from morse.core import mathutils, blenderapi
from morse.helpers.components import add_data, add_property
from morse.sensors.magnetometer import MagnetoDriver
from morse.helpers.velocity import linear_velocities, angular_velocities
from copy import copy

"""
Important note:

    The 'logger.debug' instructions take some processor work, even if they are
    not displayed. For this reason, it is best to comment out these lines in
    the 'default_action' method.
"""

class IMU(morse.core.sensor.Sensor):
    """
    This sensor emulates an Inertial Measurement Unit (IMU), measuring
    the angular velocity and linear acceleration including acceleration
    due to gravity.
    For the magnetic field part, refer to the documentation of
    :doc:`./magnetometer`.

    If the robot has a physics controller, the velocities are directly
    read from it's properties ``localAngularVelocity`` and
    ``worldLinearVelocity``. Otherwise the velocities are calculated by
    simple differentiation. Linear acceleration is always computed by
    differentiation of the linear velocity. The measurements are given
    in the IMU coordinate system, so the location and rotation of the
    IMU with respect to the robot is taken into account.
    """

    _name = "Inertial measurement unit"

    add_data('angular_velocity', [0.0, 0.0, 0.0], "vec3<float>",
             'rates in IMU x, y, z axes (in radian . sec ^ -1)')
    add_data('linear_acceleration', [0.0, 0.0, 0.0], "vec3<float>",
             'acceleration in IMU x, y, z axes (in m . sec ^ -2)')
    add_data('magnetic_field', [0.0, 0.0, 0.0], "vec3<float>",
             'magnetic field along x, y, z axes (in nT)')
    add_property('_type', 'Automatic', 'ComputationMode', 'string',
                 "Kind of computation, can be one of ['Velocity', 'Position']. "
                 "Only robot with dynamic and Velocity control can choose Velocity "
                 "computation. Default choice is Velocity for robot with physics, "
                 "and Position for others")

    def __init__(self, obj, parent=None):
        """ Constructor method.

        Receives the reference to the Blender object.
        The second parameter should be the name of the object's parent.
        """
        logger.info('%s initialization' % obj.name)
        # Call the constructor of the parent class
        morse.core.sensor.Sensor.__init__(self, obj, parent)

        has_physics = bool(self.robot_parent.bge_object.getPhysicsId())
        if self._type == 'Automatic':
            if has_physics: 
                self._type = 'Velocity'
            else:
                self._type = 'Position'

        if self._type == 'Velocity' and not has_physics:
            logger.error("Invalid configuration : Velocity computation without "
                        "physics")
            return

        if self._type == 'Velocity':
            # make new references to the robot velocities and use those.
            self.robot_w = self.robot_parent.bge_object.localAngularVelocity
            self.robot_vel = self.robot_parent.bge_object.worldLinearVelocity
        else:
            self.pp = copy(self.position_3d)

        # previous linear velocity
        self.plv = mathutils.Vector((0.0, 0.0, 0.0))
        # previous angular velocity
        self.pav = mathutils.Vector((0.0, 0.0, 0.0))

        self.gravity = - blenderapi.gravity()

        # imu2body will transform a vector from imu frame to body frame
        self.imu2body = self.sensor_to_robot_position_3d()
        # rotate vector from body to imu frame
        self.rot_b2i = self.imu2body.rotation.conjugated()
        logger.debug("imu2body rotation RPY [% .3f % .3f % .3f]" % tuple(math.degrees(a) for a in self.imu2body.euler))
        logger.debug("imu2body translation [% .3f % .3f % .3f]" % tuple(self.imu2body.translation))

        if self.imu2body.translation.length > 0.01:
            self.compute_offset_acceleration = True
        else:
            self.compute_offset_acceleration = False

        # reference for rotating a vector from imu frame to world frame
        self.rot_i2w = self.bge_object.worldOrientation

        self.mag = MagnetoDriver()

        logger.info("IMU Component initialized, runs at %.2f Hz ", self.frequency)

    def sim_imu_simple(self):
        """
        Simulate angular velocity and linear acceleration measurements via simple differences.
        """
        # linear and angular velocities
        lin_vel = linear_velocities(self.pp, self.position_3d, 1 / self.frequency)
        ang_vel = angular_velocities(self.pp, self.position_3d, 1 / self.frequency)

        # linear acceleration in imu frame
        dv_imu = self.rot_i2w.transposed() * (lin_vel - self.plv) * self.frequency

        # measurement includes gravity and acceleration
        accel_meas = dv_imu + self.rot_i2w.transposed() * self.gravity

        # save current position and attitude for next step
        self.pp = copy(self.position_3d)

        # save velocity for next step
        self.plv = lin_vel
        self.pav = ang_vel

        return ang_vel, accel_meas

    def sim_imu_with_physics(self):
        """
        Simulate angular velocity and linear acceleration measurements using the physics of the robot.
        """

        # rotate the angular rates from the robot frame into the imu frame
        rates = self.rot_b2i * self.robot_w
        #logger.debug("rates in robot frame (% .4f, % .4f, % .4f)", self.robot_w[0], self.robot_w[1], self.robot_w[2])
        #logger.debug("rates in imu frame   (% .4f, % .4f, % .4f)", rates[0], rates[1], rates[2])

        # differentiate linear velocity in world (inertial) frame
        # and rotate to imu frame
        dv_imu = self.rot_i2w.transposed() * (self.robot_vel - self.plv) * self.frequency
        #logger.debug("velocity_dot in imu frame (% .4f, % .4f, % .4f)", dv_imu[0], dv_imu[1], dv_imu[2])

        # rotate acceleration due to gravity into imu frame
        g_imu = self.rot_i2w.transposed() * self.gravity

        # measurement includes gravity and acceleration
        accel_meas = dv_imu + g_imu

        if self.compute_offset_acceleration:
            # acceleration due to rotation (centripetal)
            # is zero if imu is mounted in robot center (assumed axis of rotation)
            a_centripetal = self.rot_b2i * rates.cross(rates.cross(self.imu2body.translation))
            #logger.debug("centripetal acceleration (% .4f, % .4f, % .4f)", a_rot[0], a_rot[1], a_rot[2])

            # linear acceleration due to angular acceleration
            a_alpha = self.rot_b2i * (self.robot_w - self.pav).cross(self.imu2body.translation) * self.frequency

            # final measurement includes acceleration due to rotation center not in IMU
            accel_meas += a_centripetal + a_alpha

        # save velocity for next step
        self.plv = self.robot_vel.copy()
        self.pav = self.robot_w.copy()

        return rates, accel_meas

    def default_action(self):
        """
        Get the speed and acceleration of the robot and transform it into the imu frame
        """
        if self._type == 'Velocity':
            (rates, accel) = self.sim_imu_with_physics()
        else:
            (rates, accel) = self.sim_imu_simple()

        # Store the important data
        self.local_data['angular_velocity'] = rates
        self.local_data['linear_acceleration'] = accel
        self.local_data['magnetic_field'] = self.mag.compute(self.position_3d)