-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwalk.go
More file actions
131 lines (107 loc) · 2.74 KB
/
walk.go
File metadata and controls
131 lines (107 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package gpelements
import (
"fmt"
"math/rand"
"regexp"
)
// Re the NORAD catalog number namespace:
//
// The "Alpha-5" scheme allows for namespace expansion by accepting a
// capital English letter as the leading character. The resulting
// namespace would hold 360,000 identifiers (assuming I and O are not
// discarded).
//
// According to Celestrak, 18 Space Control Squadron (18 SPCS) is
// currently assigning numbers in the range 7995xxxxx (an "analyst sat
// range").
// NextAlpha5Num generates a new NORAD catalogy number using the "Alpha-5"
// scheme and updates the Name.
func NextAlpha5Num(state int64) (string, int64, error) {
var (
blocks = "ABCDEFGHIJKMPQRSTUVWXYZ"
block = state / 10000
rem = state % 10000
)
if int64(len(blocks)) <= block {
return "", state, fmt.Errorf("NextAlpha5Num at %d is out of blocks (%d)", state, block)
}
id := fmt.Sprintf("%c%04d", blocks[block], rem)
return id, state + 1, nil
}
var idInName = regexp.MustCompile("^#[ ]+ ")
func (e *Elements) UpdateName(id string) {
s := idInName.ReplaceAllString(e.Name, "")
e.Name = "#" + id + " " + s
}
func (e *Elements) Reassign(state int64) (int64, error) {
id, next, err := NextAlpha5Num(state)
if err != nil {
return state, err
}
e.NoradCatId = NoradCatId(id)
return next, nil
}
func (e *Elements) IncSetNum() error {
if 10000 <= e.ElementSet {
return fmt.Errorf("maximum ElementSet reached: %d", e.ElementSet)
}
e.ElementSet++
return nil
}
// Walk modifies the Elements based on an under-specified random walk.
//
// Name, Id, and ElementSet are not changed.
func (e *Elements) Walk(minSteps, maxSteps int) error {
if maxSteps < minSteps || maxSteps == 0 {
return nil
}
steps := minSteps + rand.Intn(1+maxSteps-minSteps)
for i := 0; i < steps; i++ {
switch rand.Intn(6) {
case 0:
e.Inclination = stepDegrees(e.Inclination)
case 1:
e.RightAscension = stepDegrees(e.RightAscension)
case 2:
e.Eccentricity = stepEcc(e.Eccentricity)
case 3:
e.ArgOfPericenter = stepDegrees(e.ArgOfPericenter)
case 4:
e.MeanAnomaly = stepDegrees(e.MeanAnomaly)
case 5:
e.MeanMotion = stepMotion(e.MeanMotion)
// ToDo: Somehow update derivatives?
}
}
return nil
}
func rnd() float64 {
return 1 - 2*rand.Float64()
}
// stepDegrees moves +/- [0,0.01) degree.
func stepDegrees(d float64) float64 {
return d + rnd()/100
}
// stepEcc moves +/- [0,0.001) percent.
func stepEcc(x float64) float64 {
y := x * (1 + rnd()/1000)
if 1 <= y {
y = 1 - rand.Float64()/1000
}
if y <= 0 {
y = rand.Float64() / 1000
}
return y
}
// stepMotion moves +/- [0,0.0001) percent.
func stepMotion(x float64) float64 {
// ToDo: Something better.
y := x * (1 + rnd()/10000)
if y <= 0 {
y = 1 + rnd()/10
}
if y < 0 {
panic(y)
}
return y
}