diff --git a/sailsim/simulation/Frame.py b/sailsim/simulation/Frame.py index 215f861..fb7dc8c 100644 --- a/sailsim/simulation/Frame.py +++ b/sailsim/simulation/Frame.py @@ -3,6 +3,7 @@ class Frame(): def __init__(self): self.frameNr = self.time = None + self.subframe = None self.windTable = [] @@ -28,6 +29,7 @@ def __init__(self): def collectSimulation(self, simulation): self.frameNr = simulation.frame self.time = simulation.getTime() + self.subframe = simulation.subframe def collectBoat(self, boat): """Collect and save all information about the boat.""" @@ -72,7 +74,7 @@ def getWindList(self): def getCSVLine(self): """Return string that contains all data about this frame.""" data = [ - self.frameNr, self.time, + self.frameNr, self.time, self.subframe, self.boatPosX, self.boatPosY, self.boatSpeedX, self.boatSpeedY, # self.boatDirection, self.boatApparentWindX, self.boatApparentWindY, self.boatApparentWindAngle, self.boatLeewayAngle, self.boatAngleOfAttack, self.boatForceX, self.boatForceY, diff --git a/sailsim/simulation/FrameList.py b/sailsim/simulation/FrameList.py index 022e4de..a8f396d 100644 --- a/sailsim/simulation/FrameList.py +++ b/sailsim/simulation/FrameList.py @@ -33,7 +33,7 @@ def getCSV(self): def getCSVHeader(self): """Generate head of .csv file.""" headers = [ - "frame", "time", + "frame", "time", "subframe", "boatPosX", "boatPosY", "boatSpeedX", "boatSpeedY", # "boatDirection", "boatApparentWindX", "boatApparentWindY", "boatApparentWindAngle", "boatLeewayAngle", "boatAngleOfAttack", "boatForceX", "boatForceY", diff --git a/sailsim/simulation/Simulation.py b/sailsim/simulation/Simulation.py index 8e07189..b7c0664 100644 --- a/sailsim/simulation/Simulation.py +++ b/sailsim/simulation/Simulation.py @@ -1,4 +1,7 @@ from copy import deepcopy +from math import ceil, log2 + +from sailsim.utils.coordconversion import cartToRadius from sailsim.simulation.FrameList import FrameList @@ -22,6 +25,7 @@ def __init__(self, world, timestep, lastFrame=None): # Timing self.timestep = timestep self.frame = 0 + self.subframe = 0 self.lastFrame = lastFrame def run(self): @@ -40,15 +44,31 @@ def step(self): # Calculate Forces on boat (boatX, boatY) = self.world.boat.getPos() # Fetch boat position (windX, windY) = self.world.wind.getWindCart(boatX, boatY, time) # Get wind - (forceX, forceY) = self.world.boat.resultingForce(windX, windY) + (forceX, forceY) = self.world.boat.resultingForce(windX, windY) # Get resulting Force + + # Subframing + oldSubFrame = self.subframe # Save old subframe + subframeThreshold = 2 ** 4 # 1 / maxValue until new substep + deltav = cartToRadius(forceX, forceY) * self.timestep / self.world.boat.mass # calculate change of speed of boat + subframe = ceil(log2(deltav * subframeThreshold)) # calculate ideal subframe + self.subframe = min(8, max(0, subframe)) # keep subframe in interval + + # Bring frame to integer values (get all binary decimal places to 0) + if oldSubFrame > self.subframe: # Only run this part when simulation wants to run on a lower subframe value + while oldSubFrame > self.subframe and self.frame % 2**(-oldSubFrame + 1) == 0: # If ... and the oldSubFrame'th place in binary is 0 + oldSubFrame -= 1 # decrease subframe by one + self.subframe = oldSubFrame # Use calculated subframe as subframe + + subfrFactor = 1 / (2 ** self.subframe) + # print(deltav, deltav * subfrFactor, subframe, self.subframe, sep="\t") # Save frame self.frameList.grabFrame(self) - self.frame += 1 + self.frame += 1 * subfrFactor # Move Boat - self.world.boat.applyForce(forceX, forceY, self.timestep) - self.world.boat.moveInterval(self.timestep) + self.world.boat.applyForce(forceX, forceY, self.timestep * subfrFactor) + self.world.boat.moveInterval(self.timestep * subfrFactor) def getTime(self): diff --git a/tests/basictest.py b/tests/basictest.py index 5a7a9b0..63af285 100644 --- a/tests/basictest.py +++ b/tests/basictest.py @@ -24,7 +24,7 @@ # Create world and simulation w = World(b, wind, None) -s = Simulation(w, 0.01, 1024) +s = Simulation(w, .03125, 256) # Simulate 1 step s.step()