Skip to content
Snippets Groups Projects
Select Git revision
  • d15cbdd4905cf56d592ae8c559beab1e481139d8
  • master default protected
  • LUFA-170418
  • LUFA-151115
  • LUFA-140928
  • LUFA-140302
  • LUFA-130901
  • LUFA-130901-BETA
  • LUFA-130303
  • LUFA-120730
  • LUFA-120730-BETA
  • LUFA-120219
  • LUFA-120219-BETA
  • LUFA-111009
  • LUFA-111009-BETA
  • LUFA-110528
  • LUFA-110528-BETA
17 results

Descriptors.c

Blame
  • clStepClient.js 8.33 KiB
    /*
    clank-client.js
    
    clank controller client side
    
    Jake Read at the Center for Bits and Atoms
    (c) Massachusetts Institute of Technology 2020
    
    This work may be reproduced, modified, distributed, performed, and
    displayed for any purpose, but must acknowledge the open systems assembly protocol (OSAP) project.
    Copyright is retained and must be preserved. The work is provided as is;
    no warranty is provided, and users accept all liability.
    */
    
    'use strict'
    
    import OSAP from '../osapjs/core/osap.js'
    import { TS, PK, DK, AK, EP } from '../osapjs/core/ts.js'
    import NetRunner from '../osapjs/client/netrunner/osap-render.js'
    
    // the clank 'virtual machine'
    import ClStepVM from './clStepVM.js'
    
    import { AutoPlot } from '../osapjs/client/components/autoPlot.js'
    import { Button } from '../osapjs/client/interface/button.js'
    import { TextInput } from '../osapjs/client/interface/textInput.js'
    
    console.log("hello clank controller")
    
    // an instance of some osap capable thing (the virtual object)
    // that will appear on the network, be virtually addressable
    let osap = new OSAP()
    osap.name = "cl-step tuner client"
    
    // draws network, 
    let netrunner = new NetRunner(osap, 10, 760, false)
    
    // -------------------------------------------------------- THE VM
    
    // vm, 
    let vm = new ClStepVM(osap, TS.route().portf(0).portf(1).end())
    
    // -------------------------------------------------------- QUERY MAG
    
    let magDiagnosticsBtn = new Button(10, 10, 94, 14, 'mag?')
    magDiagnosticsBtn.onClick(() => {
      vm.getMagDiagnostics().then((result) => {
        console.log(result)
        magDiagnosticsBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        magDiagnosticsBtn.bad("err", 500)
      })
    })
    
    // -------------------------------------------------------- DO CALIB
    
    let runCalibBtn = new Button(10, 40, 94, 14, 'calibr8')
    runCalibBtn.onClick(() => {
      vm.runCalib().then(() => {
        runCalibBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        runCalibBtn.bad("err", 500)
      })
    })
    
    // -------------------------------------------------------- QUERY POSITION
    
    let posnLp = false
    let positionQueryBtn = new Button(10, 70, 94, 14, 'pos?')
    positionQueryBtn.onClick(() => {
      if (posnLp) {
        posnLp = false
      } else {
        let loop = () => {
          if (!posnLp) {
            positionQueryBtn.bad("halted", 500)
          } else {
            vm.getPosition().then((pos) => {
              $(positionQueryBtn.elem).text(pos.toFixed(3))
              setTimeout(loop, 10)
            }).catch((err) => {
              console.error(err)
              posnLp = false;
              setTimeout(loop, 10)
            })
          }
        }
        posnLp = true
        loop()
      }
    })
    
    // -------------------------------------------------------- LOOP SPEC
    
    let effortPlot = new AutoPlot(130, 10, 500, 210, 'effort')
    effortPlot.setHoldCount(500)
    //tempPlot.setYDomain(0, 100)
    effortPlot.redraw()
    
    let anglePlot = new AutoPlot(130, 230, 500, 210, 'angle reading')
    anglePlot.setHoldCount(500)
    //tempPlot.setYDomain(0, 100)
    anglePlot.redraw()
    
    let posEstPlot = new AutoPlot(130, 450, 500, 210, 'pos estimate')
    posEstPlot.setHoldCount(500)
    //tempPlot.setYDomain(0, 100)
    posEstPlot.redraw()
    
    let posDotPlot = new AutoPlot(130, 670, 500, 210, 'position dot')
    posDotPlot.setHoldCount(500)
    posDotPlot.redraw()
    
    let specLp = false
    let specPlotCount = 0
    let loopQueryBtn = new Button(10, 100, 94, 14, 'spec?')
    loopQueryBtn.onClick(() => {
      if (specLp) {
        specLp = false
      } else {
        let loop = () => {
          if (!specLp) {
            loopQueryBtn.bad("halted", 500)
          } else {
            vm.getSpec().then((spec) => {
              specPlotCount++
              effortPlot.pushPt([specPlotCount, spec.effort]); effortPlot.redraw()
              anglePlot.pushPt([specPlotCount, spec.angle]); anglePlot.redraw()
              posEstPlot.pushPt([specPlotCount, spec.posEstimate]); posEstPlot.redraw()
              posDotPlot.pushPt([specPlotCount, spec.posDot]); posDotPlot.redraw()
              setTimeout(loop, 10)
            }).catch((err) => {
              console.error(err)
              specLp = false;
              setTimeout(loop, 10)
            })
          }
        }
        specLp = true
        loop()
      }
    })
    
    // -------------------------------------------------------- RUN / MODE SWICH
    
    let runBtn = new Button(10, 130, 94, 14, 'run')
    runBtn.onClick(() => {
      vm.setMode("pid").then(() => {
        runBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        runBtn.bad("err", 500)
      })
    })
    
    let stopBtn = new Button(10, 160, 94, 14, 'stop')
    stopBtn.onClick(() => {
      vm.setMode("noop").then(() => {
        stopBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        stopBtn.bad("err", 500)
      })
    })
    
    // -------------------------------------------------------- PID Values
    
    let pVal = new TextInput(10, 190, 100, 20, '-0.09')
    let iVal = new TextInput(10, 220, 100, 20, '-0.002')
    let iLimVal = new TextInput(10, 250, 100, 20, '0.8')
    let dVal = new TextInput(10, 280, 100, 20, '-0.0003')
    let aVal = new TextInput(10, 310, 100, 20, '0.2')
    let aDotVal = new TextInput(10, 340, 100, 20, '0.05')
    
    let pidSetBtn = new Button(10, 370, 94, 14, 'set PID / a')
    pidSetBtn.onClick(() => {
      let p = parseFloat(pVal.value)
      let i = parseFloat(iVal.value)
      let ilim = parseFloat(iLimVal.value)
      let d = parseFloat(dVal.value)
      let a = parseFloat(aVal.value)
      let ad = parseFloat(aDotVal.value)
      if (Number.isNaN(p) || Number.isNaN(i) || Number.isNaN(d)) {
        pidSetBtn.bad("bad parse", 1000)
        return
      }
      vm.setPIDTerms([p, i, ilim, d]).then(() => {
        return vm.setAlphas([a, ad])
      }).then(() => {
        pidSetBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        pidSetBtn.bad("err", 1000)
      })
    })
    
    let angleRandoBtn = new Button(10, 400, 94, 14, 'targ')
    angleRandoBtn.onClick(() => {
      let targ = Math.random() * 360
      vm.setTarget(targ).then(() => {
        angleRandoBtn.good(`${targ.toFixed(3)}`, 250)
      }).catch((err) => {
        console.error(err)
        angleRandoBtn.bad("err", 500)
      })
    })
    
    let angleWrapBtn = new Button(10, 430, 94, 14, 'wrap')
    angleWrapBtn.onClick(() => {
      vm.setTarget(360.0).then(() => {
        angleWrapBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        angleWrapBtn.bad("err", 500)
      })
    })
    
    // units per revolution
    
    let uprVal = new TextInput(10, 460, 100, 20, '59.6929')
    
    let uprBtn = new Button(10, 490, 94, 14, 'upr')
    uprBtn.onClick(() => {
      let upr = parseFloat(uprVal.value)
      if(Number.isNaN(upr)){
        uprBtn.bad("bad parse", 500)
        return
      }
      vm.setUPR(upr).then(() => {
        uprBtn.good("ok", 500)
      }).catch((err) => {
        console.error(err)
        uprBtn.bad("err", 500)
      })
    })
    
    // -------------------------------------------------------- STARTUP LOCAL
    
    let wscVPort = osap.vPort()
    wscVPort.name = 'websocket client'
    wscVPort.maxSegLength = 1024
    
    let LOGPHY = false
    
    // to test these systems, the client (us) will kickstart a new process
    // on the server, and try to establish connection to it.
    console.log("making client-to-server request to start remote process,")
    console.log("and connecting to it w/ new websocket")
    // ok, let's ask to kick a process on the server,
    // in response, we'll get it's IP and Port,
    // then we can start a websocket client to connect there,
    // automated remote-proc. w/ vPort & wss medium,
    // for args, do '/processName.js?args=arg1,arg2'
    
    jQuery.get('/startLocal/osapl-usb-bridge.js', (res) => {
      if (res.includes('OSAP-wss-addr:')) {
        let addr = res.substring(res.indexOf(':') + 2)
        if (addr.includes('ws://')) {
          let status = EP.PORTSTATUS.OPENING
          wscVPort.status = () => { return status }
          console.log('starting socket to remote at', addr)
          let ws = new WebSocket(addr)
          // opens, 
          ws.onopen = (evt) => {
            status = EP.PORTSTATUS.OPEN
            // implement rx
            ws.onmessage = (msg) => {
              msg.data.arrayBuffer().then((buffer) => {
                let uint = new Uint8Array(buffer)
                if (LOGPHY) console.log('PHY WSC Recv')
                if (LOGPHY) TS.logPacket(uint)
                wscVPort.receive(uint)
              }).catch((err) => {
                console.error(err)
              })
            }
            // implement tx 
            wscVPort.send = (buffer) => {
              if (LOGPHY) console.log('PHY WSC Send', buffer)
              ws.send(buffer)
            }
          }
          ws.onerror = (err) => {
            status = EP.PORTSTATUS.CLOSED
            console.log('sckt err', err)
          }
          ws.onclose = (evt) => {
            status = EP.PORTSTATUS.CLOSED
            console.log('sckt closed', evt)
          }
        }
      } else {
        console.error('remote OSAP not established', res)
      }
    })