Fixes for the crashes caused by disconnecting one odrive and connecting another while the GUI is open. Fixed numerical inputs to accept "0".

This commit is contained in:
PAJohnson
2020-10-23 21:11:26 -04:00
parent 91f3cdb293
commit 3df42396c0
11 changed files with 93 additions and 67 deletions
+24 -11
View File
@@ -58,8 +58,12 @@ def discovered_device(device):
while globals()['inUse']:
time.sleep(0.1)
globals()['odrives'][odrive_name] = device
globals()['odrives_status'][odrive_name] = True
print("Found " + str(serial_number))
print("odrive list: " + str([key for key in globals()['odrives'].keys()]))
# tell GUI the status of known ODrives (previously connected and then disconnected ODrives will be "False")
socketio.emit('odrives-status', json.dumps(globals()['odrives_status']))
# triggers a getODrives socketio message
socketio.emit('odrive-found')
def start_discovery():
@@ -68,9 +72,12 @@ def start_discovery():
shutdown = fibre.Event()
fibre.find_all("usb", None, discovered_device, shutdown, shutdown, log)
def handle_disconnect():
def handle_disconnect(odrive_name):
print("lost odrive")
#socketio.emit('odrive-disconnected')
globals()['odrives_status'][odrive_name] = False
# emit the whole list of odrive statuses
# in the GUI, mark and use status as ODrive state.
socketio.emit('odrives-status', json.dumps(globals()['odrives_status']))
@socketio.on('findODrives')
def getODrives(message):
@@ -115,8 +122,9 @@ def get_odrives(data):
odriveDict = {}
#for (index, odrv) in enumerate(globals()['odrives']):
# odriveDict["odrive" + str(index)] = dictFromRO(odrv)
for key in globals()['odrives'].keys():
odriveDict[key] = dictFromRO(globals()['odrives'][key])
for key in globals()['odrives_status'].keys():
if globals()['odrives_status'][key] == True:
odriveDict[key] = dictFromRO(globals()['odrives'][key])
globals()['inUse'] = False
emit('odrives', json.dumps(odriveDict))
@@ -126,10 +134,11 @@ def get_property(message):
# will be {"path": "odriveX.axisY.blah.blah"}
while globals()['inUse']:
time.sleep(0.1)
globals()['inUse'] = True
val = getVal(globals()['odrives'], message["path"].split('.'))
globals()['inUse'] = False
emit('ODriveProperty', json.dumps({"path": message["path"], "val": val}))
if globals()['odrives_status'][message["path"].split('.')[0]]:
globals()['inUse'] = True
val = getVal(globals()['odrives'], message["path"].split('.'))
globals()['inUse'] = False
emit('ODriveProperty', json.dumps({"path": message["path"], "val": val}))
@socketio.on('setProperty')
def set_property(message):
@@ -194,7 +203,7 @@ def postVal(odrives, keyList, value, argType):
else:
pass # dont support that type yet
except fibre.protocol.ChannelBrokenException:
handle_disconnect()
handle_disconnect(odrv)
except:
print("exception in postVal")
@@ -210,7 +219,7 @@ def getVal(odrives, keyList):
else:
return RO.get_value()
except fibre.protocol.ChannelBrokenException:
handle_disconnect()
handle_disconnect(odrv)
except:
print("exception in getVal")
return 0
@@ -235,7 +244,7 @@ def callFunc(odrives, keyList):
if isinstance(RO, fibre.remote_object.RemoteFunction):
RO.__call__()
except fibre.protocol.ChannelBrokenException:
handle_disconnect()
handle_disconnect(odrv)
except:
print("fcn call failed")
@@ -252,7 +261,11 @@ if __name__ == "__main__":
import odrive.utils # for dump_errors()
import fibre
# global for holding references to all connected odrives
globals()['odrives'] = {}
# global dict {'odriveX': True/False} where True/False reflects status of connection
# on handle_disconnect, set it to False. On connection, set it to True
globals()['odrives_status'] = {}
globals()['discovered_devices'] = []
# spinlock
globals()['inUse'] = False
-19
View File
@@ -56,9 +56,6 @@
:axis="axis.name"
:odrives="odrives"
></Axis>
<!--<div class="odrive-status">
ODrive:{{ODriveConnected}}
</div>-->
</div>
</div>
</template>
@@ -129,22 +126,6 @@ export default {
currentDash: function () {
return this.$store.state.currentDash;
},
ODriveConnected: function () {
// if server and odrive disconnected, disconnected
// if server connected and odrive disco, connecting
// if server and odrive connected, connected
let ret;
if (this.$store.state.serverConnected && this.$store.state.ODriveConnected) {
ret = "connected";
}
else if (this.$store.state.serverConnected && !this.$store.state.ODriveConnected) {
ret = "connecting...";
}
else {
ret = "disconnected";
}
return ret;
},
samplingText: function () {
let ret;
if (this.$store.state.sampling) {
+20 -9
View File
@@ -2,7 +2,7 @@
<div
class="axis"
@click.self="showError = !showError;"
:class="{ noError: !error, error: error}"
:class="{inactive: !connected, noError: !error, error: error}"
>
{{ axis }}
<div v-show="showError" class="error-popup card" @click.self="showError = !showError">
@@ -110,6 +110,9 @@ export default {
};
},
computed: {
connected() {
return this.$store.state.ODrivesConnected[this.axis.split('.')[0]];
},
axisErrorMsg() {
let retMsg = "none";
let errCode = this.axisErr;
@@ -229,14 +232,18 @@ export default {
created() {
// set up timeout loop for grabbing axis error values
let update = () => {
fetchParam(this.axis + ".error");
fetchParam(this.axis + '.motor.error');
fetchParam(this.axis + '.controller.error');
fetchParam(this.axis + '.encoder.error');
this.axisErr = getVal(this.axis + '.error');
this.motorErr = getVal(this.axis + '.motor.error');
this.controllerErr = getVal(this.axis + '.controller.error');
this.encoderErr = getVal(this.axis + '.encoder.error');
// Do we have an active connection to the ODrive that contains this axis?
if (this.$store.state.ODrivesConnected[this.axis.split('.')[0]]) {
fetchParam(this.axis + ".error");
fetchParam(this.axis + '.motor.error');
fetchParam(this.axis + '.controller.error');
fetchParam(this.axis + '.encoder.error');
this.axisErr = getVal(this.axis + '.error');
this.motorErr = getVal(this.axis + '.motor.error');
this.controllerErr = getVal(this.axis + '.controller.error');
this.encoderErr = getVal(this.axis + '.encoder.error');
}
// ODrive not connected
setTimeout(update, 1000);
}
update();
@@ -270,4 +277,8 @@ export default {
color: black;
margin-left: 0px;
}
.inactive {
color: grey;
}
</style>
+1 -1
View File
@@ -40,7 +40,7 @@ export default {
methods: {
newVal: function (e) {
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.value = val;
console.log("input = " + e.target.value + ", val = " + this.value);
this.$store.commit("setActionVal", {dashID: this.dashID, actionID: this.id, val: this.value});
+2 -1
View File
@@ -47,8 +47,9 @@ export default {
putVal: function (e) {
let keys = this.path.split('.');
keys.shift();
console.log("input recieved: " + e.target.value);
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
putVal(keys.join('.'), val);
}
},
@@ -37,7 +37,7 @@ export default {
setBR(e) {
console.log("from setBR " + e.target.value);
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.brake_resistance = val;
let configStub = undefined;
configStub = {
@@ -26,7 +26,7 @@ export default {
methods: {
setCPR(e) {
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.cpr = val;
let configStub = undefined;
if (this.data.axis == "axis0") {
@@ -27,7 +27,7 @@ export default {
methods: {
setCPR(e) {
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.cpr = val;
let configStub = undefined;
if (this.data.axis == "axis0") {
@@ -100,7 +100,7 @@ export default {
},
setVelocityLimit(e) {
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.vel_limit = parseFloat(e.target.value);
this.vel_set = true;
this.sendConfig();
@@ -108,7 +108,7 @@ export default {
},
setCurrentLimit(e) {
let val = parseMath(e.target.value);
if (val != false) {
if (val !== false) {
this.current_lim = parseFloat(e.target.value);
this.current_set = true;
this.sendConfig();
+19 -8
View File
@@ -6,11 +6,17 @@ import * as socketio from "../comms/socketio.js";
// given a path like "odrive0.axis0.config.blah", return the value
export function getParam(path) {
let keys = path.split('.');
let odriveObj = store.state.odrives;
for (const key of keys) {
odriveObj = odriveObj[key];
if (store.state.ODrivesConnected[keys[0]]) {
let odriveObj = store.state.odrives;
for (const key of keys) {
odriveObj = odriveObj[key];
}
return odriveObj;
}
else {
console.log("getParam for " + path + " is for disconnected ODrive");
return undefined;
}
return odriveObj;
}
// wrapper for val field
@@ -51,10 +57,15 @@ export function parseMath(inString) {
export function putVal(path, value) {
console.log("path: " + path + ", val: " + value + ", type: " + typeof value);
socketio.sendEvent({
type: "setProperty",
data: {path: path, val: value, type: typeof value}
})
if (store.state.ODrivesConnected[path.split('.')[0]]) {
socketio.sendEvent({
type: "setProperty",
data: {path: path, val: value, type: typeof value}
});
}
else {
console.log("requesting " + path + " from disconnected odrive")
}
}
// path is path to function, args is list of parameters
+22 -13
View File
@@ -21,7 +21,7 @@ export default new Vuex.Store({
axes: Array,
odriveServerAddress: String,
serverConnected: Boolean,
ODriveConnected: false,
ODrivesConnected: Object,
serverOutput: [],
dashboards: [
{
@@ -95,6 +95,13 @@ export default new Vuex.Store({
state.odriveConfigs['writeAble'] = payload.writeAble;
state.odriveConfigs['writeAbleNumeric'] = payload.writeAbleNumeric;
},
setODrivesStatus(state, obj) {
// obj is {"odriveX": true/false}
for (const odrive of Object.keys(obj)){
state.ODrivesConnected[odrive] = obj[odrive];
console.log(state.ODrivesConnected);
}
},
setAxes(state, axes) {
state.axes = axes;
},
@@ -163,9 +170,6 @@ export default new Vuex.Store({
setServerStatus(state, val) {
state.serverConnected = val;
},
setODriveConnected(state, val) {
state.ODriveConnected = val;
},
removeCtrlFromDash(state, obj) {
// obj is {dash: dashID, path: control path}
for (const dash of state.dashboards) {
@@ -325,7 +329,6 @@ export default new Vuex.Store({
type: "odrive-found",
callback: () => {
console.log("odrive-found recieved from server");
context.commit("setODriveConnected", true);
context.dispatch("getOdrives");
}
})
@@ -370,15 +373,21 @@ export default new Vuex.Store({
});
socketio.addEventListener({
type: "odrive-disconnected",
callback: () => {
console.log("odrive disconnected");
context.commit("setODriveConnected", false);
console.log("restarting server...");
window.ipcRenderer.send('kill-server');
window.ipcRenderer.send('start-server');
context.dispatch('setServerAddress', context.state.odriveServerAddress);
callback: (odrive_name) => {
console.log(odrive_name + " disconnected");
//console.log("restarting server...");
//window.ipcRenderer.send('kill-server');
//window.ipcRenderer.send('start-server');
//context.dispatch('setServerAddress', context.state.odriveServerAddress);
}
})
});
socketio.addEventListener({
type: "odrives-status",
callback: (odrives_status) => {
console.log("From odrives-status msg " + odrives_status);
context.commit('setODrivesStatus', JSON.parse(odrives_status));
}
});
}
}
})