physics-simulations

A collection of physics simulations
git clone https://git.ashermorgan.net/physics-simulations/
Log | Files | Refs | README

commit 864a1f61ba8051553fe9d713dafb9ae107aa6369
parent 3e21420a4692d91c2adf0543e14dc3cd53a33efe
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Mon,  8 Mar 2021 08:56:18 -0800

Implement friction in horizontal motion simulation

Diffstat:
Msimulations/horizontal-motion.html | 18+++++++++++++-----
Msimulations/horizontal-motion.js | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 78 insertions(+), 17 deletions(-)

diff --git a/simulations/horizontal-motion.html b/simulations/horizontal-motion.html @@ -25,15 +25,23 @@ <div id="input" hidden> <section> <label for="massInput"><b>Mass:</b> {{ mass.toFixed(1) }} Kg</label> - <input type="range" min="1" max="10" step="0.1" v-model.number="mass" @input="reset" @dblclick="mass=5" :disabled="active" id="massInput"> + <input type="range" min="1" max="10" step="0.1" v-model.number="mass" @dblclick="mass=5" id="massInput"> </section> <section> - <label for="initialVelocityInput"><b>Initial Velocity:</b> {{ initialVelocity.toFixed(1) }} m/s</label> - <input type="range" min="-10" max="10" step="0.1" v-model.number="initialVelocity" @input="reset" @dblclick="initialVelocity=1" :disabled="active" id="initialVelocityInput"> + <label for="forceInput"><b>Applied Force:</b> {{ force.toFixed(1) }} N</label> + <input type="range" min="-10" max="10" step="0.1" v-model.number="force" @dblclick="force=0" id="forceInput"> </section> <section> - <label for="forceInput"><b>Applied Force:</b> {{ force.toFixed(1) }} N</label> - <input type="range" min="-10" max="10" step="0.1" v-model.number="force" @input="reset" @dblclick="force=0" :disabled="active" id="forceInput"> + <label for="staticFrictionInput"><b>Static Friction:</b> {{ staticFriction.toFixed(2) }}</label> + <input type="range" min="0" max="1" step="0.01" v-model.number="staticFriction" @dblclick="staticFriction=0" id="staticFrictionInput"> + </section> + <section> + <label for="kineticFrictionInput"><b>Kinetic Friction:</b> {{ kineticFriction.toFixed(2) }}</label> + <input type="range" min="0" max="1" step="0.01" v-model.number="kineticFriction" @dblclick="kineticFriction=0" id="kineticFrictionInput"> + </section> + <section> + <label for="gravityInput"><b>Gravity:</b> {{ gravity.toFixed(1) }} m/s<sup>2</sup></label> + <input type="range" min="0" max="10" step="0.1" v-model.number="gravity" @dblclick="gravity=9.8" id="gravityInput"> </section> </div> diff --git a/simulations/horizontal-motion.js b/simulations/horizontal-motion.js @@ -1,10 +1,19 @@ const App = { data: function() { return { + // Input data mass: 5, // The object's mass (Kg) - initialVelocity: 1, // The object's initial velocity (m/s) - force: 0, // The force acting on the object (N) + force: 5, // The force acting on the object (N) + staticFriction: 0, // The coefficient of static friction + kineticFriction: 0, // The coefficient of kinetic friction + gravity: 9.8, // The acceleration due to gravity (m/s/s) + + // Output data time: 0, // The time (s) + position: 0, // The object's current position (m) + velocity: 0, // The object's current velocity (m/s) + + // Simulation properties active: false, // Whether the simulation is active refreshRate: 0.01, // The simulation refresh rate (s) intervalId: null, // The value returned by setInterval @@ -12,24 +21,44 @@ const App = { }, computed: { /** - * The acceleration of the object + * The force of static friction when the object is at rest */ - acceleration: function() { - return this.force / this.mass; + staticFrictionForce: function() { + let maxForce = this.staticFriction * this.mass * this.gravity; + if (Math.abs(this.force) <= maxForce) return -1 * this.force; + else return Math.sign(this.force) * -1 * maxForce; }, /** - * The velocity of the object + * The force of kinetic friction when the object is in motion */ - velocity: function() { - return this.initialVelocity + (this.acceleration * this.time); + kineticFrictionForce: function() { + let value = this.kineticFriction * this.mass * this.gravity; + if (this.velocity > 0) return -1 * value; + else if (this.velocity < 0) return value; + else if (this.force > 0) return -1 * value; + else if (this.force < 0) return value; + else return 0; }, /** - * The position of the object + * The net force on the object */ - position: function() { - return (this.initialVelocity * this.time) + (0.5 * this.acceleration * this.time * this.time); + netForce: function() { + if (this.velocity === 0 && (Math.abs(this.staticFrictionForce) >= Math.abs(this.force) || Math.abs(this.kineticFrictionForce) >= Math.abs(this.force))) { + // The object is at rest and cannot overcome friction + return 0; + } + else { + return this.force + this.kineticFrictionForce; + } + }, + + /** + * The acceleration of the object + */ + acceleration: function() { + return this.netForce / this.mass; }, /** @@ -57,13 +86,37 @@ const App = { */ reset: function() { this.time = 0; + this.position = 0; + this.velocity = 0; }, /** - * Update the simulation output + * Update the simulation */ update: function() { + // Update time this.time += this.refreshRate; + + // Get updated velocity + let newVelocity = this.velocity + (this.acceleration * this.refreshRate) + + // Correct velocity for friction + if (Math.sign(this.velocity) !== Math.sign(newVelocity)) { + // The object was recently at rest + this.velocity = 0; + + if (this.acceleration !== 0) { + // The object was able to overcome friction + this.velocity = newVelocity; + } + } + else { + // The object was not recently at rest + this.velocity = newVelocity; + } + + // Update position + this.position += (this.velocity * this.refreshRate); }, }, }