Let’s start at the beginning. Strictly speaking, there is no such thing as a “Markdown table,” because John Gruber never implemented a table syntax. What I, and most people, call the “Markdown table” syntax is a common extension to the basic Gruber syntax. It was popularized by Fletcher Penney in his MultiMarkdown processor, although I believe it was Michel Fortin’s PHP Markdown Extra that was the first to include it.
The syntax uses a set of pipe (|) characters to separate the columns and a row of dashes with optional colons to separate the header from body of the table and to set the alignment of the columns. Here’s an example:
| Column 1 | Column 2 | Column 3 |
|--|:--:|--:|
| first | second | third |
| column | column | column |
| left | center | right |
The leading and trailing pipe characters are optional, but I prefer to include them. When processed, the code above turns into a nice HTML table, like this:
Column 1 | Column 2 | Column 3 |
---|---|---|
first | second | third |
column | column | column |
left | center | right |
As you can see, the Markdown code for a table can be messy. It’s easy to lose track of which column you’re working on because the contents of the table cells have different lengths and the pipe characters don’t line up with each other.
Veteran Markdown table users like me have written scripts that allow us to create our tables in a spreadsheet, where the columns line up automatically, copy them them into a text editor, and convert the tab-separated text that comes from the spreadsheet into Markdown format. What TableFlip does is turn that two- to three-step process into a single step without any need to invoke a script.
Here’s TableFlip:
As you can see, it looks just like a spreadsheet. You can set the column alignment by clicking one of the buttons on the right side of the toolbar. Other buttons let you insert and delete rows and columns, just like a regular spreadsheet application. Documents created in TableFlip are plain text files with the tables in nicely formatted Markdown. The table shown in the screenshot above is saved in this format:
| Element | Grade B | Grade C |
| :--------- | ------: | ------: |
| Carbon | 0.260 | 0.230 |
| Manganese | -- | 1.350 |
| Phosphorus | 0.035 | 0.035 |
| Sulphur | 0.200 | 0.200 |
As you can see, TableFlip adds spaces to the columns to get the pipe characters to line up and make the text form of the table easy to read.
What’s even better, though, is that TableFlip isn’t limited to files that contain only Markdown tables. Any Markdown file can be opened in TableFlip, and it will find and display for editing the tables within that file. Changes made to the source document in a text editor are reflected in TableFlip; changes made to the tables in TableFlip are reflected in the text editor.
What if you’ve been writing a Markdown file and want to insert a table without typing any of those nasty pipe characters? Can TableFlip help you do that? Yes. If you open an existing Markdown file that has no tables in TableFlip, you’ll see this screen, which gives you an empty stub table to copy and paste into your document.
After you’ve done this a few times, I suspect you’ll learn to just type a pair of pipes wherever you want to put a table.
So after all this praise of TableFlip, why don’t I want to use it? Several reasons, some of which are related to its user interface, some to its functionality, and some to my peculiar tastes in formatting.
On the user interface side, the font size is just a bit too small, and TableFlip has no way to increase it. This is a known problem, and Christian Tietze, TableFlip’s developer, plans to fix it, but until it’s fixed, my 56-year-old eyes find it difficult to use.
Another user interface annoyance is the inability to select more than one cell at a time. TableFlip columns are left-aligned by default, and it’s very common for me to want to change the alignment of several of them after I’ve typed in the data. The natural thing to do would be to drag across the columns I want to change (or to shift-click or command-click to extend a selection) and then click the desired alignment button in the toolbar. But because only one cell can be selected, I’m forced to change the change the alignment one column at a time. This is very unnatural, as no real spreadsheet—and I’ve been using spreadsheets for 30 years—works this way.
On the functionality side, TableFlip doesn’t support two Markdown table features that I use often: multiple header rows, and headers that span multiple columns. Here’s an example with both: as source code,
| | Tensile strength ||
| Grade | ksi | MPa |
|:-----:|:-----------:|:---:|
| B | 58 | 400 |
| C | 62 | 427 |
and as a rendered table.^{1}
Tensile strength | ||
---|---|---|
Grade | ksi | MPa |
B | 58 | 400 |
C | 62 | 427 |
I don’t think PHP Markdown Extra supports either of these extensions (in fact, I cheated and wrote HTML directly to get the rendered table above), but MultiMarkdown has both and I use them a lot in the reports I write for work. The TableFlip roadmap shows that these are planned, but because they aren’t available now, I’m forced to do a lot of hand-editing to get what I want.
TableFlip can get confused when reading complicated Markdown documents. In the source file for this page, for example, the single pipe character in the third paragraph caused TableFlip to think that paragraph was a table.
The “tables” that are actually rendered as source code are a further source of confusion.
This is probably not a problem that would arise with most people, but it does if you write examples and explanations of Markdown.
On matters of taste, look again at how TableFlip saves that table of chemistry limits for A500 steels:
| Element | Grade B | Grade C |
| :--------- | ------: | ------: |
| Carbon | 0.260 | 0.230 |
| Manganese | -- | 1.350 |
| Phosphorus | 0.035 | 0.035 |
| Sulphur | 0.200 | 0.200 |
Although the second and third columns are to be right-aligned, TableFlip displays them as left-aligned. I know this only source code and it doesn’t affect the rendered output, but if you’re going to format the source code, format it according to the indicated alignment. Even my script can do that.
| Element | Grade B | Grade C |
|:-----------|--------:|--------:|
| Carbon | 0.260 | 0.230 |
| Manganese | -- | 1.350 |
| Phosphorus | 0.035 | 0.035 |
| Sulphur | 0.200 | 0.200 |
Tietze has big plans for TableFlip, and I hope he follows through with them. I’d like to have a professionally written app that can handle the kinds of tables I need to make. But right now, I’m sticking with Numbers, my formatting scripts, and the workflows I’ve used for years.
And I see now that my CSS stylesheet never anticipated multiple header lines. That thick horizontal line between them looks stupid. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>Round function now always rounds half upwards to the nearest integer.
Blasphemy! I cried. For is it not written in that most holy of floating point standards, that one should round halves to even?^{1}
Perhaps the release notes were wrong. I opened PCalc and began testing.
I got on the Twitter and shot off a direct message to PCalc’s developer, James Thomson, asking, in effect, WTF? His reply was pretty much what I expected. He’d been getting complaints from people who expected (for positive numbers, anyway) that halves would always be rounded up.
This is an all-too-common belief, instilled in children by parents and elementary school teachers who were taught it by previous generations of misguided souls. You may believe it yourself; I certainly did until I became enlightened sometime in grad school.
The problem with always rounding halves up is that in doing so, you introduce a persistent bias in whatever calculations you do with the rounded number. If you’re adding a list of rounded numbers, for example, the sum will be biased high.^{2}
If you round halves to the nearest even number, though, the bias from upward roundings tends to be negated by an equal number of downward roundings.^{3} Overall, you get better results.
James expected the rounding change to raise hackles, and he was thinking about how to provide rounding options before I DM’d him. PCalc 3.6.2, released today, is the result. There’s a new Rounding item in the Advanced Settings. Tapping it gives you these six choices:
The top option is what the great unwashed expect. The second is the One True Rounding. The others are specialized options that are often needed when doing integer calculations. The floor and ceiling roundings, for example, get used in things like the Doomsday Algorithm.
PCalc’s “round” function rounds to integers, but rounding also applies when you have the display set to show a limited number of decimal places.
With Nearest or Even rounding and two decimal places chosen, the numbers ⅛, –⅛, ⅞, and –⅞ will display like this:
Note that although this display rounding follows the same rule as the round function, the numbers in the display still retain, behind the scenes, all their digits. Therefore, if we enter ⅛, we’ll see 0.12 in the display, but the number is really 0.125. Multiplying by 2 will give us 0.25, not 0.24. This differs from the round function, which really does change whatever number it’s applied to into an integer.
I was perfectly happy with PCalc’s old behavior, which always rounded halves to even, but, shockingly, James has to consider the needs and wants of customers other than me. Now there’s rounding for everyone.
Yes, IEEE 754 does define other rounding rules, but round to nearest, ties to even is the default. ↩︎
I’m assuming positive numbers in this example. When numbers come from measurements, that’s the most common case. ↩︎
If you’re thinking Benford’s Law screws up the notion that there will be an equal number of upward and downward roundings, think again. Benford’s Law applies to the most significant digit; rounding is done to the least significant digit. Only if you’re rounding to one digit will Benford’s Law lead to significant bias. And even then, rounding halves to even is still less biased than rounding them up. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>Every review of Castro spent most of its time talking about the inbox, and rightly so. If you’re the kind of person who subscribes to many podcasts, but doesn’t have the time to listen to every episode, the inbox is a great way to swiftly look through your available episodes, queue up those that look the most interesting, and get rid of those that you’ll never get around to.
Here’s my inbox as of a few minutes ago:
Tapping on an episode brings up the dispatch buttons.
You can either
One of the nice usability touches of Castro is that after you’ve dispatched an episode and it disappears from the inbox, the dispatch buttons appear automatically on the next episode in the list. Castro assumes—correctly in almost every case—that once you start triaging you want to continue, and it doesn’t force you to tap on the next episode to make the dispatch buttons reappear. This makes processing your inbox go very quickly.
Don’t be concerned, by the way, that the dispatch buttons limit you to the top and bottom of the playback queue. When you switch to the queue, you can rearrange the episodes by grabbing the dotted handles at the right and dragging them up or down.
One thing that bothered me about the initial reviews of Castro 2 was that they left the impression that you have to go through the triage procedure, even for those podcasts where you listen to every episode. That’s not the case. Although starting in the inbox is the default, you can change the settings for certain podcasts to go straight to the top (or bottom) of the queue.
In my set of subscriptions, new episodes of In Our Time, 99% Invisible, and Slate’s Political Gabfest go straight to the top of the playback queue. I never skip an episode. The Talk Show, on the other hand, too often has guests that offer no insight,^{1} so it gets the triage treatment. So does The Incomparable, although I’m beginning to think that’s a mistake. I set it up so new episodes would go to the inbox because I thought I wouldn’t want to listen to episodes about books and movies I haven’t read or seen. But I’ve found that I so rarely skip an episode, it isn’t worth the triage step.
The downsides to Castro that most reviewers mentioned back in August still hold true:
I’ve been pretty promiscuous in my use of podcast players. Only Downcast and Overcast have stuck for more than a year (and I used Downcast back when there were few decent alternatives). Supertop could make a UI change to Castro tomorrow that sours me on it. But right now, Castro fits my way of listening better than the others.
These are almost always the tech reporters for “real” news outlets. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>If you’ve been a Mac user for any length of time, you’ll probably think of which machines you would have drafted had you been on the show. I sure did, and that’s what this post is about. One restriction I’m going to impose on myself that the youngsters didn’t is that I will only draft Macs that I owned or was the primary user of at work. I like the personal touch.
Yes, I know Ed drafted the SE/30 with his first round pick. I’m just going to assume that I went before him and sniped this pick. It’s my blog, and I’ll do what I want.
The SE/30 is the favorite of a lot of Mac users of a certain age. During the Mac’s 25th anniversary year, it was hailed as the greatest Mac ever by no less than Adam Engst, John Gruber, and John Siracusa. Introduced to the world at the beginning of 1989 and retired almost three years later, it was the apotheosis of the original Mac form factor.
I was teaching in 1989, and that fall one of my departmental colleagues got an SE/30. I was immediately filled with jealousy. When I changed jobs at the beginning of 1990, I persuaded my new employer to provide me with an SE/30, and the sour feeling of inadequacy washed away as I set it up at the corner of my desk.
That was the great thing about the SE/30. It was a serious workstation—the 68030 processor was a beast for its time—in a package that could fit almost anywhere. And when I was 30 years old, my eyes could handle the 9″, 512×342 pixel, black-and-white screen.
No need for a stock image of this one; it’s sitting on my lap right now. This is not the much-maligned original Air. It’s the second-generation model, the one they got right. Real ports, no flip-down door, and Flash storage instead of a 4200 rpm, iPod-class hard disk.
This machine was a revelation when I first got it. It booted up so fast. In fact, everything seemed extra quick, an indication that most of what I was doing was constrained more by I/O than by processing. And of course, it was so thin and light. Even after six years, I don’t really feel it’s a museum piece—it still gets the job done.
Although I drafted the SE/30 first, that was a tactical decision. This is my favorite Mac.
This was my first Mac. I bought it in grad school and wrote my Ph.D. thesis on it, using MacWrite, MacDraw, an ImageWriter, and Andy Hertzfeld’s amazing Switcher.
Although the formal name was 512K, based on its RAM, everyone called it the Fat Mac. Mine was configured with an external single-sided diskette drive to compliment the internal drive. That gave me a whopping 800 kB of storage for the system, the applications, and my files.
But the best thing about the Fat Mac was its RAM, something that didn’t become apparent until Switcher was released. Because applications had to be written to fit in the 128 kB of the original Mac, Switcher allowed you to fit the Finder plus two or three other applications into RAM and quickly flip back and forth between them. It wasn’t multitasking, but it was sure better than the usual launch/use/quit, launch/use/quit cycle. Given that I typeset by hand the equations for my thesis in MacDraw and then pasted them into MacWrite, Switcher was a godsend.
I have three Macs that I’d like to put into the fourth slot, and I don’t know which one to choose. So I’m just going to cheat by squeezing them all into one round. Again, it’s my blog.
Surprisingly, the SE/30 is the only overlap between my choices and the ones made by Stephen, Christina, Brian, and Ed. A good part of this is because my choices are biased toward the early days of the Mac—a lot of beige, as Stephen would say. But it’s also because 30+ years of design includes something for everyone.
It has since appeared a second time as an episode of Simple Beep. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>Modern, stats-loving baseball fans can probably come up with a dozen ways to measure the quality of a pitcher, but I wasn’t interested in cutting-edge sabremetric research, so I stuck with pitching quality statistic of my youth, the earned run average. Remember, this is mostly an excuse to keep my Python skills sharp. Don’t write to tell me about your favorite pitching stat—I don’t care.
I started with a simple text file that looked like this:
Date,IP,ER
4/4,7.0,0
4/10,7.0,3
4/16,8.0,0
4/21,9.0,0
4/28,5.0,1
etc.
Each line represents one game. The date is in month/day format, the earned runs are integers, and the innings pitched are in a hybrid decimal/ternary format common to baseball, with the full innings before the period and the partial innings after it. The full innings are regular decimal numbers, but the partials represent thirds of an inning. The number after the period can take on only the values 0, 1, or 2.
Because I knew Pandas would look at the IP values and interpret them as regular decimal numbers, I decided to massage the input file first. Also, I figured it wouldn’t hurt to add the year to the game dates. After a couple of find-and-replaces in BBEdit, the file looked like this:
Date,FIP,PIP,ER
4/4/2016,7,0,0
4/10/2016,7,0,3
4/16/2016,8,0,0
4/21/2016,9,0,0
4/28/2016,5,0,1
etc.
Now there are separate fields for the full innnings and partial innings pitched. Time to fire up Jupyter and commence to analyzin’.
python:
import pandas as pd
from functools import partial
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (12,9)
This is mostly standard preamble stuff. The odd ones are thercParams
call, which makes the inline graphs bigger than the tiny Jupyter default, and the functools
import, which will help us create ERAs over small portions of the season.
Next, we read in the data, tell Pandas how to interpret the dates, and create an innings pitched field in standard decimal form:
python:
df = pd.read_csv('arrieta.txt')
df['Date'] = pd.to_datetime(df.Date, format='%m/%d/%Y')
df['IP'] = df.FIP + df.PIP/3
Now we can calclulate Jake’s ERA for each game.
python:
df['GERA'] = df.ER/df.IP*9
To get his season ERA as the season develops, we need the cumulative numbers of innings pitched and earned runs given up. That turns out to be easy to do with the Panda’s cumsum
method.
python:
df['CIP'] = df.IP.cumsum()
df['CER'] = df.ER.cumsum()
df['ERA'] = df.CER/df.CIP*9
Let’s see how his ERA has developed:
python:
plt.plot_date(df.Date, df.ERA, '-k', lw=2)
The rise in May, though steep, doesn’t indicate poor pitching. Arrieta just started the season out so well that even very good pitching looks bad in comparison. It’s the jump in late June and early July that looks really bad. And now that I think of it, the Cubs did have a terrible three-week stretch just before the All Star break. Arrieta’s performance was part of that, so his slide started earlier than I was thinking.
But even after the big jump, there’s been a slow climb. So even though the Cubs have played excellent ball since mid-July, Arrieta hasn’t. To get a better handle on how poorly he’s been pitching, we could plot the game-by-game ERAs, but that’s likely to be too jumpy to see any patterns. A way to smooth that out is to calculate moving averages.
But what’s the appropriate number of games to average over? Two is certainly too few, but three might work. Or maybe four. I decided to try both three and four. To do this, I defined a function that operates on a row of the DataFrame to create a running average of ERA over the last n games:
python:
def rera(games, row):
if row.name+1 < games:
ip = df.IP[:row.name+1].sum()
er = df.ER[:row.name+1].sum()
else:
ip = df.IP[row.name+1-games:row.name+1].sum()
er = df.ER[row.name+1-games:row.name+1].sum()
return er/ip*9
The if
part handles the early portion of the season when there aren’t yet n names to average over. Looking at the code now, I realize this could have been simplified by eliminating the if/else
and just using
python:
max(0, row.name+1-games)
as the lower bound of the slice. Oh, well. I’ll leave my crude code here as a reminder to think more clearly next time.
With this general function defined, we can use the partial
function imported from functools
to quickly define running average functions for three and four games and add those fields to the DataFrame.
python:
era4 = partial(rera, 4)
era3 = partial(rera,3)
df['ERA4'] = df.apply(era4, axis=1)
df['ERA3'] = df.apply(era3, axis=1)
Now we can plot everything:
python:
plt.plot_date(df.Date, df.ERA3, '-b', lw=2)
plt.plot_date(df.Date, df.ERA4, '-r', lw=2)
plt.plot_date(df.Date, df.GERA, '.k', ms=10)
plt.plot_date(df.Date, df.ERA, '--k', lw=2)
plt.show()
As you can see, I didn’t bother to make this look nice. I just wanted to dump it all out and take a look at it. I don’t see much practical difference between the three-game average (blue) and the four-game average (red). Arrieta did have a good stretch there in late July and early August (which I hadn’t noticed), but he’s not been pitching well since then. It’s not unlike his early years with Baltimore. I’ll be curious to see where he’s put in the playoff rotation.
As is usually the case with my baseball posts, I’ve learned more about programming tools than I have about the game. I’ve used partial
many times in the past, and I always feel like a real wizard when I do. But I’ve never used cumsum
before, and I’m really impressed with it. Not only does it perform a useful function, it’s implemented in a way that couldn’t be easier to use for common cases like the ones here. I hope I don’t forget it.
Update Sep 24, 2016 9:33 PM
Of course I take full credit for Arrieta’s performance the day after this was posted. Jake obviously reads this blog, especially for the Python-related posts, and realized he needed to step up his game after seeing the clear evidence of how he’s gone downhill recently.
[If the formatting looks odd in your feed reader, visit the original article]
]]>PCalc has for some time been able to accept fractional input. If, for example, you wanted to enter 1⅝, you can tap out the sequence
1 . 5 . 8
And the number you want will appear in the display (assuming you have the Quick Fraction Entry preference set in Advanced Settings).
Up until now, that number would change from
to
when you tapped any operation key or (if you work in RPN, as all right-thinking people do) the Enter key.
But with PCalc 3.6, you can set the display mode to Fraction, either in the Settings
or by tapping and holding on the display area.
What’s great about this is that it allows you to get fractional answers when that’s the natural way to present the results. For example, we can add 1⅝″ and ¾″^{1}
to get 2⅜″.
Sure, it’s easy to see 2.375 and think 2⅜, but even us old hands at decimal-fraction conversion hesitate when dealing with 16ths and 32nds.
I’m told PCalc 3.6 has some cool features that work with iOS 10. I wouldn’t know, as I haven’t tried out Apple’s public beta and don’t intend to install the released version of iOS 10 until the initial excitement—and the initial bugs—have passed by. What I do know is that PCalc 3.6 is an excellent update even on my horribly outdated iPhone 6S running iOS 9.
To enter a pure fraction, tap the decimal point key twice between the numerator and the denominator, e.g., 3 . . 4
. ↩
[If the formatting looks odd in your feed reader, visit the original article]
]]>I switched to the S Club with the 5S. I had a 5 (actually, I had three 5s—two of them were replaced because of dust between the camera lens and sensor), but I went ahead and bought a 5S because my son’s 4 was on its last legs and needed to be replaced. He got my 5 as a hand-me-down.
The 5S, as you may recall, was a big jump up from the 5 despite having essentially the same case geometry and overall look. The processor went from 32 bits to 64, the home button got Touch ID, the camera got burst mode, and the case became more scratch-resistant. Also, I never had any problems with dust under the 5S’s camera lens.
I skipped the 6 and waited for the 6S,^{1} which meant I got the way way faster Touch ID, the stronger frame, twice the RAM, improved LTE networking, and the usual faster processor and better camera. S Club wins again.
But the 7 is the third version of this enclosure design, and it seems extremely unlikely we’ll see an S version of it.^{2} More important, next year is the 10th anniversary of the original iPhone, and Apple will certainly mark the occasion with a major change in case design. Sadly, there will be no S Club 7.
What will I do? Get the 10th Anniversary iPhone? Wait around another year for what will certainly be a distinctly better version of that design? I suspect I’ll be unable to resist whatever comes out in 2017, and I’ll have to tear up my S Club membership card.
[If the formatting looks odd in your feed reader, visit the original article]
]]>Why, in A Fall of Moondust, did Arthur C. Clarke get the numbering the first two Lagrange points of the Earth-Moon system backward?
While it’s certainly true that the numbering of the points is arbitrary, the convention I’ve always seen has been to put L1 between the Earth and the Moon and L2 beyond the Moon. Clarke, no neophyte when it came to orbital mechanics, turned those numbers around.
Today, the likely answer arrived in my Twitter feed. Here’s Peter Demarest with a bit of scholarship:
@drdrang Szebehely’s “Theory of Orbits” used that numbering for the Langrange points, but it fell out of fashion long ago.
— Peter Demarest (@pdemarest) Sep 1 2016 9:47 AM
It didn’t take me long to find Victor Szebehely and his wonderfully focused book, Theory of Orbits: The Restricted Problem of Three Bodies, published in 1967 by Academic Press. On page 133, we see this:
As in the analysis we went through a couple of weeks ago, Szebehely sets his origin at the barycenter. But as Peter tweeted, Szebehely defines L1 as the colinear point beyond the smaller mass and L2 as the colinear point between the masses. Clarke may have used Szebehely directly or he may have referred to works that used the same nomenclature. Either way, it wasn’t a mistake.
Theory of Orbits is a delightful book, very much in keeping with the era in which it was written. I have many engineering texts from this period, and it’s common for them to treat numerical methods as something exotic. Here’s a passage from page 135 of Szebehely, where he gives advice on the most effective ways to solve the fifth-order algebraic equation that leads to the positions of the colinear Lagrange points:
Take a look at the paragraph after Equation 20. He’s describing a direct iteration technique and actually concerns himself with the time savings that can be achieved by eliminating a single iteration. How quaint!
Thanks to Peter for solving the mystery and introducing me to this wonderful book.
On the other hand, success in blogging is often said to be the result of a tight focus on a single topic. Maybe an all-Lagrange blog would be the big break I’ve been waiting for. ↩
[If the formatting looks odd in your feed reader, visit the original article]
]]>One of the things I like about Siri is that she doesn’t complain when you deviate from her instructions. In the old days, leaving the route or missing a turn would cause GPS units to say “Recalculating…” in what I interpreted as an exasperated tone. Siri just accepts your change and gives you new directions.
So as I was hunting, Siri kept patiently telling me how to get to the airport. When I didn’t see a gas station after a few blocks worth of looking, I gave up and asked her for directions to the closest one.
“Starting route,” she replied. “Head north on Isenberg Street.”
This is why I couldn’t bring myself to read Steven Levy’s new article on how Apple is making great advances in machine learning. The iBrain is already inside my phone? No, not yet.
You see, when Siri told me to head north on Isenberg, I was traveling south on Isenberg. In that circumstance, “head north” is a stupid instruction to give.
Siri knew perfectly well I was going south on Isenberg. Not half a minute earlier, she’d been telling me how to turn off Isenberg to get to the interstate. And she’d been tracking my location continuously since I left the hotel. The context was there, but it wasn’t used.
This is what’s most frustrating about Siri and why I find myself yelling at her so often. It has nothing to do with big data or compromised privacy. The problem I posed was ideal for Apple’s everything-on-the-phone strategy. It didn’t even require changing apps. And yet Siri^{2} interpreted “get directions to the nearest gas station” without any regard to the data she had in her hands just seconds earlier. For some reason, when I asked for directions, only my position was used in developing the answer. That I was in a car and traveling south—essential information for giving good directions—was ignored.
Did Siri figure out I was going south and adjust her directions? Of course she did, and I got to the gas station fairly quickly. But the first thing she said was wrong, and that’s what ruins the experience.
Apple cares about the experience, doesn’t it?
[If the formatting looks odd in your feed reader, visit the original article]
]]>First, there’s the nomenclature. In the story, there’s a satellite on a line between the Earth and the Moon. It’s used for observation of and communication with the near side of the Moon because it stays in place relative to the Moon’s orbit. This is clearly the first Lagrange point, or L1, of the Earth-Moon system, and yet Clarke gives the satellite the name Lagrange II:
High above the surface of the Moon, from an antenna which, curiously enough, was aimed directly at the face of the Earth, a radio pulse launched itself into space. In a sixth of a second it had flashed the fifty thousand kilometres to the relay satellite known as Lagrange II, directly in the line between Moon and Earth. Another sixth of a second and the pulse had returned, much amplified, flooding Earthside North from Pole to Equator.
Later, he mentions a second satellite that occupies a similar spot above the far side of the Moon. This is the L2 point, but he calls the satellite Lagrange I:
When a ship’s down on the Moon, it can be spotted very quickly from one of the satellites—either Lagrange II above Earthside, or Lagrange I over Farside.
The choice of names can’t be coincidental. Clarke must have intended them to named after their respective points. He even says Lagrange II is
[b]alanced here between Earth and Moon, in a cosmic tight-rope act made possible by one of the obscurer consequences of the Law of Gravitation…
So did Clarke get the nomenclature backwards or has the nomenclature been changed in the past 55 years? I’ve never seen any reference to Lagrange points using Clarke’s numbering, but I still can’t believe he got it wrong. This isn’t just any science fiction author we’re talking about here. It’s the guy who invented the geosynchronous orbit.
With that mystery unresolved, I decided to check up on the 50,000 km distance mentioned in the first quote.
Rewriting one of the equations from my earlier post with a slight change in notation, the equation for the distance from the moon to the L1 point is
[3 (1 - \mu) \rho_m^3 \left( 1 - \rho_m + \frac{\rho_m^2}{3} \right) - \mu (1 - \rho_m)^3 (1 + \rho_m + \rho_m^2) = 0]where [\rho_m] is the distance from the center of the Moon to the L1 point expressed as a fraction of the distance from the Earth to the Moon, and [\mu] is the mass of the Moon expressed as a fraction of the sum of the masses of the Earth and Moon. From NASA’s Moon Fact Sheet, we calculate [\mu = 0.0122] and can then solve the equation to get [\rho_m = 0.1509].
The mean center-to-center distance from Earth to Moon is 384,400 km, so the distance from the center of the Moon to L1 is 58,000 km. Subtracting off the radius of the Moon, that puts L1 56,300 km above the Moon’s surface.
I guess I’m a little surprised Clarke would round this number to 50,000, but “fifty thousand” does have a nice sound to it.
Update 09/1/2016 10:08 PM
Look here for the answer to the L1/L2 reversal.
[If the formatting looks odd in your feed reader, visit the original article]
]]>This was the first good MacBook Air, replacing that weird thing with the flip-out door. I bought it in the fall of 2010, shortly after it was released, and it was a revelation. So thin, so light, so quiet, so quick to boot up. It instantly became my favorite Mac, displacing even the SE/30.^{2}
But it’s thisclose to six years old, and even the best computers don’t last forever. It had a near-death experience last summer, but has somehow managed to heal itself. In the last month I’ve noticed an intermittent problem with the power cord. It’s still running Yosemite, because I figured it wasn’t worth the bother to upgrade the OS on a computer I wouldn’t be using much longer.
Frankly, the Air should have been replaced at least a year ago, but I was waiting for the release of a Retina Air. The MacBook killed that idea and didn’t replace it with a computer I wanted. The relatively low power of the MacBook doesn’t bother me, but the 12″ screen does. While this is my portable computer for business travel, it’s also my only computer for home. I don’t want a screen smaller than 13″.
That leaves the MacBook Pro, last updated when Steve Jobs was still CEO. That might be an exaggeration, but I’m very leery of buying computers that seem to be on the verge of a big upgrade. I’m still traumatized by my purchase of an LC II back in the early 90s—it was almost immediately replaced by the LC III, which was 50% faster and cost 40% less. Curse you, 90s Apple!
Anyway, Mark Gurman says there’s a new MacBook Pro coming, which means everyone else who’s been saying there’s a new MacBook Pro coming must have been right. And he says the row of function keys across the top will be replaced by a touch-sensitive OLED strip, which means everyone else who’s been saying the row of function keys across the top will be replaced by a touch-sensitive OLED strip must have been right.
Lots of people are bemoaning this loss of real keys with tactile feedback. When I mentioned on Twitter that no one touch-types up there, I got some guff from poor, self-deluded souls who swear up and down that they do.
“I use the media playback and volume controls all the time without looking,” was the most common claim. I’m sure you do. Even I can do that, but it isn’t touch-typing, and it doesn’t need to be done without looking. Hitting the media and brightness keys is a context shift. However brief it is, or however brief you imagine it to be, it isn’t done in the flow of creation the way touch-typing is.
I’m more sympathetic to vi users^{3} who are worried about the loss of the Escape key. Even though switching from insert mode to command mode is, by definition, a context shift, it’s a very minor one, done in service to the overall act of writing or programming.
But I, for one, welcome our touch-sensitive OLED overlords. The flexible, fungible function strip could be a boon to user interfaces, providing both a gentle assistance to new and fearful users and a great customization tool for power users.
But there is this nagging thought in the back of my head. Can Apple pull this off? Does it still have the UX chops to figure out the right way to implement what could be a very powerful addition to the Mac? So much of what’s good about Apple products, both hardware and software, seems to be based on wise, user-centric decisions made years ago. Can it still make those decisions?
This worry is not unwarranted. Some recent versions of Apple’s Mac software—iTunes and the iWork suite, for example—have been regressions. They’ve managed to be both more confusing to average users and less powerful for advanced users.
The Apple Watch is another example. Despite the brave face put on by members of the Apple press, the lack of outright praise meant the watch wasn’t nearly what it could have been, what it should have been. This has been made even more clear by the reaction to watchOS 3. It wouldn’t seem like such a great leap forward if the earlier versions hadn’t been so backward.
On the other hand, the story of watchOS 3 is an indication that Apple still has the goods, that it can still make good decisions, even if it means reversing much-hyped earlier decisions. That’s the Apple I hope to see in the new MacBook Pro.
And the screenshot is from the indispensible MacTracker app, free in both the Mac and iOS App Stores. ↩︎
If you ask me to list my favorite Macs, I’ll still put the SE/30 at the top, just to keep its memory alive. But it’s a lie. ↩︎
I know it’s common now to refer to these people as Vim users, not vi users, but the Escape key has been a critical part of vi use since the Bill Joy days. It’s a testament to Vim’s dominance that relatively few people even know that other versions of vi exist. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>Lagrange points are points in the orbital plane of a planet^{1} that orbit the sun with the same period as the planet. You might think you could put a satellite at any point along a planet’s orbital path and Kepler’s laws would ensure that it has the same period as the planet. But Kepler’s laws apply only to a two-body system. This is a three-body problem, in which the satellite’s motion is influenced by the gravitational pulls of both the sun and the planet. While there is no solution to the general three-body problem, the Lagrange points—so named because they were worked out by the 18th century natural philosopher Joseph-Louis Lagrange—represent special cases where the solution is possible.
In last year’s post, I showed how to find the first Lagrange point, L1, by balancing the two gravitational forces acting on it to create a centripetal acceleration that keeps a satellite at L1 in place. This approach works, but it’s a very non-Lagrangian way of solving the problem.
Lagrange was all about energy. He took Newtonian mechanics and recast it to eliminate the need to balance forces and inertias. In Lagrangian mechanics, you get solutions by taking derivatives of the kinetic and potential energy functions. It’s an elegant technique, well suited to the explosion of analysis on the Continent back at that time.
Let’s start by assuming we’ve already solved the two-body problem of a sun and its planet in a circular orbit. We’ll take their masses to be [m_s] and [m_p], respectively, and the distance between their centers to be [R]. We’ll then introduce a nondimensional quantity, [\mu], to represent the planet’s fraction of the total mass, [M]. Thus,
[M = m_s + m_p] [m_p = \mu M] [m_s = (1 - \mu)M]The center of mass of the two-body system—which astronomers call the barycenter because it sounds more scientific—is on a line between the two bodies a distance [\mu R] from the sun and [(1 - \mu)R] from the planet. Both the sun and the planet revolve about the barycenter with an angular speed [\omega], where
[\omega^2 = \frac{GM}{R^3}]The period is related to the angular speed through the relation
[T = \frac{2\pi}{\omega}]which leads to the well-known expression for Kepler’s Third Law, which states that the square of the period is proportional to the cube of the distance:
[T^2 = \frac{4 \pi^2 R^3}{G M}]With these preliminaries out of the way, let’s move on to finding the Lagrange points. I want to start by pointing you to an excellent online resource, Richard Fitzpatrick’s Newtonian Dyanamics, which is available in both PDF and HTML format. Fitzpatrick, who teaches at the University of Texas at Austin (hook ’em), does a very nice job of explaining both the two-body problem and the restricted three-body problem. There’s one trick in particular that I stole directly from him to simplify a potential energy expression.
Here is our system of sun (yellow), planet (blue), and satellite (black) laid out on an [x\text{-}y] coordinate system. We put the origin at the barycenter and the [x\text{-axis}] on the line between the sun and the planet. Furthermore, we’re going to have our coordinate system rotate at a constant angular speed of [\omega], precisely matching the movement of the sun and the planet about the barycenter. This will be our reference frame for the analysis. The advantage of using a rotating reference frame is that the sun and planet are, by definition, motionless in this frame, and our search for Lagrange points is reduced to finding points where the satellite will be motionless, too.
You may object to using a rotating reference frame.
A rotating reference frame isn’t inertial. That’s true.
You can’t do an analysis in a non-inertial reference frame. That’s not true.
Non-inertial reference frames are perfectly fine as long as you account for the acceleration terms correctly. This is the deeper truth behind d’Alembert’s Principle. Most of us learn d’Alembert’s Principle as simply moving the acceleration term in Newton’s Second Law over to the other side of the equation and treating it as an additional force.
[\mathbf{F} = m\: \mathbf{a} \quad \Longleftrightarrow \quad \mathbf{F} - m\: \mathbf{a} = 0]But d’Alembert works in an energy context, too.
In our rotating frame of reference, the potential energy of the satellite has three terms.
[U = -\frac{G m_s m}{r_s} - \frac{G m_p}{r_p} - \frac{1}{2} m (r \omega)^2]The first two terms are the gravitational potential energy due to the sun and the planet, respectively, and the third term is the centrifugal potential energy due to the rotating frame. The third term wouldn’t appear in a potential energy expression written for an intertial frame.^{2}
In the expression for [U],
See the figure above for details.
The first thing to do is substitute our previous expressions for [m_s], [m_p], and [\omega^2] into the expression for [U].
[U = -\frac{G M m (1 - \mu)}{r_s} - \frac{G M m \mu}{r_p} - \frac{G M m}{2 R^3} r^2]We’re starting to see some common terms we can factor out. We can do even better if we rewrite the [r] terms using nondimensional variables,
[r = \rho R, \quad r_s = \rho_s R, \quad r_p = \rho_p R]which allows us to write [U] this way:
[U = \frac{GMm}{R} \left[ -\frac{1-\mu}{\rho_s} - \frac{\mu}{\rho_p} - \frac{1}{2}\rho^2 \right]]All of the terms with units have been factored out of the brackets into a constant scaling term. Finding the stationary points of [U] now reduces to finding the stationary points of the nondimensional expression within the brackets, which we’ll call [u].
[u = -\frac{1-\mu}{\rho_s} - \frac{\mu}{\rho_p} - \frac{1}{2}\rho^2]In effect, we’ve switched from the [x\text{-}y] coordinate system of the figure above to the [\xi\text{-}\eta] system shown below.
Using [\rho], [\rho_s], and [\rho_p] makes for a compact expression, but it isn’t convenient for plotting, which is what I want to do to help find the stationary points^{3} of [u]. We need to express [u] in terms of [\xi] and [\eta], which we get from the Pythagorean formulas
[\rho^2 = \xi^2 + \eta^2] [\rho_s^2 = (\xi + \mu)^2 + \eta^2] [\rho_p^2 = [\xi - (1 - \mu)]^2 + \eta^2]So we end up with this,
[u = -\frac{1-\mu}{\sqrt{(\xi + \mu)^2 + \eta^2}} - \frac{\mu}{\sqrt{[\xi - (1 - \mu)]^2 + \eta^2}} - \frac{1}{2}(\xi^2 + \eta^2)]which is a nasty mess, but we have computers to keep track of everything, so there’s no need to worry about losing terms.
Here’s the contour plot of [u] as a function of [\xi] (abscissa) and [\eta] (ordinate). I’m plotting it for [\mu = 0.1], because that’s a value that allows us to see all the Lagrange points. (For the Earth-Sun system, [\mu = 0.000003], which would put L1 and L2 so close to the Earth itself we wouldn’t be able to distinguish them at this scale.)
The dirty yellow dot is the sun, the blue dot is the planet, the × is the barycenter, and the various crosses are the stationary points of [u]. You can click on the plot to see a bigger version.
The contour lines represent equal spacing in the value of [u]. They range from dark blue for the lowest points to dark red for the highest. We see that L1, L2, and L3 are colinear with the sun and planet and are at saddle points. L4 and L5 are at local maxima. The coordinates of the points, which I calculated using techniques we’ll get into later, are as follows:
Point | [\xi] | [\eta] |
---|---|---|
L1 | 0.609 | 0.000 |
L2 | 1.260 | 0.000 |
L3 | -1.042 | 0.000 |
L4 | 0.400 | 0.866 |
L5 | 0.400 | -0.866 |
The [\xi] coordinates of L1, L2, and L3 pretty much have to be calculated numerically. There’s no nice closed-form solution to get those values. But there is a simple, non-computational way to get the positions of L4 and L5, and the clue is in the values you see in the table.
That 0.866 you see for the [\eta] value is the sine of 60°, and the 0.400 is exactly 0.1 less than the cosine of 60°. Remember that the sun is 0.1 to the left of the origin and the planet is 0.9 to the right of the origin. Putting this all together, we see that L4 is at the intersection of a 60° line up and out from the sun and a 60° line up and back from the planet. Similarly for L5, except that the lines are 60° down instead of up. Which means that L4 and L5 form equilateral triangles with the sun and the planet.
This is not a coincidence that just happens to work out when [\mu = 0.1]. It’s true regardless of the mass distribution between the sun and the planet. In the next section, we’ll prove that, but the math gets messy. If you want to just take it on faith, skip this next section.
For the fearless few, we’re going to use that trick I found in Richard Fitzpatrick’s book. There’s nothing especially hard in this; it’s just a lot of tedious algebra, and I’m going to show all the steps. Textbooks usually don’t for reasons of space, but there’s a lot of space on a web page.
Recall that
[\rho_s^2 = (\xi + \mu)^2 + \eta^2] [\rho_p^2 = [\xi - (1 - \mu)]^2 + \eta^2]If we multiply the first of these by [1 - \mu] and second by [\mu] and add them together, we get (after some cancellation)
[(1 - \mu)\rho_s^2 + \mu \rho_p^2 = \xi^2 + \eta^2 + \mu(1 - \mu)]Therefore
[\xi^2 + \eta^2 = \rho^2 = (1 - \mu)\rho_s^2 + \mu \rho_p^2 - \mu(1 - \mu)]We can substitute this into the compact expression for [u] to get
[u = -\frac{1-\mu}{\rho_s} - \frac{\mu}{\rho_p} - \frac{1}{2} \left[ (1 - \mu)\rho_s^2 + \mu \rho_p^2 - \mu(1 - \mu) \right]]or, after rearranging
[u = -(1 - \mu) \left(\frac{1}{\rho_s} + \frac{\rho_s^2}{2} \right) - \mu \left( \frac{1}{\rho_p} + \frac{\rho_p^2}{2} \right) + \frac{\mu (1 - \mu)}{2}]What good is this? Well, although it may not seem like it, it actually makes it a little easier to take the partial derivatives of [u] with respect to [\xi] and [\eta] in order to find the stationary points. We’ll use the chain rule to do it:
[\frac{\partial u}{\partial \xi} = \frac{\partial u}{\partial \rho_s}\frac{\partial \rho_s}{\partial \xi} + \frac{\partial u}{\partial \rho_p}\frac{\partial \rho_p}{\partial \xi} = 0] [\frac{\partial u}{\partial \eta} = \frac{\partial u}{\partial \rho_s}\frac{\partial \rho_s}{\partial \eta} + \frac{\partial u}{\partial \rho_p}\frac{\partial \rho_p}{\partial \eta} = 0]The partial derviatives with respect to [\rho_s] and [\rho_p] are simple:
[\frac{\partial u}{\partial \rho_s} = (1 - \mu) \left( \frac{1}{\rho_s^2} - \rho_s \right)] [\frac{\partial u}{\partial \rho_p} = \mu \left( \frac{1}{\rho_p^2} - \rho_p \right)]The easy way to get the partials of [\rho_s] and [\rho_p] with respect to [\xi] and [\eta] is to take the total differentials of the expressions for [\rho_s^2] and [\rho_p^2]:
[2 \rho_s\; \mathrm{d}\rho_s = 2(\xi + \mu)\;\mathrm{d}\xi + 2\eta\; \mathrm{d}\eta] [2 \rho_p\; \mathrm{d}\rho_p = 2[\xi - (1 - \mu)]\;\mathrm{d}\xi + 2\eta\; \mathrm{d}\eta]Dividing the top equation by [2 \rho_s] and the bottom by [2 \rho_p] gives us
[\mathrm{d}\rho_s = \frac{\xi + \mu}{\rho_s} \mathrm{d}\xi + \frac{\eta}{\rho_s} \mathrm{d}\eta] [\mathrm{d}\rho_p = \frac{\xi - (1- \mu)}{\rho_p} \mathrm{d}\xi + \frac{\eta}{\rho_p} \mathrm{d}\eta]which means
[\frac{\partial \rho_s}{\partial \xi} = \frac{\xi + \mu}{\rho_s}, \qquad \qquad \frac{\partial \rho_s}{\partial \eta} = \frac{\eta}{\rho_s}] [\frac{\partial \rho_p}{\partial \xi} = \frac{\xi - (1 - \mu)}{\rho_p}, \qquad \quad \frac{\partial \rho_p}{\partial \eta} = \frac{\eta}{\rho_p}]Now we have all the pieces needed to build the equations for the stationary points:
[\frac{\partial u}{\partial \xi} = (1 - \mu) \left( \frac{1}{\rho_s^2} - \rho_s \right) \frac{\xi + \mu}{\rho_s} + \mu \left( \frac{1}{\rho_p^2} - \rho_p \right) \frac{\xi - (1 - \mu)}{\rho_p} = 0] [\frac{\partial u}{\partial \eta} = (1 - \mu) \left( \frac{1}{\rho_s^2} - \rho_s \right) \frac{\eta}{\rho_s} + \mu \left( \frac{1}{\rho_p^2} - \rho_p \right) \frac{\eta}{\rho_p} = 0]Simplifying a bit we get
[\frac{\partial u}{\partial \xi} = (1 - \mu) \left( \frac{1}{\rho_s^3} - 1 \right)(\xi + \mu) + \mu \left( \frac{1}{\rho_p^3} - 1 \right)[\xi - (1 - \mu)] = 0] [\frac{\partial u}{\partial \eta} = (1 - \mu) \left( \frac{1}{\rho_s^3} - 1 \right) \eta + \mu \left( \frac{1}{\rho_p^3} - 1 \right) \eta = 0]The second equation is the key. First, we can factor out the [\eta]:
[\eta \left[ (1 - \mu) \left( \frac{1}{\rho_s^3} - 1 \right) + \mu \left( \frac{1}{\rho_p^3} - 1 \right) \right] = 0]This means that either
[\eta = 0]which is what leads us to L1, L2, and L3 (we’ll get to that later), or
[(1 - \mu) \left( \frac{1}{\rho_s^3} - 1 \right) + \mu \left( \frac{1}{\rho_p^3} - 1 \right) = 0]Let’s explore this condition. We’ll move the terms that don’t involve [\rho_s] or [\rho_p] to the other side of the equation.
[\frac{1 - \mu}{\rho_s^3} + \frac{\mu}{\rho_p^3} = (1 - \mu) + \mu = 1]An obvious solution to this equation is [\rho_s = \rho_p = 1], which will work for all values of [\mu]. What we don’t know, though, is whether that’s the only solution for [\eta \ne 0]. To see if it is, we have to combine this result with the first stationary equation.
Let’s start by solving for [\rho_s^3]. We can multiply through by [\rho_s^3 \rho_p^3] to get rid of the fractions:
[(1 - \mu) \rho_p^3 + \mu \rho_s^2 = \rho_s^3 \rho_p^3]And then solve for [\rho_s^3]:
[\rho_s^3 = \frac{(1 - \mu) \rho_p^3}{\rho_p^3 - \mu}]We plug this into the first stationary equation to get
[(1 - \mu) \left( \frac{\rho_p^3 - \mu}{(1 - \mu) \rho_p^3} - 1 \right)(\xi + \mu) + \mu \left( \frac{1}{\rho_p^3} - 1 \right)[\xi - (1 - \mu)] = 0]which simplifies first to
[(1 - \mu) \left[ \frac{\mu}{1 - \mu} \left(1 - \frac{1}{\rho_p^3} \right) \right](\xi + \mu) + \mu \left( \frac{1}{\rho_p^3} - 1 \right)[\xi - (1 - \mu)] = 0]and then to
[\left(1 - \frac{1}{\rho_p^3} \right) (\xi + \mu) - \left(1 - \frac{1}{\rho_p^3} \right) [\xi - (1 - \mu)] = 0]Once again, we can factor out a common term and simplify:
[\left(1 - \frac{1}{\rho_p^3} \right) \left\{ (\xi + \mu) - [\xi - (1 - \mu)] \right\} = 0]With this, we can say either
[1 - \frac{1}{\rho_p^3} = 0]or
[(\xi + \mu) - [\xi - (1 - \mu)] = 0]But the second of these is impossible because the [\xi] and [\mu] terms cancel, leaving [1 = 0]. So the only solution for [\eta \ne 0] is
[1 - \frac{1}{\rho_p^3} = 0]and therefore [\rho_p = 1], which means [\rho_s = 1], confirming our guess about the equilateral triangle solution for L4 and L5.
OK, now that we’ve confirmed the equilateral triangle postions for L4 and L5, let’s explore the colinear positions, L1, L2, and L3.
The two equations that must be satisfied for every Lagrange point are
[\frac{\partial u}{\partial \xi} = (1 - \mu) \left( \frac{1 - \rho_s^3}{\rho_s^3} \right)(\xi + \mu) + \mu \left( \frac{1 - \rho_p^3}{\rho_p^3} \right)[\xi - (1 - \mu)] = 0] [\frac{\partial u}{\partial \eta} = \eta \left[ (1 - \mu) \left( \frac{1 - \rho_s^3}{\rho_s^3} \right) + \mu \left( \frac{1 - \rho_p^3}{\rho_p^3} \right) \right] = 0](If you’re wondering where these equations came from, it’s because you skipped over the previous section. The path to enlightenment is not easy, grasshopper.)
An obvious condition that solves the second equation is [\eta = 0]. That’s the value of [\eta] for L1, L2, and L3. All we need to do then is pull three solutions for [\xi] out of the first equation. We’ll refer to this layout of the points to specialize the equation for each of the points:
Let’s start with L1, where
[\rho_s = \xi + \mu = 1 - \rho_p, \qquad \rho_p = (1 - \mu) - \xi]For very small values of [\mu], [\rho_p] will also be small, so it’s convenient to put the whole equation in terms of [\rho_p]:
[(1 - \mu) \left( \frac{1 - (1 - \rho_p)^3}{(1 - \rho_p)^2} \right) - \mu \left( \frac{1 - \rho_p^3}{\rho_p^2} \right) = 0]Expanding and collecting terms gives
[(1 - \mu) \left( \frac{3\rho_p (1 - \rho_p + \rho_p^2/3)}{(1 - \rho_p)^2} \right) - \mu \left( \frac{(1 - \rho_p)(1 + \rho_p + \rho_p^2)}{\rho_p^2} \right) = 0]or
[3 (1 - \mu) \rho_p^3 \left( 1 - \rho_p + \frac{\rho_p^2}{3} \right) - \mu (1 - \rho_p)^3 (1 + \rho_p + \rho_p^2) = 0]Most numerical equation solving routines will have no trouble with this equation, but as I said earlier, there is no simple closed-form solution for it. We can, however, take advantage of the fact that [\rho_p] is relatively small when [\mu] is very small to get a closed form approximate solution:
[\rho_p^3 \approx \frac{\mu}{3 (1 - \mu)}]or
[\rho_p \approx \sqrt[3]{\frac{\mu}{3 (1- \mu)}}]Notice that [\mu] and [\rho_p] are at different levels of “small.” The cube/cube root relationship means that [\mu] is much smaller than [\rho_p].
For [\mu = 0.1], a numerical solution of the exact expression gives [\rho_s = 0.291] which corresponds to [\xi = 0.609] as given in the table above. The approximate solution is [\rho_s = 0.333], which is pretty far off, mainly because [\rho_s] just isn’t small enough.
The determination of L2 follows the same pattern. For this position, with the point beyond the planet,
[\rho_s = \xi + \mu = 1 + \rho_p, \qquad \rho_p = \xi - (1 - \mu)]so
[(1 - \mu) \left( \frac{1 - (1 + \rho_p)^3}{(1 + \rho_p)^2} \right) + \mu \left( \frac{1 - \rho_p^3}{\rho_p^2} \right) = 0]After expanding, collecting, and rearranging as we did above, we get
[-3 (1 - \mu) \rho_p^3 \left( 1 + \rho_p + \frac{\rho_p^2}{3} \right) + \mu (1 - \rho_p^3) (1 + \rho_p)^2 = 0]As with L1, this can be solved numerically without much trouble, but there is a decent closed-form approximation for small [\mu] and [\rho_p]. It’s the same as the approximation for L1:
[\rho_p^3 \approx \frac{\mu}{3 (1 - \mu)}]or
[\rho_p \approx \sqrt[3]{\frac{\mu}{3 (1- \mu)}}]This puts the L2 position about as far outside the planet’s orbit as L1 is inside the planet’s orbit.
For [\mu = 0.1], a numerical solution of the exact expression gives [\rho_s = 0.360] which corresponds to [\xi = 1.260] as given in the table above. The approximate solution is [\rho_s = 0.333], which again is pretty far off.
Finally, we have L3, where we have to be careful with the signs. Because they’re distances, [\rho_s] and [\rho_p] are positive, but the coordinate [\xi] is negative.
[\rho_s = -(\xi + \mu), \qquad \rho_p = -[\xi - (1 - \mu)] = 1 + \rho_s]In this case, we’ll write the first stationary equation in terms of [\rho_s].
[-(1 - \mu) \left[ \frac{1 - \rho_s^3}{\rho_s^2} \right] - \mu \left[ \frac{1 - (1 + \rho_s)^3}{(1 + \rho_s)^2} \right] = 0]In this case, [\rho_s] is going to be close to 1, so we can introduce a small value, [\delta], such that [\rho_s = 1 - \delta]. That turns the stationary equation into
[-(1 - \mu) \left[ \frac{1 - (1 - \delta)^3}{(1 - \delta)^2} \right] - \mu \left[ \frac{1 - (1 + (1 - \delta))^3}{(1 + (1 - \delta))^2} \right] = 0]which looks like a real mess, but as before we expand, collect, and rearrange to get
[-3 (1 - \mu) \delta (2 - \delta)^2 \left( 1 - \delta + \frac{\delta^2}{3} \right) + \mu (7 - 12\delta + 6\delta^2 - \delta^3)(1 - \delta)^2 = 0]Ignoring the higher-order terms in [\delta], we get the approximation
[\delta \approx \frac{7}{12} \frac{\mu}{1 - \mu}]In this case, [\mu] and [\delta] are at about the same order of “small.”
Using this approximation, the [\xi] coordinate is
[\xi = -1 - \mu + \delta \approx - \left( 1 + \frac{5}{12} \frac{\mu}{1 - \mu} \right)]For [\mu = 0.1], a numerical solution of the exact expression gives [\delta = 0.0584] which corresponds to [\xi = -1.042] as given in the table above. The approximate solution is [\delta = 0.0648]. The percent error in this approximation for [\delta] is comparable to that of the earlier approximations for [\rho_p].
As mentioned earlier, [\mu = 0.000003] for the Sun-Earth system. With such a small value of [\mu], the approximations developed above should be pretty accurate. Let’s see.
As expected, the approximations are quite good. Probably not good enough for NASA, but good enough for a blog post.
The real value of the approximate formulas is not for computation, it’s for insight. By seeing how [\rho_p] and [\delta] scale with [\mu], we get a sense of how the positions of the colinear Lagrange points change with changing mass distributions.
It’s often said that L4 and L5 are the stable Lagrange points. This seems wrong, because those points are at local maxima of the potential energy, not local minima, and stability is associated with minima. My understanding is that the stability comes from Coriolis forces, which tend to keep objects in orbit around L4 and L5. We didn’t include a Coriolis term in our potential energy expression because our analysis was designed to find places where the satellites would be stationary in our rotating frame of reference. Coriolis forces arise only when a body is moving relative to the rotating frame.
I may look into redoing the analysis with a Coriolis term. Check back in another year.
Update 08/18/2016 8:23 AM
The Trojan asteroids are clustered around the L4 and L5 positions of the Sun-Jupiter system. They got a mention from Jason Snell and Stephen Hackett on this week’s episode of their Liftoff podcast, which I just listened to this morning. The plan of the proposed Lucy space mission is to visit five of the Trojan satellites.
A tip from Jeff Youngstrom on Twitter led me to this remarkable page by Petr Scheirich, which has a wealth of graphics related to comets and asteroids, including this animation of the Trojan (green) and Hilda (red) groups as viewed in a reference frame that rotates with Jupiter.
The animation covers, I believe, one Jovian year. The in-and-out movement of Jupiter represents its elliptical orbit from perihelion to aphelion, and you can track the orbits of at least some of the green dots around the L4 and L5 positions.
Although we tend to be most interested in the Sun-Earth Lagrange points, there are similar points for every sun-planet combination and for every planet-moon combination, too. ↩︎
And it’s not a coincidence that it looks like a kinetic energy term with the sign changed. D’Alembert strikes again! ↩︎
Stationary points are where the function is at a local maximum, minimum, or saddle point. They’re the points where the slopes of the function’s surface are zero. ↩︎
[If the formatting looks odd in your feed reader, visit the original article]
]]>