Skip to content

Commit 4fe8cdd

Browse files
committed
GearGlimpse Glowup
1 parent 03e442e commit 4fe8cdd

17 files changed

+164
-161
lines changed

Resources/Info.plist

+2-75
Original file line numberDiff line numberDiff line change
@@ -65,81 +65,8 @@
6565
<string>armv7</string>
6666
<string>arkit</string>
6767
</array>
68-
<key>UILaunchImageFile</key>
69-
<string>LaunchImage</string>
70-
<key>UILaunchImages</key>
71-
<array>
72-
<dict>
73-
<key>UILaunchImageMinimumOSVersion</key>
74-
<string>7.0</string>
75-
<key>UILaunchImageName</key>
76-
<string>LaunchImage</string>
77-
<key>UILaunchImageOrientation</key>
78-
<string>Portrait</string>
79-
<key>UILaunchImageSize</key>
80-
<string>{320, 480}</string>
81-
</dict>
82-
<dict>
83-
<key>UILaunchImageMinimumOSVersion</key>
84-
<string>7.0</string>
85-
<key>UILaunchImageName</key>
86-
<string>LaunchImage-700-568h</string>
87-
<key>UILaunchImageOrientation</key>
88-
<string>Portrait</string>
89-
<key>UILaunchImageSize</key>
90-
<string>{320, 568}</string>
91-
</dict>
92-
<dict>
93-
<key>UILaunchImageMinimumOSVersion</key>
94-
<string>7.0</string>
95-
<key>UILaunchImageName</key>
96-
<string>LaunchImage-Portrait</string>
97-
<key>UILaunchImageOrientation</key>
98-
<string>Portrait</string>
99-
<key>UILaunchImageSize</key>
100-
<string>{768, 1024}</string>
101-
</dict>
102-
<dict>
103-
<key>UILaunchImageMinimumOSVersion</key>
104-
<string>7.0</string>
105-
<key>UILaunchImageName</key>
106-
<string>LaunchImage-Landscape</string>
107-
<key>UILaunchImageOrientation</key>
108-
<string>Landscape</string>
109-
<key>UILaunchImageSize</key>
110-
<string>{768, 1024}</string>
111-
</dict>
112-
<dict>
113-
<key>UILaunchImageMinimumOSVersion</key>
114-
<string>8.0</string>
115-
<key>UILaunchImageName</key>
116-
<string>LaunchImage-800-667h</string>
117-
<key>UILaunchImageOrientation</key>
118-
<string>Portrait</string>
119-
<key>UILaunchImageSize</key>
120-
<string>{375, 667}</string>
121-
</dict>
122-
<dict>
123-
<key>UILaunchImageMinimumOSVersion</key>
124-
<string>8.0</string>
125-
<key>UILaunchImageName</key>
126-
<string>LaunchImage-800-Portrait-736h</string>
127-
<key>UILaunchImageOrientation</key>
128-
<string>Portrait</string>
129-
<key>UILaunchImageSize</key>
130-
<string>{414, 736}</string>
131-
</dict>
132-
<dict>
133-
<key>UILaunchImageMinimumOSVersion</key>
134-
<string>8.0</string>
135-
<key>UILaunchImageName</key>
136-
<string>LaunchImage-800-Landscape-736h</string>
137-
<key>UILaunchImageOrientation</key>
138-
<string>Landscape</string>
139-
<key>UILaunchImageSize</key>
140-
<string>{414, 736}</string>
141-
</dict>
142-
</array>
68+
<key>UILaunchStoryboardName</key>
69+
<string>LaunchScreen</string>
14370
<key>UISupportedInterfaceOrientations</key>
14471
<array>
14572
<string>UIInterfaceOrientationPortrait</string>

Resources/[email protected]

Whitespace-only changes.

Resources/LaunchImage-700-Landscape@2x~ipad.png

Whitespace-only changes.

Resources/LaunchImage-700-Landscape~ipad.png

Whitespace-only changes.

Resources/LaunchImage-700-Portrait@2x~ipad.png

Whitespace-only changes.

Resources/LaunchImage-700-Portrait~ipad.png

Whitespace-only changes.

Resources/[email protected]

Whitespace-only changes.

Resources/[email protected]

Whitespace-only changes.

Resources/[email protected]

Whitespace-only changes.

Resources/LaunchImage.png

Whitespace-only changes.

Resources/[email protected]

Whitespace-only changes.

RootViewController.swift

+35-49
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ class RootViewController: UIViewController, UIGestureRecognizerDelegate {
1010

1111
var hasPlacedField = false
1212

13-
var NTClient: NT4Client!
13+
var NTHandler: NetworkTablesHandler!
14+
15+
var statusLabel: PaddedLabel!
1416

1517
override func loadView() {
1618
super.loadView()
1719

18-
sceneView = ARSceneView(frame: self.view.frame)
20+
sceneView = ARSceneView(frame: UIScreen.main.bounds)
1921
sceneView.autoenablesDefaultLighting = true
2022
self.view.addSubview(sceneView)
2123
}
@@ -43,51 +45,40 @@ class RootViewController: UIViewController, UIGestureRecognizerDelegate {
4345
robotNode = robot
4446
// Create a dummy node so that I can offset the position of the robot
4547
let dummyNode = SCNNode()
46-
dummyNode.position = SCNVector3(0.35, -0.35, -0.8)
48+
dummyNode.position = SCNVector3(0.35, -0.35, -0.875)
4749
dummyNode.addChildNode(robotNode)
4850
fieldNode.addChildNode(dummyNode)
49-
50-
51-
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
52-
tapGestureRecognizer.delegate = self
53-
sceneView.addGestureRecognizer(tapGestureRecognizer)
54-
55-
let rotateGestureRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate))
56-
rotateGestureRecognizer.delegate = self
57-
sceneView.addGestureRecognizer(rotateGestureRecognizer)
58-
59-
let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
60-
pinchGestureRecognizer.delegate = self
61-
sceneView.addGestureRecognizer(pinchGestureRecognizer)
62-
63-
let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
64-
doubleTapGestureRecognizer.delegate = self
65-
doubleTapGestureRecognizer.numberOfTapsRequired = 2
66-
sceneView.addGestureRecognizer(doubleTapGestureRecognizer)
67-
68-
NTClient = NT4Client(appName: "ARKit", serverBaseAddr: "192.168.1.130", onTopicAnnounce: { topic in
69-
NSLog("Announced topic: \(topic.name)")
70-
}, onTopicUnannounce: { topic in
71-
NSLog("Unannounced topic: \(topic.name)")
72-
}, onNewTopicData: { topic, timestamp, data in
73-
NSLog("New data for topic \(topic.name): \(data)")
74-
if topic.name == "/SmartDashboard/Field/Robot" {
75-
// [x, y, rot (degrees)]
76-
let newPos = topic.getDoubleArray();
77-
// The data is in meters relative to the field center (in the field model scale) so we need to scale it to the ARKit scale
78-
self.robotNode.position = SCNVector3(-newPos![0] + 8.25, 0, newPos![1] - 4)
79-
self.robotNode.eulerAngles.y = Float(newPos![2] * .pi / 180)
80-
}
81-
}, onConnect: {
82-
NSLog("Connected to NetworkTables")
83-
}, onDisconnect: ((String, UInt16) -> Void)? { reason, code in
84-
NSLog("Disconnected from NetworkTables, reason: \(reason), code: \(code)")
85-
})
86-
87-
NTClient.connect()
88-
NTClient.subscribe(key: "/SmartDashboard/Field/Robot", periodic: 0.001)
51+
52+
addGestureRecognizers()
53+
statusLabel = PaddedLabel()
54+
55+
statusLabel.text = "NT: Disconnected"
56+
statusLabel.font = UIFont.systemFont(ofSize: 14)
57+
statusLabel.textColor = UIColor.white
58+
statusLabel.backgroundColor = UIColor.red.withAlphaComponent(0.4)
59+
statusLabel.textAlignment = .center
60+
statusLabel.layer.cornerRadius = 10
61+
statusLabel.layer.masksToBounds = true
62+
statusLabel.sizeToFit()
63+
statusLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
64+
statusLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
65+
66+
statusLabel.leftInset = 10
67+
statusLabel.rightInset = 10
68+
69+
statusLabel.translatesAutoresizingMaskIntoConstraints = false
70+
sceneView.addSubview(statusLabel)
71+
NSLayoutConstraint.activate([
72+
statusLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
73+
statusLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
74+
statusLabel.heightAnchor.constraint(equalToConstant: 30)
75+
])
76+
77+
NTHandler = NetworkTablesHandler(robotNode: robotNode, statusLabel: statusLabel)
78+
NTHandler.connect()
8979
}
9080

81+
// Done to allow rotation and pinch gestures to work simultaneously
9182
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
9283
return true
9384
}
@@ -97,15 +88,10 @@ class RootViewController: UIViewController, UIGestureRecognizerDelegate {
9788
sceneView.session.pause()
9889
}
9990

91+
// This is done to make sure the ARSceneView is resized when the device is rotated
10092
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
10193
super.viewWillTransition(to: size, with: coordinator)
10294

10395
sceneView.frame = CGRect(origin: .zero, size: size)
10496
}
105-
106-
// When the app is brought to the foreground, resume the WS connection
107-
override func viewWillAppear(_ animated: Bool) {
108-
super.viewWillAppear(animated)
109-
NTClient.connect()
110-
}
11197
}

compile_commands.json

+1-1
Large diffs are not rendered by default.

src/GestureRecognizers.swift

+40-28
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@ import UIKit
33
import ARKit
44

55
extension RootViewController {
6+
7+
func addGestureRecognizers(){
8+
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
9+
tapGestureRecognizer.delegate = self
10+
sceneView.addGestureRecognizer(tapGestureRecognizer)
11+
12+
let rotateGestureRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(handleRotate))
13+
rotateGestureRecognizer.delegate = self
14+
sceneView.addGestureRecognizer(rotateGestureRecognizer)
15+
16+
let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
17+
pinchGestureRecognizer.delegate = self
18+
sceneView.addGestureRecognizer(pinchGestureRecognizer)
19+
20+
let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(openConfig))
21+
longPressGestureRecognizer.delegate = self
22+
longPressGestureRecognizer.minimumPressDuration = 0.5
23+
sceneView.addGestureRecognizer(longPressGestureRecognizer)
24+
25+
// Prevent the tap gesture from being recognized until the long press gesture fails
26+
tapGestureRecognizer.require(toFail: longPressGestureRecognizer)
27+
}
28+
629
@objc func handleTap(sender: UITapGestureRecognizer) {
730
let tapLocation = sender.location(in: sceneView)
831
guard let query = sceneView.raycastQuery(from: tapLocation, allowing: .estimatedPlane, alignment: .horizontal) else {
@@ -37,36 +60,25 @@ extension RootViewController {
3760
sender.scale = 1.0
3861
}
3962

40-
@objc func handleDoubleTap(sender: UITapGestureRecognizer) {
41-
let alert = UIAlertController(title: "Configuration", message: "Configure the robot", preferredStyle: .alert)
63+
@objc func openConfig(sender: UITapGestureRecognizer) {
64+
let alert = UIAlertController(title: "Configuration", message: "Configure GearGlimpse", preferredStyle: .alert)
65+
alert.addTextField { (textField) in
66+
textField.placeholder = "IP Address"
67+
textField.text = UserDefaults.standard.string(forKey: "ip")
68+
}
4269
alert.addTextField { (textField) in
43-
// Default value
44-
textField.text = "192.168.1.130"
70+
textField.placeholder = "Robot Key"
71+
textField.text = UserDefaults.standard.string(forKey: "robotKey")
4572
}
46-
alert.addAction(UIAlertAction(title: "Connect", style: .default, handler: { [weak alert] (_) in
47-
let textField = alert?.textFields![0]
48-
self.NTClient.disconnect()
49-
self.NTClient = NT4Client(appName: "ARKit", serverBaseAddr: textField!.text!,
50-
onTopicAnnounce: { topic in
51-
NSLog("Announced topic: \(topic.name)")
52-
}, onTopicUnannounce: { topic in
53-
NSLog("Unannounced topic: \(topic.name)")
54-
}, onNewTopicData: { topic, timestamp, data in
55-
NSLog("New data for topic \(topic.name): \(data)")
56-
if topic.name == "/SmartDashboard/Field/Robot" {
57-
// [x, y, rot (degrees)]
58-
let newPos = topic.getDoubleArray();
59-
// The data is in meters relative to the field center (in the field model scale) so we need to scale it to the ARKit scale
60-
self.robotNode.position = SCNVector3(-newPos![0] + 8.25, 0, newPos![1] - 4)
61-
self.robotNode.eulerAngles.y = Float(newPos![2] * .pi / 180)
62-
}
63-
}, onConnect: {
64-
NSLog("Connected to NetworkTables")
65-
}, onDisconnect: ((String, UInt16) -> Void)? { reason, code in
66-
NSLog("Disconnected from NetworkTables, reason: \(reason), code: \(code)")
67-
})
68-
self.NTClient.connect()
69-
self.NTClient.subscribe(key: "/SmartDashboard/Field/Robot", periodic: 0.001)
73+
let connected = NTHandler.client.serverConnectionActive
74+
alert.addAction(UIAlertAction(title: connected ? "Reconnect" : "Connect", style: .default, handler: { [weak alert] (_) in
75+
let ipField = alert?.textFields![0]
76+
let robotKeyField = alert?.textFields![1]
77+
self.NTHandler.ip = ipField!.text
78+
self.NTHandler.robotKey = robotKeyField!.text
79+
self.NTHandler.connect()
80+
UserDefaults.standard.set(ipField!.text!, forKey: "ip")
81+
UserDefaults.standard.set(robotKeyField!.text!, forKey: "robotKey")
7082
}))
7183
self.present(alert, animated: true, completion: nil)
7284
}

src/NetworkTables/NT4Client.swift

+9-8
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,9 @@ class NT4Client: WebSocketDelegate {
1414
var onConnect: (() -> Void)?
1515
var onDisconnect: ((String, UInt16) -> Void)?
1616

17-
var serverBaseAddr: String
1817
var ws: WebSocket?
1918
var timestampInterval: Timer?
2019
var disconnectTimeout: Timer?
21-
var serverAddr = ""
2220
var serverConnectionActive = false
2321
var serverConnectionRequested = false
2422
var serverTimeOffset_us: Int?
@@ -30,22 +28,22 @@ class NT4Client: WebSocketDelegate {
3028

3129
var queuedSubscriptions = [NTSubscription]()
3230

33-
init(appName: String, serverBaseAddr: String, onTopicAnnounce: ((NTTopic) -> Void)?, onTopicUnannounce: ((NTTopic) -> Void)?, onNewTopicData: ((NTTopic, Int64, Any) -> Void)?, onConnect: (() -> Void)?, onDisconnect: ((String, UInt16) -> Void)?) {
31+
32+
init(appName: String, onTopicAnnounce: ((NTTopic) -> Void)?, onTopicUnannounce: ((NTTopic) -> Void)?, onNewTopicData: ((NTTopic, Int64, Any) -> Void)?, onConnect: (() -> Void)?, onDisconnect: ((String, UInt16) -> Void)?) {
3433
self.appName = appName
35-
self.serverBaseAddr = serverBaseAddr
3634
self.onTopicAnnounce = onTopicAnnounce
3735
self.onTopicUnannounce = onTopicUnannounce
3836
self.onNewTopicData = onNewTopicData
3937
self.onConnect = onConnect
4038
self.onDisconnect = onDisconnect
4139
}
4240

43-
func connect(){
41+
func connect(serverBaseAddr: String){
4442
if serverConnectionActive {
4543
return
4644
}
4745
serverConnectionRequested = true
48-
serverAddr = "ws://" + serverBaseAddr + ":" + String(PORT) + "/nt/" + appName
46+
let serverAddr = "ws://" + serverBaseAddr + ":" + String(PORT) + "/nt/" + appName
4947
NSLog("Connecting to \(serverAddr)")
5048
let url = URL(string: serverAddr)!
5149
let urlRequest = URLRequest(url: url)
@@ -57,6 +55,7 @@ class NT4Client: WebSocketDelegate {
5755
func disconnect(){
5856
if serverConnectionActive {
5957
ws?.disconnect()
58+
serverConnectionActive = false
6059
}
6160
}
6261

@@ -148,8 +147,10 @@ class NT4Client: WebSocketDelegate {
148147
serverConnectionActive = false
149148
onDisconnect?("Error", 0)
150149
NSLog("An error occurred")
151-
case .peerClosed:
152-
break
150+
case .peerClosed:
151+
serverConnectionActive = false
152+
onDisconnect?("Peer closed", 0)
153+
NSLog("Peer closed")
153154
}
154155
}
155156

0 commit comments

Comments
 (0)