Skip to content

Commit fc2e247

Browse files
committed
Added Rover Computer
Added Rover mode in the flight computer. Rovers can now be controlled in 3 new ways: Target: The rover drives towards a set of coordinates while maintaining a specified speed. Coordinates can be entered manually or set by holding <modifier key> + left click. on the ground or map. Use left click in order to send the command on click. Heading: The rover orients itself towards a specified heading and maintains a specified speed. Fine: The rover either turns a specified noumber of degrees (right or left) or drives forward a specified distance, while maintaining a specified speed.
1 parent 4cc180c commit fc2e247

10 files changed

Lines changed: 1108 additions & 31 deletions

File tree

src/RemoteTech/FlightComputer/Commands/AbstractCommand.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public static ICommand LoadCommand(ConfigNode n, FlightComputer fc)
9494
case "CancelCommand": { command = new CancelCommand(); break; }
9595
case "TargetCommand": { command = new TargetCommand(); break; }
9696
case "EventCommand": { command = new EventCommand(); break; }
97+
case "DriveCommand": { command = new DriveCommand(); break; }
9798
}
9899

99100
if (command != null)
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System;
2+
using System.Text;
3+
using UnityEngine;
4+
5+
namespace RemoteTech.FlightComputer.Commands
6+
{
7+
public class DriveCommand : AbstractCommand
8+
{
9+
public enum DriveMode
10+
{
11+
Off,
12+
Turn,
13+
Distance,
14+
DistanceHeading,
15+
Coord
16+
}
17+
18+
[Persistent] public float steering;
19+
[Persistent] public float target;
20+
[Persistent] public float target2;
21+
[Persistent] public float speed;
22+
[Persistent] public DriveMode mode;
23+
24+
private bool mAbort;
25+
private RoverComputer mRoverComputer;
26+
27+
public override void Abort() { mAbort = true; }
28+
29+
public override bool Pop(FlightComputer f)
30+
{
31+
mRoverComputer = f.mRoverComputer;
32+
mRoverComputer.InitMode(this);
33+
return true;
34+
}
35+
36+
public override bool Execute(FlightComputer f, FlightCtrlState fcs)
37+
{
38+
if (mAbort) {
39+
fcs.wheelThrottle = 0.0f;
40+
f.Vessel.ActionGroups.SetGroup(KSPActionGroup.Brakes, true);
41+
return true;
42+
}
43+
44+
return f.mRoverComputer.Drive(this, fcs);
45+
}
46+
47+
public static DriveCommand Off()
48+
{
49+
return new DriveCommand() {
50+
mode = DriveMode.Off,
51+
TimeStamp = RTUtil.GameTime
52+
};
53+
}
54+
55+
public static DriveCommand Turn(float steering, float degrees, float speed)
56+
{
57+
return new DriveCommand() {
58+
mode = DriveMode.Turn,
59+
steering = steering,
60+
target = degrees,
61+
speed = speed,
62+
TimeStamp = RTUtil.GameTime
63+
};
64+
}
65+
66+
public static DriveCommand Distance(float distance, float steerClamp, float speed)
67+
{
68+
return new DriveCommand() {
69+
mode = DriveMode.Distance,
70+
steering = steerClamp,
71+
target = distance,
72+
speed = speed,
73+
TimeStamp = RTUtil.GameTime
74+
};
75+
}
76+
77+
public static DriveCommand DistanceHeading(float distance, float heading, float steerClamp, float speed)
78+
{
79+
return new DriveCommand() {
80+
mode = DriveMode.DistanceHeading,
81+
steering = steerClamp,
82+
target = distance,
83+
target2 = heading,
84+
speed = speed,
85+
TimeStamp = RTUtil.GameTime
86+
};
87+
}
88+
89+
public static DriveCommand Coord(float steerClamp, float latitude, float longitude, float speed)
90+
{
91+
return new DriveCommand() {
92+
mode = DriveMode.Coord,
93+
steering = steerClamp,
94+
target = latitude,
95+
target2 = longitude,
96+
speed = speed,
97+
TimeStamp = RTUtil.GameTime
98+
};
99+
}
100+
101+
public override String Description
102+
{
103+
get
104+
{
105+
StringBuilder s = new StringBuilder();
106+
switch (mode) {
107+
case DriveMode.Coord:
108+
s.Append("Drive to: ");
109+
s.Append(new Vector2(target, target2).ToString("0.000"));
110+
s.Append(" @ ");
111+
s.Append(RTUtil.FormatSI(Math.Abs(speed), "m/s"));
112+
if (mRoverComputer != null) {
113+
s.Append(" (");
114+
s.Append(RTUtil.FormatSI(mRoverComputer.Delta, "m"));
115+
s.Append(" ");
116+
s.Append(RTUtil.FormatDuration(mRoverComputer.DeltaT, false));
117+
s.Append(")"); ;
118+
}
119+
break;
120+
case DriveMode.Distance:
121+
s.Append("Drive: ");
122+
s.Append(RTUtil.FormatSI(target, "m"));
123+
if (speed > 0)
124+
s.Append(" forwards @");
125+
else
126+
s.Append(" backwards @");
127+
s.Append(RTUtil.FormatSI(Math.Abs(speed), "m/s"));
128+
if (mRoverComputer != null) {
129+
s.Append(" (");
130+
s.Append(RTUtil.FormatSI(mRoverComputer.Delta, "m"));
131+
s.Append(" ");
132+
s.Append(RTUtil.FormatDuration(mRoverComputer.DeltaT, false));
133+
s.Append(")"); ;
134+
}
135+
break;
136+
case DriveMode.Turn:
137+
s.Append("Turn: ");
138+
s.Append(target.ToString("0.0"));
139+
if (steering < 0)
140+
s.Append("° right @");
141+
else
142+
s.Append("° left @");
143+
s.Append(Math.Abs(steering).ToString("P"));
144+
s.Append(" Steering");
145+
if (mRoverComputer != null) {
146+
s.Append(" (");
147+
s.Append(mRoverComputer.Delta.ToString("F2"));
148+
s.Append("° ");
149+
s.Append(RTUtil.FormatDuration(mRoverComputer.DeltaT, false));
150+
s.Append(")"); ;
151+
}
152+
break;
153+
case DriveMode.DistanceHeading:
154+
s.Append("Drive: ");
155+
s.Append(RTUtil.FormatSI(target, "m"));
156+
s.Append(", Hdg: ");
157+
s.Append(target2.ToString("0"));
158+
s.Append("° @ ");
159+
s.Append(RTUtil.FormatSI(Math.Abs(speed), "m/s"));
160+
if (mRoverComputer != null) {
161+
s.Append(" (");
162+
s.Append(RTUtil.FormatSI(mRoverComputer.Delta, "m"));
163+
s.Append(" ");
164+
s.Append(RTUtil.FormatDuration(mRoverComputer.DeltaT, false));
165+
s.Append(")");
166+
}
167+
break;
168+
case DriveMode.Off:
169+
s.Append("Turn rover computer off");
170+
break;
171+
}
172+
173+
return s.ToString() + Environment.NewLine + base.Description;
174+
}
175+
}
176+
177+
public override string ShortName
178+
{
179+
get { return "Drive"; }
180+
}
181+
182+
}
183+
}

src/RemoteTech/FlightComputer/FlightComputer.cs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ public State Status
7979
private readonly SortedDictionary<int, ICommand> mActiveCommands = new SortedDictionary<int, ICommand>();
8080
private readonly List<ICommand> mCommandQueue = new List<ICommand>();
8181
private readonly PriorityQueue<DelayedFlightCtrlState> mFlightCtrlQueue = new PriorityQueue<DelayedFlightCtrlState>();
82-
82+
8383
private FlightComputerWindow mWindow;
8484
public FlightComputerWindow Window { get { if (mWindow != null) mWindow.Hide(); return mWindow = new FlightComputerWindow(this); } }
8585

86+
public RoverComputer mRoverComputer { get; private set; }
87+
8688
public FlightComputer(ISignalProcessor s)
8789
{
8890
SignalProcessor = s;
@@ -96,8 +98,11 @@ public FlightComputer(ISignalProcessor s)
9698
mActiveCommands[attitude.Priority] = attitude;
9799

98100
GameEvents.onVesselChange.Add(OnVesselChange);
101+
102+
mRoverComputer = new RoverComputer();
103+
mRoverComputer.SetVessel(Vessel);
99104
}
100-
105+
101106
/// <summary>
102107
/// After switching the vessel close the current flightcomputer.
103108
/// </summary>
@@ -161,7 +166,10 @@ public void OnUpdate()
161166
public void OnFixedUpdate()
162167
{
163168
if (Vessel == null)
169+
{
164170
Vessel = SignalProcessor.Vessel;
171+
mRoverComputer.SetVessel(Vessel);
172+
}
165173

166174
// only handle onFixedUpdate if the ship is unpacked
167175
if (Vessel.packed)
@@ -182,6 +190,7 @@ public void OnFixedUpdate()
182190
{
183191
SanctionedPilots.Clear();
184192
Vessel = SignalProcessor.Vessel;
193+
mRoverComputer.SetVessel(Vessel);
185194
}
186195
Vessel.OnFlyByWire = OnFlyByWirePre + Vessel.OnFlyByWire + OnFlyByWirePost;
187196

@@ -240,14 +249,15 @@ private void PopCommand()
240249
if (dc.ExtraDelay > 0)
241250
{
242251
dc.ExtraDelay -= TimeWarp.deltaTime;
243-
}
244-
else
252+
} else
245253
{
246-
if (SignalProcessor.Powered) {
254+
if (SignalProcessor.Powered)
255+
{
247256
// Note: depending on implementation, dc.Pop() may execute the event
248-
if (dc.Pop(this)) mActiveCommands [dc.Priority] = dc;
249-
} else {
250-
string message = String.Format ("[Flight Computer]: Out of power, cannot run \"{0}\" on schedule.", dc.ShortName);
257+
if (dc.Pop(this)) mActiveCommands[dc.Priority] = dc;
258+
} else
259+
{
260+
string message = String.Format("[Flight Computer]: Out of power, cannot run \"{0}\" on schedule.", dc.ShortName);
251261
ScreenMessages.PostScreenMessage(new ScreenMessage(
252262
message, 4.0f, ScreenMessageStyle.UPPER_LEFT
253263
), true);
@@ -309,20 +319,21 @@ public void initPIDParameters()
309319
// Probably because the ship is only half-initialized...
310320
public void updatePIDParameters()
311321
{
312-
if (Vessel != null) {
313-
Vector3d torque = SteeringHelper.GetTorque (Vessel,
322+
if (Vessel != null)
323+
{
324+
Vector3d torque = SteeringHelper.GetTorque(Vessel,
314325
Vessel.ctrlState != null ? Vessel.ctrlState.mainThrottle : 0.0f);
315-
var CoM = Vessel.findWorldCenterOfMass ();
316-
var MoI = Vessel.findLocalMOI (CoM);
326+
var CoM = Vessel.findWorldCenterOfMass();
327+
var MoI = Vessel.findLocalMOI(CoM);
317328

318-
Vector3d ratio = new Vector3d (
329+
Vector3d ratio = new Vector3d(
319330
torque.x != 0 ? MoI.x / torque.x : 0,
320331
torque.y != 0 ? MoI.y / torque.y : 0,
321332
torque.z != 0 ? MoI.z / torque.z : 0
322333
);
323334

324-
Tf = Mathf.Clamp ((float)ratio.magnitude / 20f, 2 * TimeWarp.fixedDeltaTime, 1f);
325-
Tf = Mathf.Clamp ((float)Tf, (float)TfMin, (float)TfMax);
335+
Tf = Mathf.Clamp((float)ratio.magnitude / 20f, 2 * TimeWarp.fixedDeltaTime, 1f);
336+
Tf = Mathf.Clamp((float)Tf, (float)TfMin, (float)TfMax);
326337
}
327338
initPIDParameters();
328339
}
@@ -341,7 +352,7 @@ public void orderCommandList()
341352
mCommandQueue.Clear();
342353

343354
// add the sorted queue
344-
foreach(var command in backupList)
355+
foreach (var command in backupList)
345356
{
346357
mCommandQueue.Add(command);
347358
}
@@ -368,7 +379,10 @@ public void load(ConfigNode n)
368379

369380
// Load the current vessel from signalprocessor if we've no on the flightcomputer
370381
if (Vessel == null)
382+
{
371383
Vessel = SignalProcessor.Vessel;
384+
mRoverComputer.SetVessel(Vessel);
385+
}
372386

373387
// Read Flightcomputer informations
374388
ConfigNode FlightNode = n.GetNode("FlightComputer");
@@ -384,7 +398,7 @@ public void load(ConfigNode n)
384398
foreach (ConfigNode cmdNode in ActiveCommands.nodes)
385399
{
386400
ICommand cmd = AbstractCommand.LoadCommand(cmdNode, this);
387-
401+
388402
if (cmd != null)
389403
{
390404
mActiveCommands[cmd.Priority] = cmd;
@@ -423,7 +437,7 @@ public void load(ConfigNode n)
423437
// and set the new extradelay based on the current time
424438
if (cmd.ExtraDelay > 0)
425439
{
426-
cmd.ExtraDelay = cmd.TimeStamp + cmd.ExtraDelay - RTUtil.GameTime;
440+
cmd.ExtraDelay = cmd.TimeStamp + cmd.ExtraDelay - RTUtil.GameTime;
427441
cmd.TimeStamp = RTUtil.GameTime;
428442

429443
// Are we ready to handle the command ?
@@ -434,8 +448,7 @@ public void load(ConfigNode n)
434448
// TODO: Need better text
435449
RTUtil.ScreenMessage("You missed the burn command!");
436450
continue;
437-
}
438-
else
451+
} else
439452
{
440453
// change the extra delay to x/100
441454
cmd.ExtraDelay = (qCounter) / 100;
@@ -460,7 +473,7 @@ public void Save(ConfigNode n)
460473

461474
ConfigNode ActiveCommands = new ConfigNode("ActiveCommands");
462475
ConfigNode Commands = new ConfigNode("Commands");
463-
476+
464477
foreach (KeyValuePair<int, ICommand> cmd in mActiveCommands)
465478
{
466479
cmd.Value.Save(ActiveCommands, this);

0 commit comments

Comments
 (0)