package com.momega.spacesimulator.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.momega.spacesimulator.model.Maneuver;
import com.momega.spacesimulator.model.Model;
import com.momega.spacesimulator.model.Orientation;
import com.momega.spacesimulator.model.Propulsion;
import com.momega.spacesimulator.model.Spacecraft;
import com.momega.spacesimulator.model.SpacecraftSubsystem;
import com.momega.spacesimulator.model.Timestamp;
import com.momega.spacesimulator.model.Vector3d;
import com.momega.spacesimulator.utils.MathUtils;
import com.momega.spacesimulator.utils.TimeUtils;
import com.momega.spacesimulator.utils.VectorUtils;
/**
* The model of the propeller propulsion system
* Created by martin on 8/16/14.
*/
@Component
public class ThrustModel implements ForceModel {
private static final Logger logger = LoggerFactory.getLogger(ThrustModel.class);
@Autowired
private HistoryPointService historyPointService;
@Override
public Vector3d getAcceleration(Model model, Spacecraft spacecraft, double dt) {
Propulsion propulsion = findPropulsion(spacecraft);
if (propulsion == null) {
// no propulsion installed in the spacecraft
return Vector3d.ZERO;
}
Maneuver currentManeuver = spacecraft.getCurrentManeuver();
Maneuver maneuver = findManeuver(spacecraft);
if (maneuver == null) {
endOfManeuver(spacecraft, currentManeuver);
return Vector3d.ZERO;
}
double dm = propulsion.getMassFlow() * maneuver.getThrottle() * dt;
if (dm > propulsion.getFuel()) {
logger.debug("Out of fuel");
endOfManeuver(spacecraft, currentManeuver);
return Vector3d.ZERO;
}
if (currentManeuver == null) {
// start of the burn
historyPointService.startManeuver(spacecraft, maneuver);
spacecraft.setCurrentManeuver(maneuver);
}
double thrust = propulsion.getMassFlow() * maneuver.getThrottle() * propulsion.getSpecificImpulse() * MathUtils.G0;
double a = thrust / spacecraft.getMass();
if (logger.isDebugEnabled()) {
logger.debug("Engine is running, thrust = {}", thrust);
}
Orientation o = VectorUtils.rotateByAngles(spacecraft.getOrientation(), maneuver.getThrottleAlpha(), maneuver.getThrottleDelta());
Vector3d n = o.getN();
Vector3d acceleration = n.scale(a);
spacecraft.setThrust(acceleration);
// decrease the mass of the spacecraft
//TODO: place this to different method, because of Runge-Kutta method
spacecraft.setMass( spacecraft.getMass() - dm);
propulsion.setFuel( propulsion.getFuel() - dm);
if (logger.isDebugEnabled()) {
logger.debug("fuel level = {}, acc = {}", propulsion.getFuel(), acceleration);
}
return acceleration;
}
protected void endOfManeuver(Spacecraft spacecraft, Maneuver maneuver) {
if (maneuver != null) {
spacecraft.setThrust(null);
spacecraft.setCurrentManeuver(null);
historyPointService.endManeuver(spacecraft, maneuver);
}
}
protected Propulsion findPropulsion(Spacecraft spacecraft) {
for(SpacecraftSubsystem subsystem : spacecraft.getSubsystems()) {
if (subsystem instanceof Propulsion) {
return (Propulsion) subsystem;
}
}
return null;
}
protected Maneuver findManeuver(Spacecraft spacecraft) {
Timestamp timestamp = spacecraft.getTimestamp();
for(Maneuver maneuver : spacecraft.getManeuvers()) {
if (TimeUtils.isTimestampInInterval(timestamp, maneuver)) {
return maneuver;
}
}
return null;
}
}