That file has been included, but apparently only with Facelifts (under <OMSI>\Vehicles\CSB_M_MB_O530_II\Model\ACE\tuertaster_ext_clickspot.o3d). Thus, for each non-Facelift vehicle, the corresponding path reference within its model.cfg should be changed to point to ..\..\CSB_M_MB_O530_II\Model\ACE\O530\tuertaster_ext_clickspot.o3d.
Posts by Unorthodox Paradox
The forum is in reduced operation. The Addon and Support forums remain open.
Please note that OMSI is no longer under development. Some of the developers are now working on a new simulator. Further information concerning the LOTUS-Simulator can be found here.
Please note that OMSI is no longer under development. Some of the developers are now working on a new simulator. Further information concerning the LOTUS-Simulator can be found here.
-
-
You might want to check your sound.cfg (and model.cfg too, although less likely) for potential stale references to that variable.
-
-
Hi Niemand ,
Thanks for informing that the particular web-host has ceased operation. I re-uploaded the files elsewhere and updated the download link in the OP. If you encounter any strange issues, let me know. Please note however that this is still that same old original version, with compatibility limited to the first-gen Citaro, as per Morphi's v. 4.4 "patch"/pack.
-
I forgot something: can I make a [light_enh_2] source visible by a script? To be more precise, in real life, some examples of the same bus model had a type of position light, while other ones had a different type. It all depends on the fleet number of said bus.
Yes, you can, but it would only make sense to do so if the lighting effects themselves ought to differ (and not merely the corresponding objects).
Each [light_enh_2] references a so-called fading variable, valued between 0 (off) and 2 (double intensity). For standstill lights, that variable is typically lights_stand (some sources modeled as independent meshes get to use their own dedicated variable, like lights_edge_front_bulb_[l|r] for the top head position lights -- but let's disregard these for simplicity's sake for the time being).
In the lighting script, you would then introduce two additional variables, say lights_stand_type_a_active and lights_stand_type_b_active, that derive their state from the base lights_stand variable, under the additional constraint that a certain configuration variable (as discussed in your prior thread) has a certain value; e.g.:
You would append that fragment right before the closing {end} of the {macro:lights_frame}-block (while not neglecting to also declare lights_stand_type, lights_stand_type_a_active, and lights_stand_type_b_active in a varlist), such that the derived variables always reflect the latest state of the lights_stand variable.
Next, in your model.cfg, you would have one group of [light_enh_2] entries for the first type of position lights, each of which referencing lights_stand_type_a_active as its fading variable, and another group of [light_enh_2] entries for the second type, each of which referencing lights_stand_type_b_active as its fading variable. And of course the [visible] flag of the corresponding [mesh] entries would reference lights_stand_type accordingly (if equal to 0, then first type visible; if equal to 1, then second type visible).
Of course, if the two types of lights exhibit different electrical properties (e.g. different minimum voltage below which bulbs/units will go off; or radically different power consumption per unit; or perhaps different mapping between cockpit state and light circuit state), then more complexity will have to be introduced to account for these as well.
-
Hello,
It's hard to answer those questions without having concrete code to look at. Are you using the same scripts as the standard buses (MAN SD/NL/NG)? If not, would you mind attaching/uploading, or at least pointing out which scripts and accompanying const-files you're using for all the involved components (cockpit, engine, gearbox/transmission (a.k.a. "Antrieb" in German))? The relevant model.cfg entries might be helpful as well.
With regards to the maxspeed and delay animation attributes, I am unfortunately unaware of a normative documentation reference on them. Empirically I would like to believe that they are intended for providing convenient animation actualization inertia, in those cases where the script only specifies the target/final position/angle of the animation, without bothering to implement intermediate update logic. This, for example, tends to be the case with analogue thermometers, or rev counters, or sometimes even plain dashboard switches, where the script performs the measurement or other update action instantly, but we would still like the instrument or controller to be able to exhibit some actualization inertia, as it would in the real world. On the other hand, these attributes are e.g. usually not employed with doors, whose animations are more complex, with variable acceleration and blocking conditions, and thus necessitating a 100% programmatic implementation. As for the concrete meaning behind maxspeed and delay, my arbitrary guess is that the former translates to a maximum actualization rate (% change per unit of time, perhaps seconds or millis, I have honestly no idea), whereas the latter translates to the time necessary for the effective actualization rate to reach that maximum. OMSI might then internally create some sort of curve, expressing the effective actualization rate as a function of maxspeed and delay. Again, this is all just speculation, and may be totally wrong. Because of this ambiguity, I personally prefer to implement animations purely programmatically, even if it requires a bit more effort; then I at least know exactly why/how the animation works, and what to troubleshoot when it doesn't.
-
Hello,
Woher weiß ich, welche Zahl hinter dem L.L.door stehen muss?
In every* door_X variable, X stands for the real door wing index, as we perceive it by looking at the physical ordering of doors, beginning from 0, from front to rear. So door_0 reflects the opening state of the first wing, door_1 of the second wing, ..., door_7 of the eighth wing.
Was hat es mit der 5 auf sich? Es gibt doch gar keinen 5.Türflügel.... (eigentlich doch nur 0,1,2 und 3)
Indeed, if all doors combined only yield 4 wings total, then the door_4, door_5 variables are useless. But perhaps the author intended to reuse the same code with 3-door vehicle variants. Or they just didn't bother cleaning up the redundant code.
Wo ist L.L.door_4?
This is likely a shortcut because the author thinks that both wings will be opening/closing (almost) synchronously, and hence deems it appropriate to just check whether one wing, likely the slowest one, is sufficiently open to allow boarding/disembarking. But of course that will fail if one decides to manually (e.g. via the emergency opening valves) open just these individual wings (door_3, door_5) while leaving the other two (door_2, door_4) closed, in which case passengers will magically be able to walk through the closed latter ones as well.
So the proper expression would be:
...or better yet, for individual control:
Der dritte Eintrag heißt ja meines Wissens, dass die 1.Tür zum Ausstieg freigegeben ist, wenn der 3.Türflügel (2.Tür also) zu 0.9 offen ist.
Wenn ich diesen Eintrag rausgelöscht habe, sind die Fahrgäste nicht mehr hinten ausgestiegen. Dabei ist in der passengercabin.cfg gar kein Ausstieg an der ersten Tür vermerkt und dieser dritte Eintrag doch eigentlich überflüssig?
No, the index X in the PAX_[Entry|Exit]X_[Open|Req] variable names is not necessarily equivalent to the X in door_X. Here X means strictly according to the ordering of the passengercabin.cfg. And the ordering in the .cfg represents priority, and not (necessarily) physical door wing order.
For example, suppose that we have a bus with 5 doors (let's forget about door wings for a moment, for clarity's sake). Suppose also that we want our passengers to be able to board the vehicle from doors 3, 1, and 5, in that exact priority. And we would also want them to be able to disembark from doors 1 and 4 (here there's no notion of priority -- passengers in OMSI always choose the nearest exit). As for the spare 2nd door, we want it to be purely cosmetic, i.e., to neither serve as an entry nor as an exit to passengers.
Here's how the .cfg would look like:
Code- [entry] <- 1st logical entry, a.k.a. PAX_Entry0_[Open|Req]
- <path point near 3rd physical door, a.k.a. door_2>
- [entry] <- 2nd logical entry, a.k.a. PAX_Entry1_[Open|Req]
- <path point near 1st physical door, a.k.a. door_0>
- [entry] <- 3rd logical entry, a.k.a. PAX_Entry2_[Open|Req]
- <path point near 5th physical door, a.k.a. door_4>
- [exit] <- 1st logical exit, a.k.a. PAX_Exit0_[Open|Req]
- <path point near 1st physical door, a.k.a. door_0>
- [exit] <- 2nd logical exit, a.k.a. PAX_Exit1_[Open|Req]
- <path point near 4th physical door, a.k.a. door_3>
And here's how the .osc would look like:
Code- ' Map door_0 (1st physical door) to PAX_Entry1_Open (2nd logical entry) and PAX_Exit0_Open (1st logical exit)
- (L.L.door_0) 0.9 > (S.L.PAX_Entry1_Open) (S.L.PAX_Exit0_Open)
- ' Map door_2 (3rd physical door) to PAX_Entry0_Open (1st logical entry)
- (L.L.door_2) 0.9 > (S.L.PAX_Entry0_Open)
- ' Map door_3 (4th physical door) to PAX_Exit1_Open (2nd logical exit)
- (L.L.door_3) 0.9 > (S.L.PAX_Exit1_Open)
- ' Map door_4 (5th physical door) to PAX_Entry2_Open (3rd logical entry)
- (L.L.door_4) 0.9 > (S.L.PAX_Entry2_Open)
Note that there's no door_1 above. This doesn't mean that the variable is useless though, since it would still be used to animate the 2nd physical door, in another part of the script. It just hasn't been mapped to any entry or exit used by passengers, since we don't want passengers to ever use it.
* * *
* Strictly technically speaking, that's not true. door_X are non-standard variables, and as such they can represent anything the script/bus author wants them to represent. But in practice X indeed virtually always follows the physical door (wing) ordering, as do the actual values assigned to those variables.
-
Laut Fahrplan:
Laut IBIS/Drucker/Innenanzeige:
Aber: Nicht alle IBIS/etc. Scripts verwenden die act_busstop Standartvariable. Sollte es also vorkommen dass letztere nichts enthält, dann muss im Script nach den Variablen gesucht werden, die den aktuellen Route- und Haltestellen-Index enthalten (bspw. im M+R IBIS-2.osc sind es IBIS_RouteIndex und IBIS_busstop). Über diese kann dann wie folgt der Haltestellenname abgefragt werden:
Weitere Informationen zu den oben erwähnten Variablen und Makros:
-
Thanks to the current situation, I've had some time to take a fresh closer look at this problem. While I still don't have an exact answer that one could copy and paste, I think I have the foundation toward a workaround that, if refined and tested meticulously, might just turn out sufficient to cover a good portion of the various use cases requiring the ability to accurately assess brightness.
The workaround in a nutshell:
1. Park a vehicle at a dark location far away from any light-emitting scenery objects, where certain that Envir_Brightness measurements are not going to be positively skewed. Set the weather conditions to best (max visibility and lightness, clear sky, no precipitation). Set the time to a value close to solar nadir. Then begin incrementing the time at small "steps", corresponding to e.g. 0.5 degrees SunAlt. Each time note down -- ideally assisted by a script, in order to retain the best possible precision -- the pair (SunAlt, Envir_Brightness). Proceed until the sun has reached its zenith. Let's call this dataset bmax(s), i.e., the maximum naturally attainable brightness, b, as a function of solar elevation angle, s.
2. Repeat step 1 under the worst selectable weather conditions (min visibility and lightness, overcast sky, max precipitation). Let's call this dataset bmin(s).
3. Copy the datasets over to some spreadsheet and plot a combined chart of both. Looking at the chart you will realize that both curves are approximately piecewise-linear most of the time. Hence most of their data-points can be eliminated, leaving just a handful at which their curvature changes. Specifically the following intervals are of interest:
- s ∈ (-90, -18). The latter edge reflects the transition time between night and twilight, as specified by default in the envir.cfg. Both curves are linear in this interval.
- s ∈ (-18, -1.15) for bmax, s ∈ (-18, 0) for bmin; both linear.
- s ∈ (-1.15, 0) and s ∈ (0, 1.15), only for bmax. Here bmax is not linear, but has a steadily ascending slope, so it's a good idea to retain multiple data-points throughout these intervals.
- s ∈ (1.15, 10) for bmax, s ∈ (0, 10) for bmin; both linear. The latter edge reflects the transition time between twilight and day, as specified by default in the envir.cfg.
- s ∈ (10, 37.685), s ∈ (37.685, 63.3), s ∈ (63.3, 90), only for bmax, and linear.
- s ∈ (10, 90), only for bmin, and linear.
Having simplified the observation curves, removing duplicate data-points and smoothing out potential measurement errors, we now know what the maximum and minimum naturally attainable brightness at any given solar elevation angle is.
4. It is now a good idea to collect more data for various other sets of weather conditions, lying somewhere between the "best" and "worst" boundary. You will see why in a moment. At the very least the following conditions should be observed: a) minimum visibility, b) minimum lightness, c) an "overcast" cloud type, d) some scattered cloud type, ideally based on a custom, uniformly transparent texture, for preserving measurement accuracy, and e) maximum precipitation.
5. Having collected all that data, we can now ponder what we can make of it. Because all those curves are mostly linear, they readily reveal their slopes, or derivatives if you will, within the corresponding intervals as well, which are either constant, or in the case of bmax for s ∈ (-1.15, 1.15), just a straight line. The derivatives -- let's call them deltas for short -- are of value, because they can be measured accurately at times when brightness itself cannot; most notably when the vehicle is stationary, which is a recurring situation in OMSI (stops, traffic jams/lights). The reason for that is simply because the light cast by scenery objects is constant, and hence, provided that the observer is not moving, the rate at which brightness changes, i.e. the delta, remains unaffected, even though the brightness itself gets skewed.
6. Appreciating the value of deltas, go the extra mile of plotting a separate chart combining the delta curve of each original brightness curve. That will yield something like the chart depicted below:
7. Looking at the delta curves, we can then ask ourselves the ultimate question: Is it possible, given a delta and current SunAlt, to deduce the proper original brightness? This is where things get somewhat trickier, albeit not outright unsalvageable. The trick is to compare the deltas during each interval independently, without looking for a magic overlapping formula. And indeed, within individual intervals, we can utilize deltas as weather condition classifiers, and as brightness predictors by extension. For instance, at nighttime (first two intervals defined above) there appears to be a direct positive correlation between delta and brightness. At dusk/dawn there is a positive correlation if deltamin <= delta <= deltamax, and a negative correlation if delta > deltamax. And so on and so forth. I won't get into excess detail about this step, for it would require me to share tons of data and charts, which frankly I'm too lazy to do right now. Plus, this is an area I'm still working on. But the main point is hopefully evident: One ought to come up with a function, that, for each of the aforementioned intervals above, takes as an input a delta and a SunAlt, and returns a value w (for "weather factor") between 0 and 1, with 0 standing for worst conditions and 1 for best ones. How simple or complex that function gets to become is solely its author's choice. It could be a trivial binary classification scheme, only accounting for a dichotomy between "best" and "worst" conditions. Or it could be an arbitrarily complex (branched) linear or perhaps even logistic mapping of its inputs.
8. With all that said and done, below I'm going to be attaching one sample algorithm depicting how the theory could be leveraged to approximate the objective brightness in practice. Pay attention to the fact that, even when impossible to compute an accurate delta at present, the last successfully acquired one can still be reused to obtain somewhat accurate results -- provided that neither the weather conditions nor the time were radically shifted in between. When the latter is the case, as well as when a vehicle first gets spawned and begins moving before a valid delta can first be captured, then the output will likely be erroneous under non-default weather conditions. But since these are both edge cases and do not occur all the time, this failure is to some extent tolerable.
Pseudo-code:
i.a. Get the current SunAlt and assign it to variable s0, unless already assigned. Get the current Envir_Brightness and assign it to variable b0, unless already assigned.
i.b. Get the current SunAlt and assign it to variable s1. Get the current Envir_Brightness and assign it to variable b1. Examine the absolute difference between s0, s1. If it's less than 0.01, then jump to step (iv.a). If it's greater than 0.3, then jump to step (iii); otherwise proceed.
i.c. Examine the absolute difference between b0, b1. If it's zero, then jump to step (iv.a). If it exceeds the greatest known valid delta for the current SunAlt interval, then jump to step (iii); otherwise proceed.
i.d. Ensure that the current velocity is either zero or greater than 10 km/h. If it's not, then jump to step (iii); otherwise proceed.
i.e. Ensure that s0, s1 lie within the same interval. If they don't, jump to step (iii); otherwise proceed.
ii.a. Compute the current delta = abs(b0 - b1) / abs(s0 - s1).
ii.b. Let w0 equal the output of your translation function with inputs (delta, s0).
iii. Unassign s0, s1, b0, b1.
iv.a. If w0 still unassigned, let w0 equal 1, provisionally.
iv.b. Let s equal the current SunAlt, b equal the current Envir_Brightness.
If bmin(s) ≤ b ≤ bmax(s), then update w1 = (b - bmin(s)) / (bmax(s) - bmin(s)).
iv.c. Let w = min(w0, w1).
iv.d. Let the approximate output brightness, beffective, equal bmin(s) + (w * (bmax(s) - bmin(s))).
-
Jup, sieht so richtig aus. Und die model.cfg Einträge hast du auch, wie in meiner ersten Antwort vorgeschlagen, angepasst? Dann bin ich ratlos.
-
Okay danke für den Tipp! Muss das in die oben genannte Script-Datei? Die heißt bei mir stringvarlist_Knopf.txt. Und das steht da jetzt erstmal drin:
Nein -- das ist Script-Code und muss deswegen in eine *.osc rein (z.B. in den cockpit_init Makro der cockpit.osc). In eine stringvarlist.txt, z.B. die cockpit_strigvarlist.txt (oder deine eigene, spielt keine Rolle), müssen hingegen bloß die Namen der neuen (prinzipiell würde auch eine einzige Variable genügen, da der Wert, also der Pfad, immer der selbe ist) Variablen hinzugefügt werden.
Und welchen Pfad muss ich da nehmen? Also ab welchem Ordner? Ich hab' da jetzt Texture\Knopf.jpg eingetragen. Nur leider funktioniert das auch noch nicht.
Alle Pfade werden als relativ zu dem Ordner betrachtet, der die original-Textur des Objektes enthält. Also in diesem Fall relativ zum Ordner Namens "Texture". Aber dieser Ordner enthält ebenfalls die neue Textur. Deswegen ist der relative Pfad zwischen Referenz-Ordner und neuer Textur ganz einfach der Dateiname der letzteren, i.e. "Knopf.jpg" (den "Texture\Knopf.jpg" würde, relativiert gegen "Texture", den Pfad "Texture\Texture\Knopf.jpg" ergeben, der wohl nicht der erwünschte ist).
-
-
Just to clarify my intentions:
I have 2 steering wheel types, which I want to switch between by clicking on them, but I also want to make them invisible just like in any other bus. The other instance is 2 cab wall types. Until a certain fleet number, type 1 was mounted. From that number onwards, type 2 was mounted, but also the older ones had their type 1 replaced with type 2. I want to make the up-to-X number buses with the 2 types of walls changeable by clicking on them. Since this was the only difference, I wouldn't want to make 2 different .bus and model.cfg files.I see. The template given above suffices for simple boolean ("yes-no", "true/false", "one-or-the-other") cases of configuration. So that would address the second case, where there are only two possible states, i.e., either wall type 1 visible, or wall type 2 visible. In the model.cfg that would look as follows (trigger and "effective" config variable renamed):
CodeFor the purpose of switching between steering wheels, on the other hand, three states are needed: { wheel type 1 visible, wheel type 2 visible, none visible ("hidden") }. That requires slightly different code to support (only trigger changed; whole sample attached, with renamed variables, for clarity's sake):
Code: model.cfgCode: cockpit.osc- '...
- {trigger:steering_wheel_type_change_or_hide}
- (L.L.cockpit_cti_initialized)
- {if}
- (L.L.steering_wheel_type_effective) 1 + s0 2 >
- {if}
- 0 s0
- {endif}
- l0 (S.L.steering_wheel_type_effective)
- {endif}
- {end}
- '...
- {macro:cockpit_init}
- ' ...
- (L.L.cockpit_cti_initialized) !
- {if}
- -1 (S.L.steering_wheel_type_cti)
- {endif}
- ' ...
- {end}
- '...
- {macro:cockpit_frame}
- ' ...
- (L.L.cockpit_cti_initialized) !
- {if}
- (L.L.steering_wheel_type_cti) -1 = !
- {if}
- (L.L.steering_wheel_type_cti) (S.L.steering_wheel_type_effective)
- {endif}
- 1 (S.L.cockpit_cti_initialized)
- {endif}
- ' ...
- {end}
So, in summary, you need:
- The same variable coupled to the [visible] constraint of all alternative [mesh]es, with a distinct constraint value for each.
- The same [mouseevent] coupled to all alternative [mesh]es.
- A trigger that handles the [mouseevent] by cycling the [visible]-coupled variable through all permissible states.
Edit: No, better disregard what I wrote about the shared [mouseevent]. Since you would also want it to work in the case where the steering wheel is hidden (steering_wheel_type_effective = 2), you would be better off attaching it to a separate object that is always visible (e.g. the steering wheel base), so as to allow the user to "recover" from the hidden state.
-
I'm afraid there can only be a single [visible] directive per [mesh]. But the variable tested in a [visible] can itself be derived from an arbitrary number of other variables and relationships between them, via scripts.
So, assuming I've understood you correctly, you want the [visible] constraint to be satisfied, i.e., the object to be displayed, when a) some .cti-variable has a certain value, at initial spawn time, or b) the user has subsequently "clicked-activated" something in-game. Here's a template on achieving that:
Code: model.cfgCode: cockpit.osc- {trigger:cockpit_my_mesh_toggle_visible}
- (L.L.cockpit_cti_initialized)
- {if}
- (L.L.my_mesh_visibility_effective) ! (S.L.my_mesh_visibility_effective)
- {endif}
- {end}
- '...
- {macro:cockpit_init}
- ' ...
- (L.L.cockpit_cti_initialized) !
- {if}
- -1 (S.L.my_mesh_visibility_cti)
- {endif}
- ' ...
- {end}
- '...
- {macro:cockpit_frame}
- ' ...
- (L.L.cockpit_cti_initialized) !
- {if}
- (L.L.my_mesh_visibility_cti) -1 = !
- {if}
- (L.L.my_mesh_visibility_cti) (S.L.my_mesh_visibility_effective)
- {endif}
- 1 (S.L.cockpit_cti_initialized)
- {endif}
- ' ...
- {end}
And some clarification on the above:
- The script where you add these fragments doesn't really matter; just pick the one that seems most relevant to the nature of your object, or create and integrate (with the *.bus-file and main script) a new one. This means that the cockpit_init fragment could reside e.g. in gearbox_init of gearbox.osc instead, or generally speaking, in the xxx_init macro of the script named xxx.osc. The same applies to the cockpit_frame fragment, which can be appended to any xxx_frame macro really. Pay attention though that the trigger block must be pasted verbatim (including its start and end tag, and retaining the same name) to the top of the file, whichever it is, before any macro occurrences.
- Principle of operation: OMSI reads the .cti-file [setvar] entries briefly after a vehicle gets spawned. There are two problems with this: First, it not exactly known when that happens. It could be during exactly the first frame after spawn, or it could be the second, or, for that matter, the thirteenth frame. The only thing known is that it doesn't occur during the init phase (which is usually the time at which you see a "preview" of the vehicle in the vehicle selection GUI). Second, once OMSI reads the .cti and assigns its specified values to the corresponding variables, the variables can no longer be reassigned by scripts. Both these reasons explain why this complex setup is needed. First we assign (in the "init" block) a value known to be invalid (-1) to the .cti-variable (my_mesh_visibility_cti). Then, once each frame, we test whether that variable has changed. If it has, then we copy it, just once, to another variable, my_mesh_visibility_effective, which is the variable coupled to the [visible] directive, and which OMSI doesn't control. Lastly, when the user clicks, we simply invert (boolean "NOT") the previous state of my_mesh_visibility_effective.
Regarding the latter half of your question: Yes, you can have arbitrarily complex relationships between .cti variables, as long as you follow the scheme presented above, i.e., a) assign initially invalid values everywhere, then b) wait for OMSI to process [setvar]s, by testing whether those initial invalid values have changed, then c) copy those variables to other variables, under your direct control, and lastly d) apply any post-processing to them instead, as often as needed (in the trivial example given above, "post-processing" simply means taking subsequent user input into account).
-
In der heizung_constfile.txt die Werte der Konstanten cabinair_A_perdoor und/oder cabinair_windowdoor_effectivity erhöhen.
-
Im "start" Trigger vernachlässigst du die atron_back Variable zurück auf 0/Boolesch falsch zu setzen. Und da du im "frame" Makro atron_back immer zuletzt prüfst, und diese immer 1/Boolesch wahr bleibt, ist es auch logisch dass attron_display immer auf 1 gesetzt wird.
So müssten die beiden Trigger aussehen:
-
Hängst du mal bitte deine gesamte modifizierte *.osc-Datei an?
-
Hallo,
Du benötigst also eine Schleife ("loop") mit einer Dauer von (20 + 20 + 15) Sekunden. Dafür könntest du z.B. a) einen zweiten Timer verwenden, der ab 0 bis (20 + 20 + 15) Sekunden zählt, wenn der erste größer als 15 ist, und dann auf 0 zurückgesetzt wird; oder b) den bestehenden so umschreiben dass er einmalig ab 0 bis (15 + 20 + 20 + 15) Sekunden zählt, und während jeder nachfolgenden Wiederholung stattdessen ab 15 beginnt.
Hier bspw. die zweite Variante:
Code- (L.L.elec_busbar_main)
- {if}
- ' Startup-Sequenz
- (L.L.Startup_Timer) (L.S.Timegap) + (S.L.Startup_Timer) s0 5 <
- {if}
- "TFT_Boot1.dds"
- {else}
- l0 13 <
- {if}
- "TFT_Boot3.dds"
- {else}
- l0 15 <
- {if}
- "TFT_Display.dds"
- {else}
- l0 15 20 + <
- {if}
- "Main_1.dds"
- {else}
- l0 15 20 20 + + <
- {if}
- "Main_2.dds"
- {else}
- l0 15 20 20 15 + + + <
- {if}
- "Main_3.dds"
- {else}
- 15 (S.L.Startup_Timer)
- "Main_1.dds"
- {endif}
- {endif}
- {endif}
- {endif}
- {endif}
- {endif}
- (S.$.Main_1)
- {else}
- 0 (S.L.Startup_Timer)
- "TFT_Display.dds" (S.$.Main_1)
- {endif}
-
Ich antworte mal, der Klarheit halber, lieber auf Englisch. Gib bitte Bescheid, falls etwas in diesen Beitrag unverständlich sein sollte, und ich werde mein bestes tun es zu übersetzen. Du kannst beliebig entweder weiterhin auf Deutsch, oder auf Englisch (aber dann bitte ohne Google-translate) antworten.
* * *
What I meant above was: "Find the location, within the engine_moment macro, where the calculation/actualization of the engine output torque (engine_M variable) has completed (i.e., the last occurrence of (S.L.engine_M)), and append lines 8-13 of the given snippet right after it".
Anyway, I tested the aforementioned patch on an actual Facelift today, to ensure it works, and added a bit more realism. The torque reduction now depends on whether a) only the driver, only the passenger, or both A/C functions are in use; b) the temperature difference between an "optimal" heating/cooling target temperature and the temperature of the environment; and c) the humidity difference, inside the cabin, between an "optimal" value and the actual current value.
Here's the revised patch (whole macro attached for clarity's sake; modified portion lies within "--- patch start ---" and "--- patch end ---" comments):
Code- {macro:engine_moment}
- ' Reaktionszeit der Einspritzpumpe
- (L.L.engine_temperature) 5 <
- {if}
- (C.L.engine_governed_idle_RPM) 100 + (S.L.RPM_Temp)
- {else}
- (C.L.engine_governed_idle_RPM) (S.L.RPM_Temp)
- {endif}
- (L.L.engine_internal_throttle) 0 =
- (L.L.engine_n) 500 > &&
- {if}
- (L.L.engine_n) (L.L.RPM_Temp) <
- {if}
- (L.L.engine_throttle_injection) (L.S.Timegap) 1 * + 1 min (S.L.engine_throttle_injection)
- {else}
- (L.L.engine_throttle_injection) (L.S.Timegap) 1 * - 0 max (S.L.engine_throttle_injection)
- {endif}
- {else}
- (L.L.engine_internal_throttle) (L.L.engine_throttle_injection) >
- {if}
- (L.L.schaltverzoegerung) 2 >
- (L.L.schaltverzoegerung_runter) 1 > &&
- {if}
- (L.L.engine_throttle_injection) (L.S.Timegap) 2 * + (L.L.engine_internal_throttle) min (S.L.engine_throttle_injection)
- {else}
- (L.L.schaltverzoegerung_runter) 1 <
- {if}
- (L.L.engine_throttle_injection) (L.S.Timegap) 2 * + (L.L.throttle) 0.85 * min (S.L.engine_throttle_injection)
- {else}
- (L.L.engine_throttle_injection) (L.S.Timegap) 2 * + (L.L.antrieb_M_restriction) min (S.L.engine_throttle_injection)
- {endif}
- {endif}
- {else}
- (L.L.engine_throttle_injection) (L.S.Timegap) 2 * - (L.L.engine_internal_throttle) max (S.L.engine_throttle_injection)
- {endif}
- {endif}
- (L.L.engine_injection_on) (L.L.engine_on) &&
- {if}
- (L.L.engine_throttle_injection) s1 (L.L.engine_n) s0 (F.L.engine_M_maxThrottle) * 1 l1 - l0 (F.L.engine_M_minThrottle) * + (L.L.engine_M_restriction) * (S.L.engine_M) s0
- {else}
- (L.L.engine_n) 1 >
- {if}
- (L.L.engine_n) (F.L.engine_n_coldM) s0
- {else}
- 0 s0
- {endif}
- {endif}
- 'Ölviskosität:
- (L.L.engine_n) 1 >
- {if}
- (L.L.engine_temperature) (C.L.engine_oelvis_M_expfactor) * exp (C.L.engine_oelvis_M_nulldeg) *
- {else}
- 0
- {endif}
- l0 + (S.L.engine_M)
- (L.L.engine_starter)
- {if}
- 'Moment exponentiell abfallend:
- (L.L.engine_n) (C.L.engine_starter_n_halbwert) / -0.69314 * exp (C.L.engine_starterM) * (L.L.elec_busbar_main) * s2 (L.L.engine_M) + (S.L.engine_M)
- 'fließender Strom:
- (L.L.elec_busbar_Rinv_summe) l2 (C.L.engine_starter_Ifaktor) * (C.L.engine_starter_minI) + 24 / + (S.L.elec_busbar_Rinv_summe)
- ' (C.L.engine_starter_n_max) (L.L.engine_n) - (C.L.engine_starter_n_max) / 0 max (L.L.elec_busbar_main) * (C.L.engine_starterM) * s2 (L.L.engine_M) + (S.L.engine_M)
- 'fließender Strom: (0.10472 = 2*PI/60)
- ' (L.L.elec_busbar_Rinv_summe) l2 (L.L.engine_n) 0.10472 * * (L.L.elec_busbar_main) (C.L.elec_Vnenn) * sqr / + (S.L.elec_busbar_Rinv_summe)
- 'Einfache Variante:
- ' (L.L.elec_busbar_Rinv_summe) 1 0.15 (L.L.engine_n) 3000 / + / + (S.L.elec_busbar_Rinv_summe)
- l2 (L.L.engine_n) 0.10472 * *
- {endif}
- ' --- patch start ---
- (L.L.engine_on) (L.L.engine_M) 0 > &&
- {if}
- (L.L.cp_dummy_sw01)
- {if}
- (L.L.cabinair_Vrate_fanheater) (C.L.cabinair_A_frontheater) s0 min l0 /
- (C.L.driver_ac_min_consumption) max
- (C.L.driver_ac_total_consumption_contribution) *
- {else}
- 0
- {endif}
- s0
- (L.L.cp_taster_klima) (L.L.cp_taster_heat_or_frost) ||
- {if}
- (L.L.cabinair_Vrate_cabinaircondition) (C.L.cabinair_A_cabinheater) s1 min l1 /
- (C.L.passenger_ac_min_consumption) max
- (C.L.passenger_ac_total_consumption_contribution) *
- {else}
- 0
- {endif}
- s1
- l0 l1 + s0
- {if}
- (L.S.Weather_Temperature) s1
- (L.L.Cabinair_Temp) (C.L.ac_ideal_temperature) s2 <
- {if}
- l1 l2 min
- {else}
- l1 l2 max
- {endif}
- l2 - abs (F.L.ac_consumption_f_temperature_deviation)
- (C.L.ac_heating_cooling_total_consumption_contribution) * s1
- (L.L.Cabinair_relHum) (C.L.ac_ideal_rel_humidity) -
- (F.L.ac_consumption_f_humidity_deviation)
- (C.L.ac_dehumidification_total_consumption_contribution) * s2
- l0 l1 l2 + * (C.L.ac_min_consumption) max (F.L.engine_M_f_ac_consumption)
- (L.L.engine_M) * (S.L.engine_M)
- {endif}
- {endif}
- ' --- patch end ---
- {end}
And here are the accompanying const-file entries:
Code- [const]
- driver_ac_min_consumption
- 0.2
- [const]
- driver_ac_total_consumption_contribution
- 0.2
- [const]
- passenger_ac_min_consumption
- 0.2
- [const]
- passenger_ac_total_consumption_contribution
- 0.8
- [const]
- ac_ideal_temperature
- 22
- [newcurve]
- ac_consumption_f_temperature_deviation
- [pnt]
- 3
- 0.2
- [pnt]
- 6
- 0.8
- [pnt]
- 15
- 1
- [const]
- ac_heating_cooling_total_consumption_contribution
- 0.8
- [const]
- ac_ideal_rel_humidity
- 0.5
- [newcurve]
- ac_consumption_f_humidity_deviation
- [pnt]
- 0.1
- 0.05
- [pnt]
- 0.3
- 0.8
- [pnt]
- 0.5
- 1
- [const]
- ac_dehumidification_total_consumption_contribution
- 0.2
- [const]
- ac_min_consumption
- 0.01
- [newcurve]
- engine_M_f_ac_consumption
- [pnt]
- 0
- 1
- [pnt]
- 1
- 0.8
And a brief explanation on what they stand for:
- driver_ac_min_consumption, passenger_ac_min_consumption: Minimum power, expressed as a ratio (0 < x < 1), that each function can consume. The values reflect a "best-case" scenario, where the corresponding function is active but (almost) idle (because for example the temperature is already close or equal to the "optimal" value).
- driver_ac_total_consumption_contribution, passenger_ac_total_consumption_contribution: Maximum power, expressed as a ratio, that each function can consume. The sum of these constants must equal 1.
- ac_ideal_temperature: If the cabin temperature exceeds this value, then we assume that the A/C is being used for cooling; otherwise we assume that it is being used for heating.
- ac_ideal_rel_humidity: The equivalent of (3) for humidity.
- ac_consumption_f_temperature_deviation: This curve expresses power consumption as a function of deviation (positive and negative alike) of environmental temperature from (3). Input is in degrees. Output is a ratio.
- ac_consumption_f_humidity_deviation: The equivalent of (5) for relative humidity.
- ac_heating_cooling_total_consumption_contribution, ac_dehumidification_total_consumption_contribution: Maximum power, expressed as a ratio, that both functions combined can consume for, respectively, temperature control and humidity control. The sum of these constants must equal 1.
- ac_min_consumption: Equivalent to (1) for all facets of A/C functionality combined.
- engine_M_f_ac_consumption: Torque as a function of power consumption by all facets of A/C functionality combined. Input is torque as a ratio (0 < x < 1). Output is updated torque, once again expressed as a ratio. Thus, (input - output) represents the loss due to A/C usage.
-
Ist es evtl. möglich, dem Script zu sagen, dass de Tatsächliche Motorleistung der Motorleistung abzüglich der Stufe Der Klimaanlage (hochgerechnet auf 0-40PS bzw. Drehmomentverlust) entspricht?
Eine extrem primitive (und entsprechend unrealistische) Lösung, wäre, in der engine.osc:engine_moment Makro, nachdem das Motordrehmoment zuletzt aktualisiert wurden ist, zu prüfen ob die Klimaanlage gerade am laufen ist, und falls sie es tut, das Drehmoment in Abhängigkeit von ihrer "Betriebsintensität" (z.B. aktueller Luftvolumenstrom als Prozent des höchstmöglichen) zu reduzieren:
Code- {macro:engine_moment}
- ...
- ' ... Berechnung des Motordrehmomentes ...
- ... (S.L.engine_M)
- ' Wenn Klimaanlage aktiv und Drehmoment positiv (sonst Motorbremse -- die wollen wir nicht beeinflussen)...
- (L.L.cabinair_Vrate_cabinaircondition) 0 > (L.L.engine_M) 0 > && (L.L.engine_on) &&
- {if}
- ' ...dann Drehmoment relativ zum Zustand der Klimaanlage reduzieren
- (L.L.engine_M) (L.L.cabinair_Vrate_cabinaircondition) (C.L.cabinair_A_cabinheater) / (F.L.engine_M_ac_reduction) * (S.L.engine_M)
- {endif}
- ...
- {end}
Die Funktion zwischen Volumenstrom (%) und Drehmomentverlust (%) kann man sich frei erfinden:
Display MoreDie ursprünglich beschriebene korrekte(re) Lösung (Stromverbrauch ~= Drehmomentverlust) wäre dagegen recht kompliziert zu implementieren. Eine gewisse Vertrautheit mit der ganzen Mechanik wäre erforderlich, sowie viel Zeit/Geduld um alle relevanten Abschnitte des Busbar-Systems (Kupplung zwischen engine.osc und elec.osc, sowie "Verbraucher-Logik" in lights.osc und heizung.osc) anzupassen.