initial commit
This commit is contained in:
3
config.lua
Normal file
3
config.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
return {
|
||||
thrusterConfigPath = "/config/thrusters.lua"
|
||||
}
|
||||
202
docs.md
Normal file
202
docs.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Implementation Docs
|
||||
|
||||
## Redstone Mode
|
||||
|
||||
Total redstone inputs: 22
|
||||
8x tilt signals
|
||||
6x accelerometer signals
|
||||
4x direction signals
|
||||
1x altitude signal
|
||||
1x downwards thrust signal
|
||||
1x fore thrust signal
|
||||
1x aft thrust signal
|
||||
|
||||
Total required redstone outputs: at least 8
|
||||
4x for four large thrusters
|
||||
8x for at least eight small attitude thrusters (4x lateral, 4x pitch/roll)
|
||||
|
||||
## Required functionality
|
||||
|
||||
- Achieve target angles for tilt values (target is 0)
|
||||
- Achieve target values for lateral velocity (when no thrust is being applied, 0)
|
||||
- Achieve target values for for/aft velocity when thrust is applied
|
||||
- When direction indicators are referenced and autopilot is on, keep all direction indicator values beside "fore" at 0
|
||||
- A monitor that displays the following values:
|
||||
- Directional thrust values (0-15 & 0-100%)
|
||||
- Rotational thrust values (0-15 & 0-100%)
|
||||
- Velocity values
|
||||
- Altitude values
|
||||
- Navigation target values (if applicable)
|
||||
- Autopilot controls
|
||||
|
||||
## Create: Avionics relevant Peripheral methods
|
||||
|
||||
When Create: Avionics is installed, all sensors get direct peripherals for CC:T
|
||||
|
||||
Relevant peripherals:
|
||||
|
||||
- Velocity Sensor
|
||||
- Navigation Table
|
||||
- Gimbal Sensor
|
||||
- Altitude Sensor
|
||||
- Analog Transmission
|
||||
|
||||
### Altitude Sensor implementations
|
||||
|
||||
> Peripheral ID: altitude_sensor
|
||||
|
||||
- `getHeight()`: get the sensor's Y coordinate
|
||||
- `getAirPressure()`: get the local air pressure at the sensor's altitude
|
||||
- `getVerticalSpeed()`: get the sensor's vertical speed (positive is ascending, negative is descending)
|
||||
|
||||
### Navigation Table implementations
|
||||
|
||||
> Peripheral ID: navigation_table
|
||||
|
||||
- `hasTarget()`: Check whether the table has resolved a target
|
||||
- `getTargetType()`: returns a string target type ID, or nil if no item is held
|
||||
|
||||
- `getTargetMetadata()`: returns per-type metadata for the target.
|
||||
|
||||
> Metadata schema:
|
||||
>
|
||||
> - `simulated:compass`: `kind` ("lodestone"|"spawn"), `sublevel_id` (string, lodestone only)
|
||||
> - `sublevel_id` is the tracker UUID
|
||||
> - `simulated:recovery_compass`: `placer_uuid` (string, optional)
|
||||
> - `placer_uuid` is absent until a player has placed the compass into the table
|
||||
> - `simulated:map`: `map_id` (number, optional)
|
||||
> - `map_id` is absent if the held map carries no MAP_ID data component (e.g. a blank map)
|
||||
> - `simulated:magnet`: ---
|
||||
> - static target (10 blocks north of the table)
|
||||
|
||||
- `getRelativeAngle()`: get the relative angle to the target, in degrees
|
||||
|
||||
- `getRelativeAngleRad()`: get the relative angle to the target, in radians
|
||||
|
||||
- `getBearing()`: get the forward-error bearing to the target, in degrees
|
||||
- Forward-error bearing:
|
||||
- 0 -> target is straight ahead of the blocks arrow (direct fore)
|
||||
- +90 -> target is to the right (direct starboard)
|
||||
- -90 -> target is to the left (direct port)
|
||||
- +-180 -> target is directly behind (direct aft)
|
||||
|
||||
- `getBearingRad()`: get the forward-error bearing to the target, in randians
|
||||
|
||||
- `getDistanceToTarget()`: get the distance to the resolved target
|
||||
|
||||
- `getClosureRate()`: gets the rate at which the table is closing on the target in blocks/sec (positive is approaching, negative is leaving)
|
||||
|
||||
- `getVerticalOffsetToTarget()`: gets the vertical offset between the target and the table (the difference of `target.y - self.y`)
|
||||
|
||||
- `getOrientation()`: gets the host sub-level's orientation as a quaternion {x, y, z, w}
|
||||
|
||||
> Matches JOML's constructor and the convention used by CC quaternion libraries (e.g. TechTastic/Advanced-Math)
|
||||
|
||||
- `getHeading()`: Gets the host sub-level's heading in degrees
|
||||
|
||||
> 0 degrees refers to world +Z, minecraft south
|
||||
|
||||
- `getHeadingRad()`: gets the host sub-level's heading in radians
|
||||
|
||||
### Gimbal Sensor
|
||||
|
||||
> Peripheral ID: gimbal_sensor
|
||||
|
||||
- `getAngles()`: get the contraption's pitch and roll angles in degrees
|
||||
- xAngle: rotation about body-X (pitch). 0 degrees is aligned with world-up
|
||||
- zAngle: rotation about body-Z (roll). 0 degrees is aligned with world-up
|
||||
- returns {xAngle, zAngle}
|
||||
- `getAnglesRad()`: get the contraption's pitch and roll angles in radians
|
||||
- `getAngularRates()`: get the contraption's angular velocity in degrees/sec
|
||||
- wx: pitch rate
|
||||
- wy: yaw rate
|
||||
- wz: roll rate
|
||||
- returns {wx, wy, wz}
|
||||
- `getAngularRatesRad()`: get the contraption's angular velocity in radians/sec
|
||||
- `getGravity()`: gets the local gravity vector in body frame, in m/s^2
|
||||
- returns {gx, gy, gz}
|
||||
- `getLinearAcceleration()`: get the contraption's proper acceleration in body frame, in m/s^2
|
||||
- returns {ax, ay, az}
|
||||
|
||||
### Velocity Sensor
|
||||
|
||||
> Peripheral ID: velocity_sensor
|
||||
|
||||
- `getVelocity()`: gets the velocity component along the sensor's axis
|
||||
- returns signed velocity in m/s
|
||||
|
||||
> note: returns 0 if the magnitude is below 0.05 m/s
|
||||
|
||||
- `getAxis()`: returns the body-frame axis the sensor measures along
|
||||
- returns string "x", "y", and "z"
|
||||
|
||||
### Analog Transmission
|
||||
|
||||
> Peripheral ID: analog_transmission
|
||||
>
|
||||
> These are used as controllers for rotationally-powered thruster blocks
|
||||
|
||||
- `getSignal()`: get the current signal driving the transmission ratio
|
||||
- returns an integer between 0 and 15
|
||||
- `setSignal(signal)`: set the signal driving the transmission ratio
|
||||
|
||||
> Note: flips externallyControlled, even when signal == current
|
||||
>
|
||||
> The documented way to get control without changing the value is calling `setSignal(getSignal())`.
|
||||
|
||||
- `releaseSignal()`: Release external control and return signal driving to redstone
|
||||
- `isExternallyControlled()`: Check whether the transmission is currently under script control
|
||||
- `getRotationModifier()`: get the current rotation modifier (output:input speed ratio)
|
||||
- `getOutputSpeed()`: get the output shaft speed
|
||||
- `getOutputTheoreticalSpeed()`: get the output shaft's theoretical (target) speed
|
||||
- `getOutputStressImpact()`: get the output-side stress impact (post-ratio kinetic accounting)
|
||||
- `isOversaturated()`: check whether the transmission is oversaturated
|
||||
- `getAxis()`: get the transmission's shaft axis name
|
||||
- returns the axis as string "x", "y", or "z"
|
||||
- `getSelfId()`: get this block's ID
|
||||
|
||||
> Note: other peripherals' getSourceId or getSubnetworkAnchorId will return this ID when they refer to this block
|
||||
|
||||
- `getSourceId()`: get the ID of the block immediately driving this one, or nil if theis block has no source
|
||||
- `getSubnetworkAnchorId()`: get the ID of this block's speed-zone anchor -- the gearshift/clutch/speed controller/generator that defines the start of this speed zone.
|
||||
|
||||
> Note: Two blocks share an anchor if they're in the same speed zone. A generator or split-shaft returns its own `getSelfId()`
|
||||
|
||||
- `getNetworkId()`: get the ID of this block's kinetic network.
|
||||
- `getKind()`: returns one of "generator", "split_shaft", "consumer", or "passthrough"
|
||||
- `getSpeed()`: get the local rotational speed at this block.
|
||||
- `hasSource()`: check whether this block is connected to a kinetic source
|
||||
- `isOverstressed()`: check whether this block's network is overstressed
|
||||
- `getStressImpact()`: get the stress impact of this block on its network. zero for sources and pure conduit blocks
|
||||
- `getStressContribution()`: get this block's contribution to its network's stress capacity. Non-zero for sources only
|
||||
|
||||
## Peripheral Notes
|
||||
|
||||
- Analog Transmissions signal speed changes:
|
||||
- 0: no change from input speed
|
||||
- 14: maximum change from input speed
|
||||
- 15: input and output rotational networks are decoupled (generally means no output rotation)
|
||||
- All that is to say, when being driven properly, the minimum speed is at signal 15, and increasing the speed goes from the lowest nonzero RPM at signal 0 to the highest at signal 14.
|
||||
|
||||
## Implementation
|
||||
|
||||
On startup, call these methods:
|
||||
|
||||
- All Analog Transmission's `getSelfId()`
|
||||
- All rotationally controlled thruster's `getSubnetworkAnchorId()`
|
||||
|
||||
If the ID returned by a thruster's `getSubnetworkAnchorId()` is also returned by an analog transmission's `getSelfId()`, associated that transmission with the thruster
|
||||
|
||||
Also upon startup, check for a configuration file with other thruster's peripherals, or redstone-controlled thrusters
|
||||
|
||||
Every cycle:
|
||||
|
||||
- Check for new machines in the network. If new machines are found, initialize them similarly to the startup
|
||||
|
||||
- Gimbal Sensor `getAngles()`, `getAngularRates()`, and `getLinearAcceleration()`
|
||||
- Navigation Table `getHeading()`, `hasTarget()`, and depending on the output of `hasTarget()`:
|
||||
- if true, call `getBearing()`, `getDistanceToTarget()`, `getClosureRate()`, and `getVerticalOffsetToTarget()`
|
||||
- if false, continue to the next sensors
|
||||
- Altitude Sensor `getHeight()`, `getAirPressure()`, `getVerticalSpeed()`
|
||||
- Velocity Sensor `getAxis()`, `getVelocity`
|
||||
- Poll input signal strengths for global downwards thrust, and fore and aft thrust
|
||||
547
main.lua
Normal file
547
main.lua
Normal file
@@ -0,0 +1,547 @@
|
||||
Thrusters = {
|
||||
thruster0 = {
|
||||
type = "rotator",
|
||||
name = nil,
|
||||
thruster = nil,
|
||||
transmission = nil,
|
||||
-- NOTE:
|
||||
-- affectVectors will have values depending on how the thruster's
|
||||
-- thrust vector interacts with the vessel's attitude
|
||||
-- possible directions for yaw: "port"|"star"
|
||||
-- possible directions for roll: "port"|"star"
|
||||
-- possible directions for pitch: "up"|"down"
|
||||
-- possible directions for lateral: "port"|"star"|"fore"|"aft"|"up"|"down"
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = nil,
|
||||
roll = nil,
|
||||
lateral = nil
|
||||
},
|
||||
power = 0
|
||||
},
|
||||
thruster1 = {
|
||||
type = "thruster",
|
||||
name = nil,
|
||||
thruster = nil,
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = nil,
|
||||
roll = nil,
|
||||
lateral = nil
|
||||
},
|
||||
power = 0
|
||||
}
|
||||
} -- Table of thruster tables
|
||||
|
||||
ConfigPath = "/config/config.lua"
|
||||
Config = {}
|
||||
|
||||
-- Autopilot
|
||||
AutopilotEngaged = false -- Is auto-yaw enabled?
|
||||
AutoForeAft = false -- Is auto-thrust enabled?
|
||||
AutopilotDesiredSpeed = 0 -- Signed thrust value to compare against VelocityVectors["x"]
|
||||
AutopilotDesiredHeading = 0 -- If NavTableHasTarget == true this gets ignored in favor of TargetRelativeAngle
|
||||
|
||||
-- Gimbal Sensor Values
|
||||
Angles = {
|
||||
0, -- xAngle: rotation about body-X (pitch); 0 is aligned with world-up
|
||||
0 -- zAngle: rotation about body-Z (roll); 0 is aligned with world-up
|
||||
}
|
||||
AngularRates = {
|
||||
0, -- wx: pitch rate about body-X
|
||||
0, -- wy: yaw rate about body-Y
|
||||
0 -- wz: roll rate about body-Z
|
||||
}
|
||||
LinearAcceleration = {
|
||||
0, -- Acceleration along body-X
|
||||
0, -- Acceleration along body-Y
|
||||
0 -- Acceleration along body-Z
|
||||
}
|
||||
|
||||
-- Nav Table Values
|
||||
Heading = 0
|
||||
|
||||
-- Nav Table Values (targets)
|
||||
NavTableHasTarget = false
|
||||
BearingToTarget = 0
|
||||
TargetClosureRate = 0
|
||||
TargetVerticalOffset = 0
|
||||
TargetRelativeAngle = 0
|
||||
|
||||
-- Altitude Sensor Values
|
||||
Altitude = 0
|
||||
AirPressure = 0
|
||||
VerticalSpeed = 0
|
||||
|
||||
-- Velocity Sensors
|
||||
VelocityVectors = {
|
||||
x = 0, -- +X is east (port), +Y is up, +Z is south (aft)
|
||||
y = 0, -- -X is west (star), -Y is down, -Z is north (fore)
|
||||
z = 0
|
||||
}
|
||||
|
||||
-- Throttle Inputs
|
||||
Throttles = {
|
||||
ForeThrottle = {
|
||||
name = "",
|
||||
side = "",
|
||||
input = 0
|
||||
},
|
||||
DownThrottle = {
|
||||
name = "",
|
||||
side = "",
|
||||
input = 0
|
||||
},
|
||||
AftThrottle = {
|
||||
name = "",
|
||||
side = "",
|
||||
input = 0
|
||||
}
|
||||
}
|
||||
|
||||
local function getRelayStates()
|
||||
local states = {}
|
||||
local sides = {
|
||||
"top",
|
||||
"bottom",
|
||||
"left",
|
||||
"right",
|
||||
"front",
|
||||
"back"
|
||||
}
|
||||
|
||||
local names = peripheral.getNames()
|
||||
for _, name in ipairs(names) do
|
||||
if peripheral.getType(name) == "redstone_relay" then
|
||||
local wrapper = peripheral.wrap(name)
|
||||
for _, side in ipairs(sides) do
|
||||
states[name][side] = wrapper.getAnalogInput(side)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return states
|
||||
end
|
||||
|
||||
local function identifyRelay(label)
|
||||
print("\nIdentifying "..label.." throttle")
|
||||
print("\nPlease change the input signal for the throttle")
|
||||
|
||||
local initialStates = getRelayStates
|
||||
|
||||
while true do
|
||||
os.pullEvent("redstone_relay")
|
||||
|
||||
local currentStates = getRelayStates
|
||||
|
||||
for pname, currentState in pairs(currentStates) do
|
||||
local initialState = initialStates[pname]
|
||||
for k, v in pairs(currentState) do
|
||||
if initialState[k] ~= v then
|
||||
return {
|
||||
name = pname,
|
||||
side = k
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ThrottleInit()
|
||||
Throttles.ForeThrottle = identifyRelay("fore")
|
||||
Throttles.DownThrottle = identifyRelay("down")
|
||||
Throttles.AftThrottle = identifyRelay("aft")
|
||||
end
|
||||
|
||||
function PropellerInit()
|
||||
local propellerTypes = {
|
||||
"gyroscopic_propeller_bearing",
|
||||
"propeller",
|
||||
"propeller_bearing"
|
||||
}
|
||||
|
||||
local transmissionTypes = {
|
||||
"analog_transmission",
|
||||
"Create_RotationSpeedController"
|
||||
}
|
||||
|
||||
local transmissions = {}
|
||||
local propellers = {}
|
||||
|
||||
for _, v in ipairs(transmissionTypes) do
|
||||
table.insert(transmissions, peripheral.find(v))
|
||||
end
|
||||
|
||||
for _, v in ipairs(propellerTypes) do
|
||||
table.insert(propellers, peripheral.find(v))
|
||||
end
|
||||
|
||||
for pi, pv in ipairs(propellers) do
|
||||
for ti, tv in ipairs(transmissions) do
|
||||
if pv.getSubnetworkAnchorId() == tv.getSelfId() then
|
||||
if Thrusters[peripheral.getName(pv)] == nil then
|
||||
Thrusters[peripheral.getName(pv)] = {
|
||||
type = "rotator",
|
||||
thruster = pv,
|
||||
transmission = tv,
|
||||
-- NOTE:
|
||||
-- affectVectors will have values depending on how the thruster's
|
||||
-- thrust vector interacts with the vessel's attitude
|
||||
-- possible directions for yaw: "port"|"star"
|
||||
-- possible directions for roll: "port"|"star"
|
||||
-- possible directions for pitch: "up"|"down"
|
||||
-- possible directions for lateral: "port"|"star"|"fore"|"aft"|"up"|"down"
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = nil,
|
||||
roll = nil,
|
||||
lateral = nil
|
||||
},
|
||||
power = (tv.getSignal())/15
|
||||
}
|
||||
end
|
||||
if Thrusters[peripheral.getName(pv)] ~= nil then
|
||||
if Thrusters[peripheral.getName(pv)].type == nil then Thrusters[peripheral.getName(pv)].type = "rotator" end
|
||||
Thrusters[peripheral.getName(pv)].thruster = pv
|
||||
Thrusters[peripheral.getName(pv)].transmission = tv
|
||||
if Thrusters[peripheral.getName(pv)].affectVectors == nil then Thrusters[peripheral.getName(pv)].affectVectors = nil end
|
||||
Thrusters[peripheral.getName(pv)].power = (tv.getSingnal())/15
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ThrusterInit()
|
||||
local thrusterTypes = {
|
||||
"thruster",
|
||||
"ion_thruster",
|
||||
"vector_thruster",
|
||||
"liquid_vector_thruster"
|
||||
}
|
||||
|
||||
local thrusters = {}
|
||||
|
||||
for _, v in ipairs(thrusterTypes) do
|
||||
table.insert(thrusters, peripheral.find(v))
|
||||
end
|
||||
|
||||
for ti, tv in ipairs(thrusters) do
|
||||
if Thrusters[peripheral.getName(tv)] == nil then
|
||||
Thrusters[peripheral.getName(tv)] = {
|
||||
thruster = tv,
|
||||
transmission = nil,
|
||||
type = "thruster",
|
||||
-- NOTE:
|
||||
-- affectVectors will have values depending on how the thruster's
|
||||
-- thrust vector interacts with the vessel's attitude
|
||||
-- possible directions for yaw: "port"|"star"
|
||||
-- possible directions for roll: "port"|"star"
|
||||
-- possible directions for pitch: "up"|"down"
|
||||
-- possible directions for lateral: "port"|"star"|"fore"|"aft"|"up"|"down"
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = nil,
|
||||
roll = nil,
|
||||
lateral = nil
|
||||
},
|
||||
power = tv.getPower()
|
||||
}
|
||||
end
|
||||
if Thrusters[peripheral.getName(tv)] ~= nil then
|
||||
if Thrusters[peripheral.getName(tv)].type == nil then Thrusters[peripheral.getName(tv)].type = "thruster" end
|
||||
Thrusters[peripheral.getName(tv)].thruster = tv
|
||||
Thrusters[peripheral.getName(tv)].transmission = nil
|
||||
if Thrusters[peripheral.getName(tv)].affectVectors == nil then Thrusters[peripheral.getName(tv)].affectVectors = nil end
|
||||
Thrusters[peripheral.getName(tv)].power = tv.getPower()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Update()
|
||||
PropellerInit()
|
||||
ThrusterInit()
|
||||
end
|
||||
|
||||
local function checkIfThrusterIsIndexed()
|
||||
local thrusterTypes = {
|
||||
"thruster",
|
||||
"ion_thruster",
|
||||
"vector_thruster",
|
||||
"liquid_vector_thruster"
|
||||
}
|
||||
|
||||
local thrusters = {}
|
||||
local unindexedThrusters = {}
|
||||
|
||||
for _, v in ipairs(thrusterTypes) do
|
||||
table.insert(thrusters, peripheral.find(v))
|
||||
end
|
||||
|
||||
local propellerTypes = {
|
||||
"gyroscopic_propeller_bearing",
|
||||
"propeller",
|
||||
"propeller_bearing"
|
||||
}
|
||||
|
||||
for _, v in ipairs(propellerTypes) do
|
||||
table.insert(thrusters, peripheral.find(v))
|
||||
end
|
||||
|
||||
for _, v in ipairs(thrusters) do
|
||||
if Thrusters[peripheral.getName(v)] == nil then
|
||||
table.insert(unindexedThrusters, v)
|
||||
end
|
||||
end
|
||||
|
||||
if #unindexedThrusters == 0 then
|
||||
return nil
|
||||
end
|
||||
return unindexedThrusters
|
||||
end
|
||||
|
||||
local function partiallyUpdateThrusters(thrusterList)
|
||||
local thrusterTypes = {
|
||||
"thruster",
|
||||
"ion_thruster",
|
||||
"vector_thruster",
|
||||
"liquid_vector_thruster"
|
||||
}
|
||||
|
||||
local propellerTypes = {
|
||||
"gyroscopic_propeller_bearing",
|
||||
"propeller",
|
||||
"propeller_bearing"
|
||||
}
|
||||
|
||||
for _, tv in ipairs(thrusterList) do
|
||||
for _, tt in ipairs(thrusterTypes) do
|
||||
if peripheral.getType(tv) == tt then
|
||||
Thrusters[peripheral.getName(tv)] = {
|
||||
thruster = tv,
|
||||
transmission = nil,
|
||||
type = "thruster",
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
roll = nil,
|
||||
pitch = nil,
|
||||
lateral = nil
|
||||
},
|
||||
power = tv.getPower()
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UpdateStabilization()
|
||||
|
||||
end
|
||||
|
||||
function PollThrottle()
|
||||
for _, v in ipairs(Throttles) do
|
||||
v.input = peripheral.call(v.name, "getAnalogInput("..v.side..")")
|
||||
end
|
||||
end
|
||||
|
||||
function PollSensors()
|
||||
PollVelocity()
|
||||
PollAltitude()
|
||||
PollNavTable()
|
||||
PollGimbal()
|
||||
end
|
||||
|
||||
function PollVelocity()
|
||||
local velSensors = peripheral.find("velocity_sensor")
|
||||
|
||||
-- Velocity Sensors
|
||||
VelocityVectors = {}
|
||||
for vi, vs in pairs(velSensors) do
|
||||
local vsAxis = vs.getAxis()
|
||||
local vsVelocity = vs.getVelocity()
|
||||
VelocityVectors[vsAxis] = vsVelocity
|
||||
end
|
||||
end
|
||||
|
||||
function PollAltitude()
|
||||
local altSensor = peripheral.find("altitude_sensor") -- enforce one alt sensor
|
||||
|
||||
-- Altitude Sensor
|
||||
Altitude = altSensor.getHeight()
|
||||
AirPressure = altSensor.getAirPressure()
|
||||
VerticalSpeed = altSensor.getVerticalSpeed()
|
||||
end
|
||||
|
||||
function PollNavTable()
|
||||
local navTable = peripheral.find("navigation_table") -- enforce one nav table
|
||||
|
||||
-- Navigation Table
|
||||
Heading = navTable.getHeading()
|
||||
NavTableHasTarget = navTable.hasTarget()
|
||||
if NavTableHasTarget then
|
||||
BearingToTarget = navTable.getBearing()
|
||||
TargetClosureRate = navTable.getClosureRate()
|
||||
TargetVerticalOffset = navTable.getVerticalOffsetToTarget()
|
||||
TargetRelativeAngle = navTable.getRelativeAngle()
|
||||
end
|
||||
if not NavTableHasTarget then
|
||||
BearingToTarget = 0
|
||||
TargetClosureRate = 0
|
||||
TargetVerticalOffset = 0
|
||||
TargetRelativeAngle = 0
|
||||
end
|
||||
end
|
||||
|
||||
function PollGimbal()
|
||||
local gimbalSensor = peripheral.find("gimbal_sensor") -- enforce one gimbal sensor
|
||||
|
||||
-- Gimbal Sensor
|
||||
Angles = gimbalSensor.getAngles()
|
||||
AngularRates = gimbalSensor.getAngularRates()
|
||||
LinearAcceleration = gimbalSensor.getLinearAcceleration()
|
||||
end
|
||||
|
||||
function Sigmoid(x)
|
||||
local e = 2.718281828459045
|
||||
return 1 / (1 + e^(-x))
|
||||
end
|
||||
|
||||
function CustomSigmoid(x)
|
||||
return ((2 * Sigmoid(x)) - 1) * -1
|
||||
end
|
||||
|
||||
-- thruster is a thruster type, power is a vector from 0.0 to 1.0
|
||||
function SetThrusterPower(thruster, power)
|
||||
if thruster.type == "rotator" then
|
||||
thruster.power = power
|
||||
local actualPower = 0
|
||||
if peripheral.getType(thruster.transmission) == "Create_RotationSpeedController" then
|
||||
if (math.ceil(power*256) - power*256 <= 0.5) then
|
||||
actualPower = math.ceil(power*256)
|
||||
end
|
||||
if (math.ceil(power*256) - power*256) > 0.5 then
|
||||
actualPower = math.floor(power*256)
|
||||
end
|
||||
|
||||
thruster.transmission.setTargetSpeed(actualPower)
|
||||
end
|
||||
if peripheral.getType(thruster.transmission) == "analog_transmission" then
|
||||
if (math.ceil(power*15) - power*15) <= 0.5 then
|
||||
actualPower = math.ceil(power*15)
|
||||
end
|
||||
if (math.ceil(power*15) - power*15) > 0.5 then
|
||||
actualPower = math.floor(power*15)
|
||||
end
|
||||
|
||||
if actualPower < 1 then
|
||||
actualPower = 15 -- signal 15 will decouple the speed and stop the motion
|
||||
end
|
||||
if actualPower <= 15 then
|
||||
actualPower = actualPower - 1
|
||||
end
|
||||
|
||||
thruster.transmission.setSignal(actualPower)
|
||||
end
|
||||
|
||||
end
|
||||
if thruster.type == "thruster" then
|
||||
thruster.power = power
|
||||
thruster.thruster.setPowerNormalized(power)
|
||||
end
|
||||
end
|
||||
|
||||
function UpdateGlobalThrust()
|
||||
-- lateral thrust
|
||||
local desiredLateralThrustVectors = {}
|
||||
|
||||
for f, v in ipairs(VelocityVectors) do
|
||||
desiredLateralThrustVectors[f] = CustomSigmoid(v)
|
||||
end
|
||||
|
||||
local thrustDirections = {}
|
||||
for f, v in desiredLateralThrustVectors do
|
||||
if f == "x" then
|
||||
if v > 0 then table.insert(thrustDirections, { port = v }) else table.insert(thrustDirections, { star = math.abs(v) }) end
|
||||
end
|
||||
if f == "y" then
|
||||
if v > 0 then table.insert(thrustDirections, { down = v }) else table.insert(thrustDirections, { up = math.abs(v) }) end
|
||||
end
|
||||
if f == "z" then
|
||||
if v > 0 then table.insert(thrustDirections, { fore = v }) else table.insert(thrustDirections, { aft = math.abs(v) }) end
|
||||
end
|
||||
end
|
||||
|
||||
for _, d in ipairs(thrustDirections) do
|
||||
for _, t in ipairs(Thrusters) do
|
||||
if t.affectVectors.lateral == d then
|
||||
SetThrusterPower(d)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- angular thrust
|
||||
local desiredAngluarThrustVectors = {}
|
||||
|
||||
for f, v in ipairs(AngularRates) do
|
||||
desiredAngluarThrustVectors[f] = CustomSigmoid(v)
|
||||
end
|
||||
end
|
||||
|
||||
function Init()
|
||||
ThrottleInit()
|
||||
Thrusters = {}
|
||||
|
||||
local configFile = io.open(ConfigPath, "r")
|
||||
if configFile then
|
||||
local configContent = configFile:read("*all")
|
||||
local configChunk, err = load(configContent)
|
||||
if configChunk then
|
||||
Config = configChunk()
|
||||
else
|
||||
print("Error loading config string: "..err)
|
||||
end
|
||||
else
|
||||
print("Could not open the config file")
|
||||
end
|
||||
configFile.close()
|
||||
|
||||
if Config.thrusterConfigPath ~= nil then
|
||||
local thrusterConfigFile = io.open(Config.thrusterConfigPath, "r")
|
||||
if thrusterConfigFile then
|
||||
local configContent = thrusterConfigFile:read("*all")
|
||||
local configChunk, err = load(configContent)
|
||||
if configChunk then
|
||||
Thrusters = configChunk()
|
||||
else
|
||||
print("Error loading thruster config string: "..err)
|
||||
end
|
||||
|
||||
else
|
||||
print("Could not open the thruster config file")
|
||||
end
|
||||
thrusterConfigFile.close()
|
||||
end
|
||||
|
||||
if Config.ThrusterConfigPath ~= nil then
|
||||
local unindexedThrusters = checkIfThrusterIsIndexed()
|
||||
|
||||
if unindexedThrusters ~= nil then
|
||||
partiallyUpdateThrusters(unindexedThrusters)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Main()
|
||||
Init()
|
||||
|
||||
while true do
|
||||
local unindexedThrusters = checkIfThrusterIsIndexed()
|
||||
if unindexedThrusters ~= nil then
|
||||
partiallyUpdateThrusters(unindexedThrusters)
|
||||
end
|
||||
|
||||
PollSensors()
|
||||
UpdateGlobalThrust()
|
||||
end
|
||||
end
|
||||
27
thrusters.lua
Normal file
27
thrusters.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
return {
|
||||
gyroscopic_propeller_bearing_0 = {
|
||||
type = "rotator",
|
||||
name = "gyroscopic_propeller_bearing_0",
|
||||
thruster = nil,
|
||||
transmission = nil,
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = "up",
|
||||
roll = "star",
|
||||
lateral = nil
|
||||
},
|
||||
power = nil
|
||||
},
|
||||
gyroscopic_propeller_bearing_1 = {
|
||||
type = "rotator",
|
||||
name = "gyroscopic_propeller_bearing_1",
|
||||
thruster = nil,
|
||||
affectVectors = {
|
||||
yaw = nil,
|
||||
pitch = "up",
|
||||
roll = "port",
|
||||
lateral = nil
|
||||
},
|
||||
power = nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user