2012-11-27 09:07:15 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
'''
|
|
|
|
simple rover simulator core
|
|
|
|
'''
|
|
|
|
|
|
|
|
from aircraft import Aircraft
|
|
|
|
import util, time, math
|
|
|
|
from math import degrees, radians
|
|
|
|
from rotmat import Vector3, Matrix3
|
|
|
|
|
|
|
|
class Rover(Aircraft):
|
|
|
|
'''a simple rover'''
|
|
|
|
def __init__(self,
|
|
|
|
max_speed=10,
|
|
|
|
max_accel=10,
|
2013-03-14 19:52:32 -03:00
|
|
|
max_turn_rate=45,
|
|
|
|
skid_steering=False):
|
2012-11-27 09:07:15 -04:00
|
|
|
Aircraft.__init__(self)
|
|
|
|
self.max_speed = max_speed
|
|
|
|
self.max_accel = max_accel
|
|
|
|
self.max_turn_rate = max_turn_rate
|
|
|
|
self.last_time = time.time()
|
2013-03-14 19:52:32 -03:00
|
|
|
self.skid_steering = skid_steering
|
2012-11-27 09:07:15 -04:00
|
|
|
|
|
|
|
def update(self, state):
|
2013-03-14 19:52:32 -03:00
|
|
|
|
|
|
|
# if in skid steering mode the steering and throttle values are used for motor1 and motor2
|
|
|
|
if self.skid_steering:
|
2013-03-14 21:05:03 -03:00
|
|
|
motor1 = state.steering # left motor
|
|
|
|
motor2 = state.throttle # right motor
|
|
|
|
steering = motor1 - motor2
|
2013-03-14 19:52:32 -03:00
|
|
|
throttle = 0.5*(motor1 + motor2)
|
|
|
|
else:
|
|
|
|
steering = state.steering
|
|
|
|
throttle = state.throttle
|
|
|
|
|
2012-11-27 09:07:15 -04:00
|
|
|
# how much time has passed?
|
|
|
|
t = time.time()
|
|
|
|
delta_time = t - self.last_time
|
|
|
|
self.last_time = t
|
|
|
|
|
|
|
|
# speed in m/s in body frame
|
|
|
|
velocity_body = self.dcm.transposed() * self.velocity
|
|
|
|
|
|
|
|
# speed along x axis, +ve is forward
|
|
|
|
speed = velocity_body.x
|
|
|
|
|
|
|
|
# yaw rate in degrees/s
|
2013-03-14 19:52:32 -03:00
|
|
|
yaw_rate = self.max_turn_rate * steering * (speed / self.max_speed)
|
2012-11-27 09:07:15 -04:00
|
|
|
|
|
|
|
# target speed with current throttle
|
2013-03-14 19:52:32 -03:00
|
|
|
target_speed = throttle * self.max_speed
|
2012-11-27 09:07:15 -04:00
|
|
|
|
|
|
|
# linear acceleration in m/s/s - very crude model
|
|
|
|
accel = self.max_accel * (target_speed - speed) / self.max_speed
|
|
|
|
|
|
|
|
# print('speed=%f throttle=%f steering=%f yaw_rate=%f accel=%f' % (speed, state.throttle, state.steering, yaw_rate, accel))
|
|
|
|
|
|
|
|
self.gyro = Vector3(0,0,radians(yaw_rate))
|
|
|
|
|
|
|
|
# update attitude
|
|
|
|
self.dcm.rotate(self.gyro * delta_time)
|
|
|
|
self.dcm.normalize()
|
|
|
|
|
|
|
|
# accel in body frame due to motor
|
|
|
|
accel_body = Vector3(accel, 0, 0)
|
|
|
|
|
|
|
|
# add in accel due to direction change
|
|
|
|
accel_body.y += radians(yaw_rate) * speed
|
|
|
|
|
|
|
|
# now in earth frame
|
|
|
|
accel_earth = self.dcm * accel_body
|
|
|
|
accel_earth += Vector3(0, 0, self.gravity)
|
|
|
|
|
|
|
|
# if we're on the ground, then our vertical acceleration is limited
|
|
|
|
# to zero. This effectively adds the force of the ground on the aircraft
|
|
|
|
accel_earth.z = 0
|
|
|
|
|
|
|
|
# work out acceleration as seen by the accelerometers. It sees the kinematic
|
|
|
|
# acceleration (ie. real movement), plus gravity
|
|
|
|
self.accel_body = self.dcm.transposed() * (accel_earth + Vector3(0, 0, -self.gravity))
|
|
|
|
|
|
|
|
# new velocity vector
|
|
|
|
self.velocity += accel_earth * delta_time
|
|
|
|
|
|
|
|
# new position vector
|
|
|
|
old_position = self.position.copy()
|
|
|
|
self.position += self.velocity * delta_time
|
|
|
|
|
|
|
|
# update lat/lon/altitude
|
|
|
|
self.update_position(delta_time)
|
2013-03-14 19:52:32 -03:00
|
|
|
|