Mechanical grid now only requires torque to accelerate
This commit is contained in:
parent
e2a1b9601a
commit
65c3661f90
|
@ -25,10 +25,16 @@ trait TNodeMechanical extends INode with IVectorWorld
|
|||
def torque: Double
|
||||
|
||||
/**
|
||||
* The mechanical load energy loss per second.
|
||||
* The mechanical resistance of this node.
|
||||
* Consider the moment of inertia, which equals mass * radius ^ 2
|
||||
*
|
||||
* Torque = Moment of Intertia * angular velocity
|
||||
*
|
||||
* A higher resistance or moment of inertia means that it is more difficult for this mechanical node to accelerate.
|
||||
*
|
||||
* @return Power loss in Watts.
|
||||
*/
|
||||
def getLoad = 10D
|
||||
def inertia = 10D
|
||||
|
||||
/**
|
||||
* The radius of rotation
|
||||
|
@ -55,5 +61,5 @@ trait TNodeMechanical extends INode with IVectorWorld
|
|||
*
|
||||
* @param torque - force at an angle
|
||||
*/
|
||||
def rotate(torque: Double, angularVelocity: Double)
|
||||
def accelerate(torque: Double)
|
||||
}
|
|
@ -32,6 +32,11 @@ object TileMotor
|
|||
val fieldStrength = 1
|
||||
val coils = 10
|
||||
val area = 1
|
||||
|
||||
/**
|
||||
* Motor constant is the product of: N (Number of coils), B (Magnetic Field Density), A (Area)
|
||||
* Or, we can call it: N * Total Flux
|
||||
*/
|
||||
val motorConstant = fieldStrength * area * coils
|
||||
}
|
||||
|
||||
|
@ -63,7 +68,19 @@ class TileMotor extends SpatialTile(Material.iron) with TIO with TElectric with
|
|||
override def start()
|
||||
{
|
||||
super.start()
|
||||
updateConnectionMask()
|
||||
updateConnections()
|
||||
}
|
||||
|
||||
def updateConnections()
|
||||
{
|
||||
electricNode.connectionMask = ForgeDirection.VALID_DIRECTIONS.filter(getIO(_) > 0).map(d => 1 << d.ordinal()).foldLeft(0)(_ | _)
|
||||
electricNode.positiveTerminals.clear()
|
||||
electricNode.negativeTerminals.clear()
|
||||
electricNode.positiveTerminals.addAll(getInputDirections())
|
||||
electricNode.negativeTerminals.addAll(getOutputDirections())
|
||||
electricNode.reconstruct()
|
||||
notifyChange()
|
||||
markUpdate()
|
||||
}
|
||||
|
||||
override def update()
|
||||
|
@ -72,9 +89,10 @@ class TileMotor extends SpatialTile(Material.iron) with TIO with TElectric with
|
|||
|
||||
/**
|
||||
* Produce torque based on current.
|
||||
* T = NBA * I / (2pi)
|
||||
*/
|
||||
val power = electricNode.power
|
||||
val torque = TileMotor.motorConstant * electricNode.current
|
||||
val torque = TileMotor.motorConstant * electricNode.current / (2 * Math.PI)
|
||||
|
||||
//TODO: Check if angular velocity should be generated based on torque
|
||||
if (torque != 0)
|
||||
|
@ -83,7 +101,11 @@ class TileMotor extends SpatialTile(Material.iron) with TIO with TElectric with
|
|||
/**
|
||||
* Motors produce emf or counter-emf by Lenz's law based on angular velocity
|
||||
* emf = change of flux/time
|
||||
* = (NBCos(x))/time
|
||||
*
|
||||
* After differentiation via chain rule:
|
||||
* emf = NBAwSin(wt)
|
||||
* emfMax = NBAw
|
||||
* where w = angular velocity
|
||||
*/
|
||||
val inducedEmf = TileMotor.motorConstant * mechNode.angularVelocity // * Math.sin(mechNode.angularVelocity * System.currentTimeMillis() / 1000d)
|
||||
electricNode.generateVoltage(inducedEmf * -1)
|
||||
|
@ -98,22 +120,10 @@ class TileMotor extends SpatialTile(Material.iron) with TIO with TElectric with
|
|||
//Auto-set opposite side for unreachable sides
|
||||
if (ioType != 0)
|
||||
super.setIO(dir.getOpposite, (ioType % 2) + 1)
|
||||
updateConnectionMask()
|
||||
updateConnections()
|
||||
}
|
||||
}
|
||||
|
||||
def updateConnectionMask()
|
||||
{
|
||||
electricNode.connectionMask = ForgeDirection.VALID_DIRECTIONS.filter(getIO(_) > 0).map(d => 1 << d.ordinal()).foldLeft(0)(_ | _)
|
||||
electricNode.positiveTerminals.clear()
|
||||
electricNode.negativeTerminals.clear()
|
||||
electricNode.positiveTerminals.addAll(getInputDirections())
|
||||
electricNode.negativeTerminals.addAll(getOutputDirections())
|
||||
electricNode.reconstruct()
|
||||
notifyChange()
|
||||
markUpdate()
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def renderDynamic(pos: Vector3, frame: Float, pass: Int): Unit =
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ class NodeGear(parent: PartGear) extends NodeMechanical(parent: PartGear)
|
|||
{
|
||||
override def angleDisplacement = if (gear.getMultiBlock.isConstructed) Math.PI / 36 else Math.PI / 12
|
||||
|
||||
override def getLoad: Double =
|
||||
override def inertia: Double =
|
||||
{
|
||||
return gear.tier match
|
||||
{
|
||||
|
|
|
@ -10,7 +10,7 @@ import resonant.lib.wrapper.ForgeDirectionWrapper._
|
|||
|
||||
class NodeGearShaft(parent: PartGearShaft) extends NodeMechanical(parent)
|
||||
{
|
||||
override def getLoad: Double =
|
||||
override def inertia: Double =
|
||||
{
|
||||
return shaft.tier match
|
||||
{
|
||||
|
|
|
@ -11,11 +11,6 @@ import scala.collection.convert.wrapAll._
|
|||
*/
|
||||
class GridMechanical extends GridNode[NodeMechanical] with IUpdate
|
||||
{
|
||||
/**
|
||||
* The energy loss of this grid
|
||||
*/
|
||||
private var load = 0D
|
||||
|
||||
/**
|
||||
* Determines if this grid is locked (invalid opposite gear connections)
|
||||
*/
|
||||
|
@ -48,24 +43,26 @@ class GridMechanical extends GridNode[NodeMechanical] with IUpdate
|
|||
{
|
||||
nodes synchronized
|
||||
{
|
||||
load = 0
|
||||
|
||||
/**
|
||||
* Consider this as the moment of inertia: how difficult it is to spin this object.
|
||||
*/
|
||||
nodes.foreach(
|
||||
n =>
|
||||
{
|
||||
n.torque = 0
|
||||
n.angularVelocity = 0
|
||||
load += n.getLoad
|
||||
// n.angularVelocity = 0
|
||||
}
|
||||
)
|
||||
|
||||
//TODO: Add deceleration
|
||||
|
||||
if (!isLocked)
|
||||
{
|
||||
getNodes.filter(n => n.bufferTorque != 0 && n.bufferAngularVelocity != 0).foreach(
|
||||
getNodes.filter(n => n.bufferTorque != 0).foreach(
|
||||
n =>
|
||||
{
|
||||
allPassed = Seq(n)
|
||||
recurse(Seq(n), deltaTime, n.bufferTorque, n.bufferAngularVelocity)
|
||||
recurse(Seq(n), deltaTime, n.bufferTorque, 0)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -94,11 +91,22 @@ class GridMechanical extends GridNode[NodeMechanical] with IUpdate
|
|||
}
|
||||
|
||||
n.bufferTorque = 0
|
||||
n.bufferAngularVelocity = 0
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
def calculateEquivalentInertia(passed: Seq[NodeMechanical]): Double =
|
||||
{
|
||||
val curr = passed.last
|
||||
/**
|
||||
* I1 + n^2 * I
|
||||
* where n is the acceleration ratio
|
||||
*/
|
||||
var inertia = curr.inertia
|
||||
inertia += curr.connections.map(c => c.radius(curr) / curr.radius(c) * calculateEquivalentInertia(passed :+ c)).foldLeft(0d)(_ + _)
|
||||
return inertia
|
||||
}
|
||||
|
||||
def recurse(passed: Seq[NodeMechanical], deltaTime: Double, torque: Double, angularVelocity: Double)
|
||||
{
|
||||
val curr = passed.last
|
||||
|
@ -138,19 +146,24 @@ class GridMechanical extends GridNode[NodeMechanical] with IUpdate
|
|||
}
|
||||
else
|
||||
{
|
||||
//This is the first node.
|
||||
//Calculate energy loss
|
||||
val power = torque * angularVelocity
|
||||
val netEnergy = Math.max(power - load * deltaTime, 0)
|
||||
val netTorque = netEnergy * (torque / power)
|
||||
val netVelocity = netEnergy * (angularVelocity / power)
|
||||
/**
|
||||
* This is the first node.
|
||||
* 1. Calculate equivalent moment of inertia of the mechanical system.
|
||||
* 2. Determine the angular acceleration:
|
||||
* T = I * a
|
||||
* a = T/I
|
||||
* where I = inertia and a = angular acceleration
|
||||
*/
|
||||
val inertia = calculateEquivalentInertia(passed)
|
||||
val netTorque = torque
|
||||
val netAcceleration = torque / inertia
|
||||
|
||||
curr.torque += netTorque
|
||||
curr.angularVelocity += netVelocity * deltaTime
|
||||
curr.angularVelocity += netAcceleration * deltaTime
|
||||
curr.connections.foreach(c =>
|
||||
{
|
||||
allPassed :+= c
|
||||
recurse(passed :+ c, deltaTime, netTorque, netVelocity)
|
||||
recurse(passed :+ c, deltaTime, netTorque, netAcceleration)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ class NodeMechanical(parent: INodeProvider) extends NodeGrid[NodeMechanical](par
|
|||
* Buffer values used by the grid to transfer mechanical energy.
|
||||
*/
|
||||
protected[grid] var bufferTorque = 0D
|
||||
protected[grid] var bufferAngularVelocity = 0D
|
||||
private var _torque = 0D
|
||||
private var _angularVelocity = 0D
|
||||
|
||||
|
@ -80,22 +79,14 @@ class NodeMechanical(parent: INodeProvider) extends NodeGrid[NodeMechanical](par
|
|||
*/
|
||||
def angleDisplacement = 0D
|
||||
|
||||
override def rotate(torque: Double, angularVelocity: Double)
|
||||
override def accelerate(torque: Double)
|
||||
{
|
||||
bufferTorque += torque
|
||||
bufferAngularVelocity += angularVelocity
|
||||
}
|
||||
|
||||
def power: Double = torque * angularVelocity
|
||||
|
||||
/**
|
||||
* Gets the torque of the mechanical device from a specific side
|
||||
*
|
||||
* @return force
|
||||
*/
|
||||
override def torque = _torque
|
||||
|
||||
def torque_=(newTorque: Double) = _torque = newTorque
|
||||
override def radius(other: TNodeMechanical) = 0.5
|
||||
|
||||
def getMechanicalGrid: GridMechanical = super.grid.asInstanceOf[GridMechanical]
|
||||
|
||||
|
@ -107,6 +98,15 @@ class NodeMechanical(parent: INodeProvider) extends NodeGrid[NodeMechanical](par
|
|||
|
||||
override def toString = "NodeMechanical [" + connections.size() + " Torque: " + BigDecimal(torque).setScale(2, BigDecimal.RoundingMode.HALF_UP) + " Velocity: " + BigDecimal(angularVelocity).setScale(2, BigDecimal.RoundingMode.HALF_UP) + "]"
|
||||
|
||||
/**
|
||||
* Gets the torque of the mechanical device from a specific side
|
||||
*
|
||||
* @return force
|
||||
*/
|
||||
override def torque = _torque
|
||||
|
||||
def torque_=(newTorque: Double) = _torque = newTorque
|
||||
|
||||
/**
|
||||
* The class used to compare when making connections
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,7 @@ import net.minecraftforge.common.util.ForgeDirection
|
|||
*/
|
||||
class NodeGrinder(parent: TileGrindingWheel) extends NodeMechanical(parent: TileGrindingWheel)
|
||||
{
|
||||
override def getLoad = 1000d * Math.abs(angularVelocity)
|
||||
override def inertia = 1000d * Math.abs(angularVelocity)
|
||||
|
||||
override def canConnect[B <: NodeMechanical](other: B, from: ForgeDirection): Boolean = parent.getDirection == from || parent.getDirection.getOpposite == from
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class NodeTurbine(parent: TileTurbine) extends NodeMechanical(parent)
|
|||
* The mechanical load
|
||||
* @return Torque in Newton meters per second
|
||||
*/
|
||||
override def getLoad = 100 * parent.multiBlockRadius * parent.multiBlockRadius
|
||||
override def inertia = 100 * parent.multiBlockRadius * parent.multiBlockRadius
|
||||
|
||||
/**
|
||||
* Moment of inertia = m * r * r
|
||||
|
|
Loading…
Reference in New Issue