From 52acb7cae2a1e5b9a602790c1ad402ccc3f057be Mon Sep 17 00:00:00 2001 From: mfbehrens99 Date: Fri, 19 Feb 2021 09:09:54 +0100 Subject: [PATCH 1/2] implemented subframes --- sailsim/simulation/Frame.py | 4 +++- sailsim/simulation/FrameList.py | 2 +- sailsim/simulation/Simulation.py | 19 ++++++++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) 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..e4d6022 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): @@ -42,13 +46,22 @@ def step(self): (windX, windY) = self.world.wind.getWindCart(boatX, boatY, time) # Get wind (forceX, forceY) = self.world.boat.resultingForce(windX, windY) + thresh = 0.01 + + force = cartToRadius(forceX, forceY) + deltav = force * self.timestep / self.world.boat.mass + self.subframe = min(4, max(0, ceil(log2(deltav / thresh)))) + subfrFactor = 1 / (2 ** self.subframe) + subfrTimestep = self.timestep * subfrFactor + # TODO delete print(force, deltav, ceil(log2(deltav / thresh)), self.subframe, sep="\t") + # Save frame self.frameList.grabFrame(self) - self.frame += 1 + self.frame += 1 / (2 ** self.subframe) # Move Boat - self.world.boat.applyForce(forceX, forceY, self.timestep) - self.world.boat.moveInterval(self.timestep) + self.world.boat.applyForce(forceX, forceY, subfrTimestep) + self.world.boat.moveInterval(subfrTimestep) def getTime(self): From 6a181ee931e84b14dcbdd7728e2afc47916650a2 Mon Sep 17 00:00:00 2001 From: mfbehrens99 Date: Fri, 19 Feb 2021 18:14:36 +0100 Subject: [PATCH 2/2] Improve subframing --- sailsim/simulation/Simulation.py | 27 +++++++++++++++++---------- tests/basictest.py | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/sailsim/simulation/Simulation.py b/sailsim/simulation/Simulation.py index e4d6022..b7c0664 100644 --- a/sailsim/simulation/Simulation.py +++ b/sailsim/simulation/Simulation.py @@ -44,24 +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 - thresh = 0.01 + # 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 - force = cartToRadius(forceX, forceY) - deltav = force * self.timestep / self.world.boat.mass - self.subframe = min(4, max(0, ceil(log2(deltav / thresh)))) subfrFactor = 1 / (2 ** self.subframe) - subfrTimestep = self.timestep * subfrFactor - # TODO delete print(force, deltav, ceil(log2(deltav / thresh)), self.subframe, sep="\t") + # print(deltav, deltav * subfrFactor, subframe, self.subframe, sep="\t") # Save frame self.frameList.grabFrame(self) - self.frame += 1 / (2 ** self.subframe) + self.frame += 1 * subfrFactor # Move Boat - self.world.boat.applyForce(forceX, forceY, subfrTimestep) - self.world.boat.moveInterval(subfrTimestep) + 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()