Jump to content

MechJeb Autom8 Scripts Megathread


r4m0n

Recommended Posts

Thank you to the Mechjeb team for both Mechjeb, and releasing the Autom8 lua interface! That's very much something I'm enjoying.

In the hopes that this is useful to some of the other script kerbals out there, I'm hereby releasing a set of three lua scripts/pseudo-libraries, licensed under your choice of GPLv2, GPLv3, or Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) http://www.gnu.org/licenses/gpl-2.0.html or http://www.gnu.org/licenses/gpl.html or http://creativecommons.org/licenses/by-sa/3.0/

All functions have extensive comments regarding how to use them, and there are help functions in all three files to make essentially the same information available when using the code.

SimpleOrbitalMechanics 0.002 (http://pastebin.com/eZkL9wW7) is just that - orbital mechanics. It can be run in any lua environment (including lua for your OS), and all it does it orbital math. Well, and it knows a few facts regarding a few celestial bodies (Earth, Kerbin, Mun, Minmus). It has functions to calculate the semi-major axis, calculate desired Apoapsis and Periapsis values, calculate sidereal orbital periods, calculate orbital velocities, and calculate u (GM, the standard gravitiational parameter) - which it can use to guess which body your orbit must be around. There are also functions to calculate whether an orbit is stable (above the atmosphere, below the end of the Hill sphere [of influence]), to calculate Apoapsis and Periapsis for a particular orbital period, and a specific function to calculate Molniya orbits. Additionally, it has a reasonably capable test harness, so you can do a test and see if it's returning the expected results.


-- Function headings:
globalSomOverallInit()
globalSomMainBodyReset(MainBodyName)
calcSomSemiMajorAxisOrbitingSphereFromApPeMbr(Ap, Pe, MainBodyRadius)
calcSomPeorapFromaAporpeMbr(a, Aporpe, MainBodyRadius)
calcSomSiderealOrbitalPeriodFromaGm(a, GM)
calcSomSemiMajorAxisFromSopGm(SiderealOrbitalPeriod, GM)
calcSomGMFromaSop(a, SiderealOrbitalPeriod)
calcSomSiderealOrbitalPeriodFromApPeMbrGm(Ap, Pe, MainBodyRadius, GM)
calcSomOrbitalVelocityFromaGmRfcb(a, GM, RadiusFromCentralBody)
calcSomOrbitalVelocityFromaGmAltaslMbr(a, GM, AltitudeASL, MainBodyRadius)
calcSomGMFromaOvRfcb(a, OrbitalVelocity, RadiusFromCentralBody)
calcSomGMFromaOvAltaslMbr(a, OrbitalVelocity, AltitudeASL, MainBodyRadius)
guessSomWhatBodyIsTheMainBodyFromaOvAltaslMoe(a, OrbitalVelocity, AltitudeASL, MarginOfError)
calcSomPeorapFromAporpeMbrGmSop(Aporpe, MainBodyRadius, GM, SiderealOrbitalPeriod)
calcSomMolniyaPeorapFromAporpeMbrGmSrp(Aporpe, MainBodyRadius, GM, SiderealRotationalPeriod)
calcSomApPeFromAporpePeorap(Aporpe, Peorap)
calcSomMolniyaApPeFromHsoiMsaMbrGmSrpMoe(HillSphereOfInfluence, MinStableAltitude, MainBodyRadius, GM, SiderealRotationalPeriod, MarginOfError)
isSomOrbitStableFromApPeHsoiMsa(Ap, Pe, HillSphereOfInfluence, MinStableAltitude)
calcSomDeltaVFromIspTsmTem(Isp, TotalStartingMass, TotalEndingMass)
calcSomIspFromTsmTemDv(TotalStartingMass, TotalEndingMass, DeltaV)
testSomTestHarness()
helpSomSimpleOrbitalMechanics1()
helpSomSimpleOrbitalMechanics2()
helpSomSimpleOrbitalMechanics3()
helpSomSimpleOrbitalMechanics4()
helpSomSimpleOrbitalMechanics5()

Notably lacking are Delta-V predictions for specific orbital changes - what I could find of the vis-viva equations were mostly simplified for circular orbits, and I want to implement the general case if possible, not a specific case.

SimpleKSPOrbitalMechanics 0.003 (http://pastebin.com/fvD6hK1h) is pretty sparse, since KSP already implements simple orbital mechanics properly in the first place. It has functions that automatically use the vessel.X values to guess which planet you're orbiting (or on), to print a fair bit of that vessel.X information to the Autom8 screen, to calculate stable Molniya orbits around whatever celestial body you're orbiting, to check if your current orbit is stable, and to report on orbital and mass variables instantaneously as well as the changes over a specified number of seconds.


-- Function headings
globalSkomKSPMainBodyResetBasedOnGuessing()
guessSkomKSPWhatBodyIsTheMainBodyCurrentlyBeingOrbited()
function calcSkomMolniyaApPeFromMainBodyCurrentlyBeingOrbitedFromMoe(MarginOfError)
function printSkomKSPCurrentOrbitalElements()
function reportSkomCurrentMsMsdApPeSopTmapTmpeLanAopIncEccAOvSvVvHvHdPiRlAltaslAlttruAltbotLatLngRfcbGAtmdTm()
function reportSkomCurrentChangeOverTimeMsiMsfMsMsdApPeSopTmapTmpeLanAopIncEccAOvSvVvHvHdPiRlAltaslAlttruAltbotLatLngRfcbGAtmdTmFromTmbiTmbtwnDriver(TimeBeforeInitial, TimeBetween)
function printSkomCurrentChangeOverTimeMsiMsfMsMsdApPeSopTmapTmpeLanAopIncEccAOvSvVvHvHdPiRlAltaslAlttruAltbotLatLngRfcbGAtmdTmFromTmbiTmbtwnDriver(TimeBeforeInitial, TimeBetween)
coprintSkomCurrentChangeOverTimeMsiMsfMsMsdApPeSopTmapTmpeLanAopIncEccAOvSvVvHvHdPiRlAltaslAlttruAltbotLatLngRfcbGAtmdTmFromTmbiTmbtwn(TimeBeforeInitial, TimeBetween)
isSkomCurrentOrbitStable()
printSkomKSPCurrentVesselInfo()
helpSkomSimpleKSPOrbitalMechanics1()
helpSkomSimpleKSPOrbitalMechanics2()
helpSkomSimpleKSPOrbitalMechanics3()
helpSkomSimpleKSPOrbitalMechanics4()

SimpleKSPOrbitalOperations 0.002 (http://pastebin.com/Vsdbth2h) is, so far, similar to but a little more generic than what we've seen already by other users - one function to launch a ship from the ground into a specific orbit (by Apoapsis, Periapsis, and Inclination), and a second script that automatically launches into a Molniya orbit at the chosen inclination (63.4, 116.6, -63.4, -116.6), if one is available (Kerbin and the Mun, at least, can have Molniya orbits). Functions are available to show a ship's actual, tested Isp (Specific Impulse), DeltaV per kg fuel, and DeltaV per second at various thrusts - this is an amazing test of the 0.16 fuel consumption bug:


-- Put the three .lua files in your PluginData\mumechlib directory
-- in the Autom8 window from a vessel in a stable elliptical or circular orbit around any body, copy and paste:
require "SimpleKSPOrbitalOperations"
cotestSkooIspFromTmbiTmbtwnNsMpcs(0.5, 0.5, 4, 0.02)
-- then hit Enter or click Execute


-- Function headings
launchSkooFromApPeInc(Ap, Pe, Inclination)
launchSkooMolniyaFromIncMoe(Inclination, MarginOfError)
colaunchSkooFromApPeInc(Ap, Pe, Inclination)
colaunchSkooMolniyaFromIncMoe(Inclination, MarginOfError)
measureSkooIspFromTmbiTmbtwnNsDriver(TimeBeforeInitial, TimeBetweenEach, NumberSlices)
testSkooIspFromTmbiTmbtwnNsMpcsDriver(TimeBeforeInitial, TimeBetweenEach, NumberSlices, MaxPointingChangeStable)
cotestSkooIspFromTmbiTmbtwnNs(TimeBeforeInitial, TimeBetweenEach, NumberSlices)
cotestSkooIspFromTmbiTmbtwnNsMpcs(TimeBeforeInitial, TimeBetweenEach, NumberSlices, MaxPointingChangeStable)
helpSkooSimpleKSPOrbitalOperations1()
helpSkooSimpleKSPOrbitalOperations2()

Next on the agenda, if I can get them working: Orbit phase changes for those that want constellations!

I've also attached them, for anyone who doesn't want to use the Pastebin links.

P.S. No, I've never touched lua before in my life. Why do you ask?

P.P.S. No, I really don't know if the sidereal rotational period of the Mun is 41, 38... or 39... hours - I see a note about being tidally locked in the wiki, and then I see that the sidereal and planetary rotation periods are different, so I'm confused.

EDIT: 20120827 Updated Som and Skom to 0.002 - added real life Moon data, delta-V based on Tsiolkovsky rocket equation and Isp (specific impulse), useful constants, minor renaming of Period to SiderealOrbitalPeriod, added more Autom8 variables to the Skom print... functions.

EDIT: 20120904 Updated Skom to 0.003 and Skoo to 0.002 - added KSP based isOrbitStable, reporting on orbital and mass variables instantaneously and over time(!), and operational testing of actual Isp at various thrust settings. Skoo now has functional code to detect when mechjeb.attitudeTo() has finished pointing.

Older versions are at:

SimpleOrbitalMechanics 0.001 (http://pastebin.com/YDdSA37H)

SimpleKSPOrbitalMechanics 0.001 (http://pastebin.com/yQ09yHJi)

SimpleKSPOrbitalMechanics 0.002 (http://pastebin.com/8zcahtTB)

SimpleKSPOrbitalOperations 0.001 (http://pastebin.com/s5KQg8fu)

Edited by Nadrek
Updated Orbital Mechanics pastebins to 0.003
Link to comment
Share on other sites

You can't use C functions is the Lua console directly. If all you want to do is to pause the script for a given time, use the provided wait(ms) function.

Thank you.

For C functions, what I meant to say was can we include (require "xxx") Lua libraries that are wrappers to C libraries - there appear to be very few pure lua libraries to do real math available.

When I tried the hand-typed experiment, in the Autom8 console, of:


do print(vessel.time) wait(2) print(vessel.time) end

The entire game froze for 2 seconds, and then I had two identical timestamps in the display.

Link to comment
Share on other sites

When I tried the hand-typed experiment, in the Autom8 console, of:


do print(vessel.time) wait(2) print(vessel.time) end

The entire game froze for 2 seconds, and then I had two identical timestamps in the display.

To avoid the game freezing, take a look at the coroutine implementation in the scripts linked in the first post. Currently, the autom8 lua console runs on the same thread as the main game. Using the coroutine workaround, your Lua code that uses the wait() function can be offloaded into a separate thread, which allows the game to continue running as the script waits - this is used extensively in my Mun return and shuttle landing scripts.

Link to comment
Share on other sites

I've also been trying to work out how to do delta v calcs given the limited info available.

Well, if you can help with an equation that works for any mix of circular, elliptical, parabolic and hyperbolic orbits, perhaps we can work something out together. Equation or equations which don't assume at least one orbit is circular are what I haven't found (or noticed I'd found) yet.

Link to comment
Share on other sites

Hey What am I doing wrong?


> dofile("KminO")
Usage: KMinO(alt, malt)
alt is Kerbin Orbit Altitude in meters
malt is Minmus Orbit Altitude in meters
Warning: Insure that you do not transect Mun.
> KminO(99978,75000)
Exception: Invoke function call on non function value.

Link to comment
Share on other sites

The dV formula's I know are all about transfering mass to energy. This means moving fuel to thrust. MJ can't tell how much fuel you have or how much you're burning. :(

What I actually was talking about was "dV required" equations; i.e. to move from a 125km Pe, 500km Ap orbit to a 125km Pe, 750km Ap orbit, what dV will be required?

i.e. http://www.enotes.com/topic/Bi-elliptic_transfer has some equations based on orbit changes irrespective of the vessel doing so, but again, a brief glance shows "initial circular orbit with radius r0", which indicates a simplification has been done that I don't want (circular orbits only). Likewise, http://en.wikipedia.org/wiki/Hohmann_transfer_orbit uses circular orbit based equations, i.e. "r1 and r2 are, respectively, the radii of the departure and arrival circular orbits".

Note that this is going to end up as the same math Mechjeb uses internally to tell you how much dV will be required for a given manuever.

Link to comment
Share on other sites

To the author:

Thank you again for creating this - it's very much something I like working with.

I do have a few requests for future versions:

1) mechjeb.warpToEvent with "instant" as an option, so only the optional lead time in seconds is used (i.e. warp (amount of time))

2) mechjeb.warpToEvent Ascending Node and Descending Node, for inclination change manuevers

3) Ideally, some way of determining where other objects are - the Mun, other craft or debris, and their orbital parameters so we can work out the rendevous/intercept/orbit phase math ourselves.

4) mechjeb.launchToApogee - do the launch to inclination at an apogee, but do not circularize.

5) Better instructions on how to use mechjeb.attitudeTo - is it instant or sustained, and if sustained, how do we turn it off?

Link to comment
Share on other sites

What I actually was talking about was "dV required" equations; i.e. to move from a 125km Pe, 500km Ap orbit to a 125km Pe, 750km Ap orbit, what dV will be required?

...

Note that this is going to end up as the same math Mechjeb uses internally to tell you how much dV will be required for a given manuever.

I see. I was hoping to find out how much dV a craft has at a given point in time. This would help a pilot know what maneuvors are an option and what are not. In Kerbin orbit and want to do a Mun/Minmus slingshot? Check your current dV and see if its even possible. That sort of thing.

Link to comment
Share on other sites

> 5) Better instructions on how to use mechjeb.attitudeTo - is it instant or sustained, and if sustained, how do we turn it off?

It's just a direction facing. You still need to adjust throttle for the required time period. That time period depends on what you're trying to achieve. I've used attitudeTo in my most recent script posted above. It's not a maneuver - its a facing/heading.

Link to comment
Share on other sites

I see. I was hoping to find out how much dV a craft has at a given point in time. This would help a pilot know what maneuvors are an option and what are not. In Kerbin orbit and want to do a Mun/Minmus slingshot? Check your current dV and see if its even possible. That sort of thing.

We're working on opposite ends of the problem, then. I want to calculate dV required for arbitrary operations, and you want to calculate dV remaining.

I'd advise you to create the pure math functions first, in the most general way possible. That way, you have options:

1) You can have the user enter the amount of fuel left (in kg, available by using the GUI to right-click fuel tanks one at a time and then using another general function to convert X type of fuel from liters to kg) as a temporary bandaid.

2) Once fuel is available, you can easily create a shell function like the ones in my SimpleKSPOrbitalMechanics that automatically determines those values in the units you need, and passes them in to the mathematical function you already wrote.

3) The real future fun will be figuring out fuel per stage and mass per stage, for accurate calculations on multi-stage vessels.

Link to comment
Share on other sites

Hi,

Frist of all thanks for that excellent addon. At first i thought that automat8 and all these autopilots are mere "cheats" but after some testing i am convinced it should be a core part of the game as it is not simply a "push a button and land on the mun" software. Excellently balanced Addon.

What i wonder though is: how do i change the orbiting direction. As of now i can only orbit in a 90° angle and follow the equator. I tried setting heading/inclination in the take off autopilot and in an automate script, but i always keep circling above the equator.. do i miss something or is there maybe some bug?

As script i simply use the line " mechjeb.launchTo(100000, 78) " but this seems not to work... any ideas?

Link to comment
Share on other sites

There is another script, this one to fly VTOL mun land/start Spaceplane to KSC /Horizontal Land tnere/.

it is better to start it when is KSC on oposite side of kerbin from Muun - but not neceseary should be abel land in any start time.

http://pastebin.com/gSDNG3Bm

Parameters is Pe for areobraking /set to value that get you to low Kerbin orbit - depend on drag and gliding capabity/

Landing offset /set distance in km before KSC for deorbit Landing Autopilot depend on gliding capapility of space plane/

There is posibility to warp manualy on Muun parking orbit but must manualy stop before Equator /at least 1 degree/ and Muun escape point /-120 N/.

Link to comment
Share on other sites

Okay, first of all, let me give all of you a huge applause for what you've created. Especially the Shuttle-landing script is extremely useful...or I suppose it could be and that's why I'm writing this post ;)

To test the script (and spaceplanes in general) I've built a really small, simple shuttle. It's a good glider and it can actually fly, I tested that out.

I then shot it into orbit and tried to return it using the script. I tried it three times but every single time I got this:

Coroutine exception: InvalidOperationException - out of sync

at System.Collections.Generic.Dictionary`2+Enumerator[sharpLua.LuaTypes.LuaValue,SharpLua.LuaTypes.LuaValue].VerifyState () [0x00000] in <filename unknown>:0

at System.Collections.Generic.Dictionary`2+Enumerator[sharpLua.LuaTypes.LuaValue,SharpLua.LuaTypes.LuaValue].MoveNext () [0x00000] in <filename unknown>:0

at System.Collections.Generic.Dictionary`2+KeyCollection+Enumerator[sharpLua.LuaTypes.LuaValue,SharpLua.LuaTypes.LuaValue].MoveNext () [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetKey (System.String key) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetValue (System.String name) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetValueFromMetaTable (System.String name) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetValue (System.String name) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetValueFromMetaTable (System.String name) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaTable.GetValue (System.String name) [0x00000] in <filename unknown>:0

at SharpLua.AST.VarName.Evaluate (SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.PrimaryExpr.Evaluate (SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.Operation.InfixBinaryOperation (SharpLua.AST.Term LeftOperand, System.String Operator, SharpLua.AST.Term RightOperand, SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.Operation.Evaluate (SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.Chunk.<Execute>m__6 (SharpLua.AST.Expr expr) [0x00000] in <filename unknown>:0

at System.Collections.Generic.List`1[sharpLua.AST.Expr].ConvertAll[LuaValue] (System.Converter`2 converter) [0x00000] in <filename unknown>:0

at SharpLua.AST.Chunk.Execute (System.Boolean& isBreak) [0x00000] in <filename unknown>:0

at SharpLua.AST.Chunk.Execute () [0x00000] in <filename unknown>:0

at SharpLua.AST.FunctionBody+<Evaluate>c__AnonStorey8.<>m__A (SharpLua.LuaTypes.LuaValue[] args) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaFunction.Invoke (SharpLua.LuaTypes.LuaValue[] args) [0x00000] in <filename unknown>:0

at SharpLua.Library.BaseLib.Wait (SharpLua.LuaTypes.LuaValue[] args) [0x00000] in <filename unknown>:0

at SharpLua.AST.FunctionCall.Evaluate (SharpLua.LuaTypes.LuaValue baseValue, SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.PrimaryExpr.Evaluate (SharpLua.LuaTypes.LuaTable enviroment) [0x00000] in <filename unknown>:0

at SharpLua.AST.ExprStmt.Execute (SharpLua.LuaTypes.LuaTable enviroment, System.Boolean& isBreak) [0x00000] in <filename unknown>:0

at SharpLua.AST.Chunk.Execute (System.Boolean& isBreak) [0x00000] in <filename unknown>:0

at SharpLua.AST.Chunk.Execute () [0x00000] in <filename unknown>:0

at SharpLua.AST.FunctionBody+<Evaluate>c__AnonStorey8.<>m__A (SharpLua.LuaTypes.LuaValue[] args) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaFunction.Invoke (SharpLua.LuaTypes.LuaValue[] args) [0x00000] in <filename unknown>:0

at SharpLua.LuaTypes.LuaCoroutine+<Resume>c__AnonStoreyD.<>m__2F () [0x00000] in <filename unknown>:0

Once it happened shortly after the reto burn began, two other times it happened at about 50'000 m during re-entry. The ILS-Autoland function could still land the plane after I turned it on manually, but it started about 60 km away from KSC so it took me quite a while to get back to ground.

This error doesn't only happen with this script, I also encoutered it with the Kerbin return script, but that one worked about 80% of times while the lander script doesn't seem to work for me at all.

Is there something wrong with the script(s) or am I doing something wrong?

Link to comment
Share on other sites

This error happens a lot, it is known, and nothing is found yet we can do about it.

It appears to stem from the fact that the script thread is running in parallel to the game thread, and during the waiting loops, as variables from the game thread are accessed to check if the wait needs to be ended, a sync exception happens (meaning that the variable was written to at the same time it was read or something similar). Since the multithread solution is a workaround already (without it the wait() function would freeze the whole game outright), there's nothing we know of that could be done about it.

Link to comment
Share on other sites

There is another script, this one to fly VTOL mun land/start Spaceplane to KSC /Horizontal Land tnere/.

it is better to start it when is KSC on oposite side of kerbin from Muun - but not neceseary should be abel land in any start time.

http://pastebin.com/gSDNG3Bm

Parameters is Pe for areobraking /set to value that get you to low Kerbin orbit - depend on drag and gliding capabity/

Landing offset /set distance in km before KSC for deorbit Landing Autopilot depend on gliding capapility of space plane/

There is posibility to warp manualy on Muun parking orbit but must manualy stop before Equator /at least 1 degree/ and Muun escape point /-120 N/.

I looked at your script, and I noticed that you know commands that I do not - mechjeb.thrustActivate(10), mechjeb.controlRelease(), and mechjeb.stage() are not on the Autom8 wiki page I was using as a reference, much less ils = mechjeb.getModule("ils") ils.glideslope = slope - how did you find them - read the source code for Mechjeb, or some other way?

Link to comment
Share on other sites

This script started out as what I thought would be a <i>trivial</i> modification of olex's Mun to Kerbin Return script. Well there is no such thing as a <i>trivial</i> mod to someone else code! I did have a "yeah" moment when I was finally coasting to Mun escape with fuel, but that didn't last. I found out what olex was refering to as fine tuning when I ended up back in Mun orbit. I know how to return from Mun, but I needed to start fresh. So HomeJeb started.

The script is not optimal. Longitude is not yet available (neither vessel.longitude nor vessel.Longitude worked) and I don't know how to kill time warp. This is where you come in. You need to manually "abort" the time warp at the deorbit burn point. These are are -45 degrees longitude for Mun and +20 degrees longitude for Minmus. Neither value is critical or for that matter even optimal, but they work well. Longitude is at the bottom of the "surface info" screen.

Notes:

The script assumes your ship has sufficient fuel and thrust to get back to Kerbin. If you run out of fuel it just stops.

There is one scenario I'm aware of that will cause you to crash. If you run out of fuel just before landing and without enough altitude to deploy your chute you will crash. Easy fix, if it looks like this may happen stage to your chute.

<font color="red">Warning:</font> The script sometimes returns a coroutine error - out of sync. I think I understand what this means but I have no clue how to fix it. Fortunately it's intermittent, so quick save before starting script.

<a href="http://pastebin.com/Bj0eC7P2">HomeJeb</a> on pastebin. I'm also attaching a zip file.

<a href="

">Video</a>

Usage:

Enter dofile("homejeb")

Enter Home()

Edited by Jontu
Change Minmus deorbit burn point
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...