KontrolSystem2
KontrolSystem2 copied to clipboard
Request for bunch of Quality Of Life data
version 0.5.3.4 (Ckan) gessed tag : Question, Enhancement
Hi ! Maybe I didn't be able to found thoses, in that case, «My bad», but I miss some acces to definitions datas.
Fairing (feels important to me)
There is 2 kind of fairing : the conveniences ones, and the wanted ones. I mean, when you put a stage under an engine, this one is covered by a fairing. It's thoses I call the conveniences ones. And there is obviously the fairing you put to protect your payload, have better aerodynamics etc aka the wanted ones.
Since vessel.parts.filter(fn(p) -> p.fairing.defined) is not able to distinguish them, I would like to know if there is an other way I didn't think about.
At first, I was thinking «Nah, easy, I collect fairings, I substract engines, and i'm good to go»
BUT ! Because there is a 'but', obviously, engines are not the only ones to have «conveniences» fairings. Heatshields too. And structural hollow tubes. And probably some others parts I didn't think about. And all thoses delicious parts don't have any modules to identify them :)
As part.is_fairing is probably an equivalent of part.fairing.defined, his behavior is unsurprizingly the same.
I'm not feeling good at the idea to look at the name of a part to identify it. I think it's not reliable.
If I didn't miss a way, maybe a part.fairing.value.is_jettisonable could be a good idea (since I wasn't able to jettison «convenience» fairing)
Solar panels (feels important to me)
I have a nice piece of code which is able to give the one of best vectors to expose to the sun. But in order to be able to do it, I needs to know max output of each solar panels. Maybe I miss it, but I haven't be able to found it. I had to write this kind of things :
pub const SolarPanel: (Name: string, MaxFlow: float)[] = [
(Name: "solararray_0v_flat", MaxFlow: 0.145209029316902), // OX-STAT
(Name: "solararray_1v_1x6", MaxFlow: 0.968068957328796), // OX-4L
(Name: "solararray_1v_3x2", MaxFlow: 0.968069076538086), // OX-4W
(Name: "solararray_1v_shielded_1x6", MaxFlow: 0.968068957328796), // SP-4L
(Name: "solararray_1v_shielded_3x2", MaxFlow: 0.968069076538086), // SP-4W
(Name: "solararray_1v_flat", MaxFlow: 1.21007525920868), // OX-STAT-XL
(Name: "solararray_1v_circular", MaxFlow: 3.3882417678833), // OX-10C
(Name: "solararray_1v_circular_shielded", MaxFlow: 3.3882417678833), // SP-10C
(Name: "solararray_2v_accordion", MaxFlow: 11.6168279647827), // SP-XL 'Gigantor'
(Name: "solararray_3v_large", MaxFlow: 33.8824119567871), // SP-XXL 'Colosse'
]
As said, I don't think it's a reliable way to gather data.
Resources / Engines (seems to be a good idea)
Did I miss a way to connect an engine with the fuel it burn ?
I wrote this :
pub type ResourceConst = int
pub const Resource: (MP: ResourceConst, SF: ResourceConst, Air: ResourceConst, H: ResourceConst, CH4: ResourceConst, Ox: ResourceConst, EC: ResourceConst, Xe: ResourceConst, Ab: ResourceConst) = (
MP: 1, // "ME"->"MP" Monopropellant
SF: 2, // "ES"->"SF" Solid Fuel
Air: 3, // "Air"->"Air" Air
H: 6, // "H"->"H" Helium
CH4: 7, // "CH4"->"CH4" Methane (Liquid Fuel)
Ox: 8, // "Ox"->"Ox" Oxygen
EC: 12, // "CE"->"EC" Electrical Charge
Xe: 13, // "Xe"->"Xe" Xenon
Ab: 15 // "Ab"->"Ab" Ablator
)
pub const EngineFuel: (Fuel: int, Engine: string)[] = [
(Fuel: Resource.MP, Engine: "MonoProp"), // "ME"->"MP" Monopropellant
(Fuel: Resource.SF, Engine: "SolidBooster"), // "ES"->"SF" Solid Fuel
(Fuel: Resource.Air, Engine: "Turbine"), // "Air"->"Air" Air
(Fuel: Resource.H, Engine: "Nuclear"), // "H"->"H" Helium
(Fuel: Resource.CH4, Engine: "Methalox"), // "CH4"->"CH4" Methane (Liquid Fuel)
(Fuel: Resource.CH4, Engine: "Turbine"), // "CH4"->"LF" Methane (Liquid Fuel)
(Fuel: Resource.Ox, Engine: "Methalox"), // "Ox"->"Ox" Oxygen
(Fuel: Resource.EC, Engine: "Electric"), // "CE"->"EC" Electrical Charge
(Fuel: Resource.Xe, Engine: "Electric") // "Xe"->"Xe" Xenon
]
which is far more reliable than looking at part's name.
It connect part.engine_module.value.current_engine_mode.engine_type to a part.resources.list.map(fn(r) -> r.resource.id).
This is way less an issue than others topics, but just in case I miss something... :). But I don't think it's a bad idea to have a way to know what input/output each part are able to.
For example, most Liquid Fueled engines have Oxygen and Methan as Input, and have Electric charges as output.
Propellant Tanks have their propelant as output
Solar panels have Electric charges as output
etc
The cherry on the cake would be able to ignite individualy each engine, especially since part.engine_module.value.independent_throttle have appeared ^^
Heatshield (feels accessory)
Maybe thoses parts would have benefits to have their very own module, since they can be deployed, they have resources (Ablator), fairing, etc It would be a shame to inadvertently deploy one of those (Yes, I look at you, inflatable heatshield) while expecting deploy antennaes, solarpanels, cargoholds etc :) At the time, I'm able to filter them on the resources the part hold. If their is 'Ablator' in it, it's a heatshield.
Edit : typo, grammar etc
If I may add:
ENGINES: access to engine's thrust limiter (R/W). WARP: it's possible to get current_rate and current_index of the actual warp. Is it possible to change them?
@lefouvert I don't understand how Resource and EngineFuel work. What are the numbers next to the resources?
@PhilouDS The numbers in Resource are the ingame ids of the resources.
When you look at a part's resources, you may access to this id
part.resources.list.map(fn(r) -> r.resource.id)
ResourceContainer
ResourceData
ResourceDefinition
Displayed names are more user friendly, but id's are more efficient to link datas.
EngineFuel is just an array that describe which engine burn which fuel.
So if I run a «LV-1 'Ant'» engine, I'm able to know it's a Methalox engine type
part.engine_module.value.current_engine_mode.engine_type
ModuleEngine
EngineMode
EngineType
which will burn CH4 and Ox. I just have to search for parts inside the decouple stage I consider thoses which have CH4 and Ox.
With thoses two datas, you can know the mass a part will lost, and deduce lot of things as deltaV, isp, burntime etc.
Kontrol System give us access to most of thoses datas, but I gess they are retrieved directly from the game, which implies some are missing.
This nice little thing is able to achieve a circular orbit around Kerbin, at any inclination. However KSP2 and Kontrol System
vessel.delta_v.stages[].get_deltav(DeltaVSituation.Vaccum) are undivided : the 4 firsts stages aren't able to deliver any thrust, and don't provide any delta V.
And I can garantee you that LV-1 'Ant' didn't lift it in the sky.
Thank you for all those explanations. Nice log in the Console. Too bad we can't save that in a txt file... yet ;-) In the BAV, I've created an UI and I compute myself the effective velocity of a stage to calculate then the delta-v. Maybe, I could look deeper of what you did to improve that.
At least, my stage info window (at the bottom) is better than the one from MicroEngineer (which only uses the numbers from KSP).
@untoldwind I see you ^^
Thoses things_array.reduce(<Foobar>[], fn(flat, things) -> flat + things.filter(fn(t) -> t.defined)) seems to had given you some inspiration :)
Thank you very much.
For that and all.
That are a lot of wishes and unluckily I messed my games-saves I use for testing. So there is just a pre-release for now: https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.3.5 Updated documentation: https://kontrolsystem2.readthedocs.io/en/prerelease/
From top to bottom (mostly):
-
I added a
.filter_mapto array, which is similar to.mapbut the function should return anOptionand only the defined value end up in the result.- So to get a list of all the solar_panels one can now just do
vessel.parts.filter_map(fn(part) -> part.solar_panel) - Similarly all the other things like fairing/air intakes etc.
- So to get a list of all the solar_panels one can now just do
-
Also added a
.flat_map, in which the function returns an array, that as then concatenated in result.- E.g. to get all the resources of a vessel:
vessel.parts.flat_map(fn(part) -> part.resources.list)
- E.g. to get all the resources of a vessel:
-
As for the fairing: I checked the current implementation,
part.fairingseems to be working as intended. Maybe you have a cargo-bay instead, which can be found and controlled viapart.deployable? -
As for solar panels: The energy-flow is actually a bit more complicated:
- There is now a
.base_flow_rateand.efficiency_multiplierwhich seem to be constants of the model - Additionally there is the
.star_energy_scalewhich changes with the distance to the star (and probably also depends on the type of star once we get the interstellar patch) - The
.max_flowis a shortcut forbase_flow_rate * star_energy_scale * efficiency_multiplier - And eventually:
.energy_flowis the current energy flow which is a fraction of.max_flowdepending on sun-exposure (and angle I guess)
- There is now a
-
As for the propellant/resource information of the engine: Again a bit more complicated
- There is now a
.current_propellantwhich is the currently used propellant depending on the engine mode - Additionally
.propellantsreturns all the potential propellants in the same order as.engine_modes(if the engine only has one mode there should be only one element) - Unluckily it gets even more complicated: The propellant might be a mixture different resources.
- E.g. most engines will have
.current_propellant.name == "Methalox", which is a mix of two resources - In these cases
.current_propellant.is_recipeistrueand.current_propellant.recipe_ingredientswill contain a list of all the ingredients and their ratio.
- There is now a
-
The heatshield has been added with some basic fields:
is_deployedis_ablatingis_ablator_exhaustedablator_ratio- ... maybe this can be a bit more detailed
-
As for the thrust limiter: This should now be tweakable via
engine.thrust_limiter -
As for warp: Some basic information should have be already available in the
ksp::game::warpmodule: https://kontrolsystem2.readthedocs.io/en/prerelease/reference/ksp/game_warp.html- At the moment this is read-only. I will check if there is an easy way to make tweakable as well
Undoubtly, you may say me 'no' at anytime, if it's bad ideas or too much work. Besides, I'm blown away by the speed you implement all thoses ! From top to bottom ;) :
.filter_map&flat_mapsmell like candies. I'll have to re-read all my code to add this, it will be way more readable :)- Fairings : I'm not saying they don't work as intended. They absolutly work as intended. I was just seeking an idea to differenciate the "explicit" fairing as 'AEFF000' part or 'AEFF375' part, and the "implicit" fairing, as the one which cover an engine or a heatshield.
I have a
.check_fairing()method which is unable to see any difference between both, and after having successfully jettisoned the AEFF125, try desperately to jettison the engine fairing. In vain, obviously, since it will be automaticly jettisoned at the staging, not before, not after. - solar panels : I understand why you had to take care of all thoses parameters. I must admit it was an untold wish to have access to all of them. I'm fulfilled. I had some testings on solar panels, so I can answer you : Yes,
.energy_flowis totaly dependent of the angle :) - Engines' propellants : as solar panels, your implementation is above expectations. Does
.recipe_ingredientscontains a list of 1 ingredient if it's not a recip, (for monoprop, for example) ? - Heatshield : at the time, I don't see more which could be usefull.
- thrust limiter : Oh that's a cheating parameter x). Solid Booster powered launcher with in flight variable thrust will appear soon. I can garantee it ^^. I'll try for fun, but not in main code base.
- Warp : PhilouDS oriented gift. At the time, I do not have any needs on this topic, since I do not have ended my ship.park() method which is , for me, a mandatory to warp. I will not let my vessel deplete all EC while time warping because of bad sun exposure :)
Can I say enough 'thank you' to illustrate how much I'm happy with all thoses addings ?
Edit typo, grammar etc as usual
Ah ok, the engine fairing was not on my radar. Quick workaround would be to filter out the engines before using .filter_map. E.g.
vessel.parts.filter(fn(part) -> !part.is_engine).fitler_map(fn(part) -> part.fairing)
But I understand that this is somewhat confusing. I'll probably split the API in .fairing and .engine_fairing
As for the the propellants: If .is_recipe is false than the propellant is just the resource that is used, i.e. .receipe_ingredients should be empty. Otherwise this would be just a reference to self.
As said, I had think about excluding engine parts, howerver, this behavior is also true for heatshield (nice we can recognize them and exclude them now ^^) AND at least thoses parts :
- Structure/MountPlate/MEM-XXX
- Structure/Tube/TUUB-XXX And maybe some other I could had miss.
Created a new pre-release: https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.3.6
part.fairingshould now only cover fairings- EDIT: Sorry saw that last comment too late, only engines are excluded. I will try to find a stable way to only get "real" fairings.
- For engines:
part.engine.fairingorpart.engine.has_fairing - To get cargo bay (which are deployables) there is now also a
part.is_cargo_bay- Note: There is no corresponding
part.cargo_baybecause cargo bays do not really have any interesting values to tweak that are not covered withpart.deployable
- Note: There is no corresponding
As for the time-warping:
- The
ksp::game::warpmodule has been extended: https://kontrolsystem2.readthedocs.io/en/prerelease/reference/ksp/game_warp.html - In particular there is a
set_warp_index(int)function.- Note: This can not be used in a sync function ... I encountered some very strange behavior when not waiting for a next game update cycle. Playing with time has to be done with care, H.G. Wells wrote a book about it.
Hopefully this is the one: https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.3.7
I added part.part_category and .fairing should now only contain fairings in the Payload category
Just did few testings :
Notice deployable.value.deploy_state became a constant instead of a string. Nice touch ^^
Legitim fairings respond positively to .is_cargo_bay.
Will test others aspects later, but it smell good.
Little engine test.
With is_recipe false, .recipe_ingredients is not even instancied (Not really surprizing).
Out of curiosity, why .recipe_ingredientsis not an Option<ResourceReceipeIngredient[]> ? (Just to get a better understanding ! )
Yes good point that should be an option.
I merge it all into the 0.5.4.0 release.
.recipe_ingredients is now Option<ResourceReceipeIngredient[]> as suggested
Sorry, I was a bit busy this week-end, so I can't look at all I was expecting on KSP2 & KS2.
Browing datas and engines, I was thinking about propellants.
EngineMode govern which propelant is used, this is why an array is needed for part.engine_module.propellants. After had read your source code (and what I assume to be KSP2 .dll api's files like Data_Engine.cs), I assume index of part.engine_module.propellants match index part.engine_module.engine_modes.
Would it make sense that propellants be a property of EngineMode (not array, therefore, but keeping the notion of recipe and the recipe array) rather than ModuleEngine?
It's just an idea to talk about.
I just noticed that the underlying structure of EngineMode also has a propellant definition, have to check if that is in sync with the the one on the engine though.
I saw you added some information for engines and solar panels in the VAB too :) Is it possible to have access to the Electricity consumption of any part inside the VAB (to compute the total consumption)?
@PhilouDS I just take a look at PartComponent.cs (little 2k lines file) which seems be a portion of the API. It don't seems to be an easy task. Apparently, all goes through something like a PartResourceFlowRequestBroker which don't seems to have a direct access thru a public method. I didn't explore enough to be fluent into thoses files, but seems to be a chore. Maybe I'm wrong, Untoldwind should be able to correct my assessments.
Looks like all the Data_* structures (e.g. Data_Command, Data_Transmitter etc.) have either resource settings or requiredResources. At first glance this seems to contain ElectricalCharge as a resource requirement for certain modules.
Though I have to do some restructuring to make this available in VAB and flight ... hopefully I will not break too many eggs in the process.
Thanks for your answer. If it's too complicated, don't worry about this. You certainly have a lot on your plate.
There are some (potential) breaking changes: I noticed that ModuleCommand and ModuleDockingNode hat a lot of field from the underlying part, which does not translate well to the VAB version.
So instead I added a .part field to all the modules (i.e. if your scripts are now missing a moduleDockingNode.something_important just use moduleDockingNode.part.something_important now).
Upside to this:
- API is now more consistent
- A lot of modules are now available in the VAB
Just a pre-release for now (too many changes ;) ) https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.5.0 Documentation: https://kontrolsystem2.readthedocs.io/en/prerelease/
... and most importantly: I added bindings for ModuleLight. Your disco needs you!
KSP2 tells me than Flight_plan is a now a dependency of this pre release version. Is it normal?
@untoldwind I do not understand what you are talking about
@PhilouDS : Flightplan is marked as a soft dependency (i.e. should be optional) Some time ago we were testing out the possibility to include APIs to other mods. In theory:
- If flightplan is installed if can be accessed via
flight_plan()inksp::addons - If it is not installed that function returns None.
Maybe the logic of soft dependency has changed in SpaceWarp recently, I will checkout the latest version
@PhilouDS I just checked the newest pre-release 0.5.5.1 with the latest spacewarp 1.9.4 without flightplan installed, which works fine for me.
Please check the BepInEx/LogOutput.log file in the game folder. It should contain some more detailed information why the plugin is suddenly creating problems
I have installed the version 0.5.5.1 and I don't have the problem anymore. I don't know why but it's fine now.
@PhilouDS I think I reproduced the problem by downgrading spacewarp to 1.6.0 was able to resolve the dependency issue by removing the BepInEx/cache folder
Just to note :
This deLICious .flat_map didn't have been reported on Ranges ^^
(I'm not sure their is any purpose to have a .filter_map on ranges since ranges are integer only)
Pre-release 0.5.5.3 https://github.com/untoldwind/KontrolSystem2/releases/tag/v0.5.5.3
contains .flat_map and .filter_map for ranges.
There actually might be some use-cases for the latter.