411 lines
14 KiB
Markdown
411 lines
14 KiB
Markdown
# Implementation Docs
|
|
|
|
## Documentation Bookmarks
|
|
|
|
- [Create: Avionics Documentation](https://solastrius.github.io/CreateAvionics/)
|
|
- [ComputerCraft: Tweaked Documentation](https://tweaked.cc/)
|
|
- [Create Propulsion: Simulated CC:T Peripheral Documentation](https://github.com/Propulsion-Team/create-propulsion-simulated/blob/main/wiki/ComputerCraft-Peripherals.md)
|
|
|
|
## 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", or "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
|
|
|
|
### Tentative Plan
|
|
|
|
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
|
|
|
|
### Math
|
|
|
|
#### Calculate Counteractive Thrust
|
|
|
|
TODO: fill in
|
|
|
|
### Data Structures
|
|
|
|
#### Config
|
|
|
|
The member variables of the Config table is as follows:
|
|
|
|
```lua
|
|
Config = {
|
|
ConfigPath = "/path/to/config.txt",
|
|
thrusterConfigPath = "path/to/thrusters.txt",
|
|
Debug = false, -- controls various debug print statements
|
|
Monitors = {
|
|
InstrumentPanelMonitor = {
|
|
name = "peripheralName",
|
|
peripheral = {} -- stores the table returned by running peripheral.wrap(name)
|
|
},
|
|
AutopilotControlMonitor = {
|
|
name = "peripheralName",
|
|
peripheral = {}
|
|
}
|
|
},
|
|
Autopilot = {
|
|
AutopilotEngaged = false, -- global shutoff for all autopilot functions
|
|
AutoForeAft = false, -- automatic forward/rearward throttle
|
|
AutopilotDesiredSpeed = nil, -- keep a certain velocity
|
|
AutopilotDesiredHeading = nil -- maintain a certain heading
|
|
},
|
|
SensorCorrection = {
|
|
Heading = 0 -- this is directly added to the heading value, in case the vessel was built with the heading not being direct north
|
|
},
|
|
Throttles = {
|
|
fore = {
|
|
name = "peripheralName",
|
|
side = "redstoneRelaySide" -- it is assumed that a user will use a redstone relay for their throttles
|
|
},
|
|
aft = {
|
|
name = "peripheralName",
|
|
side = "redstoneRelaySide"
|
|
},
|
|
down = {
|
|
name = "peripheralName",
|
|
side = "redstoneRelaySide"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### SensorData
|
|
|
|
The member variables of the sensor table is as follows:
|
|
|
|
```lua
|
|
SensorData = {
|
|
Velocity = {
|
|
Raw = {
|
|
x = nil,
|
|
y = nil,
|
|
z = nil
|
|
}
|
|
},
|
|
Altitude = {
|
|
Altitude = nil,
|
|
AirPressure = nil,
|
|
VerticalSpeed = nil
|
|
},
|
|
NavTable = {
|
|
Heading = nil,
|
|
HasTarget = nil,
|
|
-- values past this are only populated if HasTarget == true
|
|
TargetBearing = nil,
|
|
TargetClosureRate = nil,
|
|
TargetVerticalOffset = nil,
|
|
TargetRelativeAngle = nil
|
|
},
|
|
Gimbal = {
|
|
Angles = {
|
|
xAngle = nil,
|
|
zAngle = nil
|
|
},
|
|
AngularRates = {
|
|
wx = nil,
|
|
wy = nil,
|
|
wz = nil
|
|
},
|
|
LinearAcceleration = {
|
|
ax = nil,
|
|
ay = nil,
|
|
az = nil
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Thrusters
|
|
|
|
The member variables of the Thruster table are as follows (using some example thrusters):
|
|
|
|
```lua
|
|
Thrusters = {
|
|
gyroscopic_propeller_bearing_0 = {
|
|
-- primary attitude thruster?
|
|
primary_pitch_thruster = true,
|
|
primary_roll_thruster = true,
|
|
primary_yaw_thruster = false,
|
|
-- primary lateral thruster?
|
|
primary_altitude_thruster = true,
|
|
primary_fore_thruster = false,
|
|
primary_aft_thruster = false,
|
|
type = "rotator",
|
|
name = "gyroscopic_propeller_bearing_0",
|
|
thruster = nil,
|
|
transmission = nil,
|
|
affectVectors = {
|
|
angular = {
|
|
yaw = nil,
|
|
pitch = "up",
|
|
roll = "star",
|
|
},
|
|
lateral = {
|
|
x = nil,
|
|
y = "up",
|
|
z = nil
|
|
}
|
|
},
|
|
power = nil
|
|
},
|
|
gyroscopic_propeller_bearing_1 = {
|
|
-- primary attitude thruster?
|
|
primary_pitch_thruster = true,
|
|
primary_roll_thruster = true,
|
|
primary_yaw_thruster = false,
|
|
-- primary lateral thruster?
|
|
primary_altitude_thruster = true,
|
|
primary_fore_thruster = false,
|
|
primary_aft_thruster = false,
|
|
type = "rotator",
|
|
name = "gyroscopic_propeller_bearing_1",
|
|
thruster = nil,
|
|
transmission = nil,
|
|
affectVectors = {
|
|
angular = {
|
|
yaw = nil,
|
|
pitch = "up",
|
|
roll = "port",
|
|
},
|
|
lateral = {
|
|
x = nil,
|
|
y = "up",
|
|
z = nil
|
|
}
|
|
},
|
|
power = nil
|
|
},
|
|
gyroscopic_propeller_bearing_2 = {
|
|
-- primary attitude thruster?
|
|
primary_pitch_thruster = true,
|
|
primary_roll_thruster = true,
|
|
primary_yaw_thruster = false,
|
|
-- primary lateral thruster?
|
|
primary_altitude_thruster = true,
|
|
primary_fore_thruster = false,
|
|
primary_aft_thruster = false,
|
|
type = "rotator",
|
|
name = "gyroscopic_propeller_bearing_2",
|
|
thruster = nil,
|
|
transmission = nil,
|
|
affectVectors = {
|
|
angular = {
|
|
yaw = nil,
|
|
pitch = "down",
|
|
roll = "port",
|
|
},
|
|
lateral = {
|
|
x = nil,
|
|
y = "up",
|
|
z = nil
|
|
}
|
|
},
|
|
power = nil
|
|
},
|
|
gyroscopic_propeller_bearing_3 = {
|
|
-- primary attitude thruster?
|
|
primary_pitch_thruster = true,
|
|
primary_roll_thruster = true,
|
|
primary_yaw_thruster = false,
|
|
-- primary lateral thruster?
|
|
primary_altitude_thruster = true,
|
|
primary_fore_thruster = false,
|
|
primary_aft_thruster = false,
|
|
type = "rotator",
|
|
name = "gyroscopic_propeller_bearing_3",
|
|
thruster = nil,
|
|
transmission = nil,
|
|
affectVectors = {
|
|
angular = {
|
|
yaw = nil,
|
|
pitch = "down",
|
|
roll = "star",
|
|
},
|
|
lateral = {
|
|
x = nil,
|
|
y = "up",
|
|
z = nil
|
|
}
|
|
},
|
|
power = nil
|
|
}
|
|
}
|
|
```
|