Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Jake Read
rndmc
Commits
26bbd9bf
Commit
26bbd9bf
authored
Feb 09, 2019
by
Jake Read
Browse files
ready for sww, some improvements to go
parent
b08b0c28
Changes
10
Hide whitespace changes
Inline
Side-by-side
canvas.js
View file @
26bbd9bf
...
...
@@ -6,7 +6,6 @@ const Programs = require('./programs.js')
// the program object: real simple, just has a description, and a 'modules'
var
program
=
Programs
.
new
(
'
new program
'
)
var
canvas
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/ui/threeCanvas.js
'
)
Programs
.
setUI
(
canvas
,
200
,
200
)
...
...
littlerascal.js
0 → 100644
View file @
26bbd9bf
// business
const
Reps
=
require
(
'
./reps.js
'
)
const
Programs
=
require
(
'
./programs.js
'
)
// the program object: real simple, just has a description, and a 'modules'
var
program
=
Programs
.
new
(
'
new program
'
)
/* ok
- new plotter
- ack four
- go to pos block
- neil:mm adjust
- git push
- add y axis network wait ?
*/
// das link
var
link
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/hardware/atkseriallink.js
'
)
link
.
startUp
()
link
.
state
.
log
=
true
let
steps
=
10
// x motor
var
xm
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/hardware/atkstepper.js
'
)
xm
.
route
.
route
=
'
0,0
'
xm
.
state
.
route
=
'
0,0
'
xm
.
state
.
spu
=
steps
xm
.
state
.
axis
=
'
X
'
// y left and right
var
ylm
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/hardware/atkstepper.js
'
)
ylm
.
route
.
route
=
'
0,1
'
ylm
.
state
.
route
=
'
0,1
'
ylm
.
state
.
spu
=
steps
ylm
.
state
.
axis
=
'
Y
'
var
ylr
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/hardware/atkstepper.js
'
)
ylr
.
route
.
route
=
'
0,2
'
ylr
.
state
.
route
=
'
0,2
'
ylr
.
state
.
spu
=
-
steps
ylr
.
state
.
axis
=
'
Y
'
// z motor
var
zm
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/hardware/atkstepper.js
'
)
zm
.
route
.
route
=
'
0,3
'
zm
.
state
.
route
=
'
0,3
'
zm
.
state
.
spu
=
-
steps
zm
.
state
.
axis
=
'
Z
'
var
planner
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/motion/simplanner.js
'
)
planner
.
state
.
minSpeed
=
1
planner
.
state
.
accel
=
300
planner
.
netWindow
=
1
/*
var simplanner = Programs.loadModuelFromSource(program, './modules/motion/simplanner.js')
let ahMove = {
axes: ['X', 'Y', 'Z'],
p1: [10, 10, 10],
p2: [20, 20, 20],
vector: [10, 10, 10],
cruise: 100,
entry: 10,
exit: 10,
accel: 100
}
*/
// what doth planner output ?
/*
var newMove = {
axes: axes,
p1: p1,
p2: p2,
cruise: move.speed,
entry: 0,
exit: 0,
accel: state.accel
}
*/
// can we write something that just steps through moves one by one ?
// HOOKUP
planner
.
outputs
.
moves
.
attach
(
xm
.
inputs
.
trapezoid
)
planner
.
outputs
.
moves
.
attach
(
ylm
.
inputs
.
trapezoid
)
planner
.
outputs
.
moves
.
attach
(
ylr
.
inputs
.
trapezoid
)
planner
.
outputs
.
moves
.
attach
(
zm
.
inputs
.
trapezoid
)
xm
.
outputs
.
ack
.
attach
(
planner
.
inputs
.
acks
)
ylm
.
outputs
.
ack
.
attach
(
planner
.
inputs
.
acks
)
zm
.
outputs
.
ack
.
attach
(
planner
.
inputs
.
acks
)
let
moveToPlanner
=
{
position
:
{
X
:
20
,
Y
:
10
,
Z
:
5
},
speed
:
150
}
link
.
onOpen
=
function
(){
// planner.inputs.instruction.fn(moveToPlanner)
//xm.inputs.trapezoid.fn(ahMove)
}
// ws input
var
sockit
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/pipes/websocket.js
'
)
var
np
=
Programs
.
loadModuleFromSource
(
program
,
'
./modules/motion/neilparse.js
'
)
sockit
.
outputs
.
data
.
attach
(
np
.
inputs
.
array
)
np
.
outputs
.
move
.
attach
(
planner
.
inputs
.
instruction
)
planner
.
outputs
.
moveComplete
.
attach
(
np
.
inputs
.
shift
)
// UI HOOKUP
Programs
.
setView
(
program
,
{
scale
:
0.5
,
translate
:
[
-
160
,
-
30
],
origin
:
[
200
,
120
]
})
let
top
=
100
let
motorbar
=
1200
let
motorspace
=
400
Programs
.
setUI
(
sockit
,
top
,
top
)
Programs
.
setUI
(
np
,
600
,
top
)
Programs
.
setUI
(
link
,
1800
,
top
)
Programs
.
setUI
(
xm
,
motorbar
,
top
)
Programs
.
setUI
(
ylm
,
motorbar
,
top
+
motorspace
)
Programs
.
setUI
(
ylr
,
motorbar
,
top
+
2
*
motorspace
)
Programs
.
setUI
(
zm
,
motorbar
,
top
+
3
*
motorspace
)
Programs
.
setUI
(
planner
,
600
,
450
)
// UI
const
View
=
require
(
'
./views.js
'
)
View
.
startHttp
()
View
.
startWs
()
Programs
.
assignSocket
(
View
.
uiSocket
)
View
.
assignProgram
(
program
)
\ No newline at end of file
modules/hardware/atkseriallink.js
View file @
26bbd9bf
...
...
@@ -94,6 +94,7 @@ function ATKSerialLink() {
//state.portStatus = 'opening'
serialport
.
on
(
'
open
'
,
function
()
{
state
.
portStatus
=
'
open
'
atkSerialLink
.
onOpen
()
})
serialport
.
on
(
'
error
'
,
function
(
err
)
{
state
.
portStatus
=
err
.
message
...
...
@@ -103,6 +104,10 @@ function ATKSerialLink() {
}
}
atkSerialLink
.
onOpen
=
function
()
{
// null 4 now ...
}
/*
------------------------------------------------------
PACKETS TO HARDWARE
...
...
modules/hardware/atkstepper.js
View file @
26bbd9bf
...
...
@@ -47,7 +47,7 @@ function Stepper() {
})
state
.
axis
=
'
X
'
state
.
spu
=
20
0
// steps per unit
state
.
spu
=
8
0
// steps per unit
state
.
rawMove
=
-
10
var
ui
=
stepper
.
ui
...
...
@@ -191,7 +191,7 @@ function Stepper() {
console
.
log
(
dMove
)
}
if
(
verbos
e
)
console
.
log
(
'
------------------- DMOVE
'
,
state
.
axis
,
dMove
.
steps
)
if
(
tru
e
)
console
.
log
(
'
------------------- DMOVE
'
,
state
.
axis
,
dMove
)
var
packet
=
new
Array
()
// step blocks are #131
...
...
modules/motion/neilparse.js
0 → 100644
View file @
26bbd9bf
// boilerplate atkapi header
const
JSUnit
=
require
(
'
../../src/jsunit.js
'
)
let
Input
=
JSUnit
.
Input
let
Output
=
JSUnit
.
Output
let
State
=
JSUnit
.
State
// unit to convert neil's mods-output arrays into human readable move objects
// probably do flow control here also ?
function
NeilParser
()
{
var
neilParser
=
{
description
:
{
name
:
'
neilParser Parser
'
,
alt
:
'
line of neilParser -> points
'
}
}
// log more
var
verbose
=
false
let
npList
=
null
// one caveat here is that we can't dynamically add objects to this,
// or they don't get getter / settered when we do
neilParser
.
state
=
State
()
var
state
=
neilParser
.
state
state
.
lift
=
50
state
.
moveSpeed
=
200
state
.
plungeSpeed
=
50
state
.
jogSpeed
=
600
state
.
listLength
=
0
neilParser
.
inputs
=
{
array
:
Input
(
'
array
'
,
(
arr
)
=>
{
let
list
=
writeMoveObjects
(
arr
)
console
.
log
(
'
have list
'
,
list
)
npList
=
list
state
.
listLength
=
npList
.
length
// throw it out
neilParser
.
outputs
.
newList
.
emit
(
1
)
onShift
()
}),
shift
:
Input
(
'
event
'
,
(
arg
)
=>
{
onShift
()
})
}
neilParser
.
outputs
=
{
move
:
Output
(
'
move
'
),
newList
:
Output
(
'
event
'
)
}
function
writeMoveObjects
(
arr
)
{
// arr[i] are segments,
// between arr[i] instances, we put a z-lift and then
// a z-drop
if
(
Array
.
isArray
(
arr
))
{
let
flat
=
new
Array
()
for
(
var
i
=
0
;
i
<
arr
.
length
;
i
++
)
{
flat
.
push
(
arr
[
i
][
0
])
flat
.
push
(
'
z down move
'
)
flat
=
flat
.
concat
(
arr
[
i
].
slice
(
1
))
flat
.
push
(
'
z up move
'
)
}
// console.log('FLATTENED TO', flat)
// add header
flat
.
splice
(
0
,
0
,
'
z up move
'
)
// and return home
flat
.
push
([
0
,
0
])
// make a list of objs
let
list
=
new
Array
()
// this is actually stateful ... jogging or not
let
upState
=
false
for
(
var
j
=
0
;
j
<
flat
.
length
;
j
++
)
{
if
(
Array
.
isArray
(
flat
[
j
]))
{
let
move
=
{
position
:
{
X
:
flat
[
j
][
0
],
Y
:
flat
[
j
][
1
]
}
}
if
(
upState
)
{
move
.
speed
=
state
.
jogSpeed
}
else
{
move
.
speed
=
state
.
moveSpeed
}
list
.
push
(
move
)
}
else
if
(
flat
[
j
]
===
'
z up move
'
)
{
upState
=
true
list
.
push
({
position
:
{
Z
:
state
.
lift
},
speed
:
state
.
plungeSpeed
})
}
else
if
(
flat
[
j
]
===
'
z down move
'
)
{
upState
=
false
list
.
push
({
position
:
{
Z
:
0
},
speed
:
state
.
plungeSpeed
})
}
}
return
list
}
else
{
console
.
log
(
'
NEIL PARSE: err: not an array
'
)
}
}
function
onShift
()
{
if
(
npList
!=
null
&&
npList
.
length
>
0
)
{
neilParser
.
outputs
.
move
.
emit
(
npList
.
shift
())
state
.
listLength
=
npList
.
length
}
else
{
console
.
log
(
'
NP Completes Moves
'
)
}
}
return
neilParser
}
// export the module
module
.
exports
=
NeilParser
\ No newline at end of file
modules/motion/simplanner.js
0 → 100644
View file @
26bbd9bf
// boilerplate atkapi header
const
JSUnit
=
require
(
'
../../src/jsunit.js
'
)
let
Input
=
JSUnit
.
Input
let
Output
=
JSUnit
.
Output
let
State
=
JSUnit
.
State
// interface elements
const
JSUI
=
require
(
'
../../src/jsui.js
'
)
let
UI
=
JSUI
.
UI
// descartes, to you
const
DCRT
=
require
(
'
../../src/cartesian.js
'
)
const
MJS
=
require
(
'
mathjs
'
)
// planner consumes target moves (i.e. segments having uniform speed throughout)
// and subjects them to acceleration constraints
function
Planner
()
{
var
planner
=
{
description
:
{
name
:
'
Lookahead-Motion-Planner
'
,
alt
:
'
movements -> acceleration planned moves
'
}
}
// log more
var
verbose
=
false
planner
.
state
=
State
()
var
state
=
planner
.
state
// reference pass attempt?
state
.
axisIDs
=
'
X,Y,Z
'
state
.
onUiChange
(
'
axisIDs
'
,
axisIDUpdate
)
state
.
accel
=
200
// units/s/s
state
.
minSpeed
=
1
// units/s
state
.
position
=
[
0
,
0
,
0
]
// should be grn / red button ...
state
.
isRunning
=
1
state
.
onUiChange
(
'
isRunning
'
,
netStateRefresh
)
state
.
netWindow
=
1
state
.
netState
=
[
0
,
0
,
0
]
planner
.
ui
=
UI
()
var
ui
=
planner
.
ui
ui
.
addElement
(
'
startStopButton
'
,
'
ui/uiButton.js
'
)
ui
.
startStopButton
.
subscribe
(
'
onload
'
,
function
(
msg
)
{
ui
.
startStopButton
.
send
({
calls
:
'
setText
'
,
argument
:
'
start / stop planner
'
})
})
ui
.
startStopButton
.
subscribe
(
'
onclick
'
,
onStartStop
)
planner
.
inputs
=
{
instruction
:
Input
(
'
move instruction
'
,
onNewInstruction
),
acks
:
Input
(
'
move acknowledgement
'
,
onAck
),
run
:
Input
(
'
boolean
'
,
onRunInstruction
)
}
planner
.
outputs
=
{
moves
:
Output
(
'
move instruction
'
),
moveComplete
:
Output
(
'
number
'
)
}
// we'll use one of these to assert / do things
// after the module is loaded, and state is copied etc
// i.e. one thing we can do is assert a starting value
planner
.
init
=
function
()
{
state
.
isRunning
=
0
state
.
netState
=
[
0
,
0
,
0
]
}
/*
------------------------------------------------------
UPDATING / SETUP
------------------------------------------------------
*/
function
onAck
(
msg
)
{
//console.log("Planner onAck:", msg)
// update position, net states, run netCheck
var
axes
=
state
.
axisIDs
.
split
(
'
,
'
)
var
match
=
axes
.
indexOf
(
msg
.
axis
)
if
(
match
!==
-
1
)
{
// HERE is a hack, for our state-updating system doesn't yet accomodate arrays
var
newPos
=
state
.
position
.
slice
(
0
)
newPos
[
match
]
+=
msg
.
increment
state
.
position
=
newPos
var
newNetState
=
state
.
netState
.
slice
(
0
)
newNetState
[
match
]
-=
1
state
.
netState
=
newNetState
if
(
verbose
)
console
.
log
(
'
NEW NET STATE
'
,
newNetState
)
}
else
{
console
.
log
(
'
ERR in PLANNER: missed axis on ack from stepper
'
)
}
netStateRefresh
()
}
function
netStateRefresh
()
{
// check if received all four,
// send a packet
var
ns
=
state
.
netState
var
i
=
0
// check equality
while
(
ns
[
i
]
==
ns
[
i
+
1
])
{
i
++
// console.log('EQUALITY LOOP')
if
(
i
>
ns
.
length
-
1
)
{
break
}
}
if
(
i
==
ns
.
length
-
1
)
{
console
.
log
(
'
Planner confirms Move Complete
'
)
planner
.
outputs
.
moveComplete
.
emit
(
1
)
}
}
function
onRunInstruction
(
boolean
)
{
if
(
boolean
)
{
if
(
state
.
isRunning
)
{
// already running, do nothing
}
else
{
state
.
isRunning
=
1
netStateRefresh
()
}
}
else
{
if
(
state
.
isRunning
)
{
state
.
isRunning
=
0
}
else
{
// oy
}
}
}
function
axisIDUpdate
()
{
var
axes
=
state
.
axisIDs
.
split
(
'
,
'
)
var
position
=
new
Array
(
axes
.
length
)
position
.
fill
(
0
)
var
packetState
=
new
Array
(
axes
.
length
)
for
(
i
in
axes
)
{
position
.
push
(
0
)
packetState
.
push
(
0
)
// could do
//planner.outputs[axes[i]] = Output('move instruction')
}
state
.
position
=
position
state
.
packetState
=
packetState
console
.
log
(
planner
)
}
function
onStartStop
()
{
if
(
state
.
isRunning
)
{
state
.
isRunning
=
0
}
else
{
state
.
isRunning
=
1
netStateRefresh
()
}
}
function
sendMoveToNetwork
(
move
)
{
for
(
i
in
state
.
netState
)
{
state
.
netState
[
i
]
++
}
state
.
netState
=
state
.
netState
planner
.
outputs
.
moves
.
emit
(
move
)
}
/*
------------------------------------------------------
ENTRY POINTS
------------------------------------------------------
*/
function
onNewInstruction
(
move
)
{
// our axis
var
axes
=
state
.
axisIDs
.
split
(
'
,
'
)
// we'll make a new move object
// start and end points, and axes to track
var
p1
=
[]
var
p2
=
new
Array
(
axes
.
length
)
p2
.
fill
(
0
)
// start point is current pos ... one at a time in simplanner
p1
=
state
.
position
// now pick out new deltas
for
(
i
in
axes
)
{
var
key
=
axes
[
i
]
if
(
move
.
position
[
key
]
!=
null
)
{
// some new pos,
p2
[
i
]
=
move
.
position
[
key
]
}
else
{
// or none, this axis stays
p2
[
i
]
=
p1
[
i
]
}
}
// check for zero-length vector
if
(
MJS
.
distance
(
p1
,
p2
)
==
0
)
{
console
.
log
(
'
------------------ !ACHTUNG! -------------------
'
)
console
.
log
(
'
------------------ !ACHTUNG! -------------------
'
)
console
.
log
(
'
planner throwing zero length vector
'
)
zlcounter
++
console
.
log
(
zlcounter
)
// this means we need another one from the queue
planner
.
outputs
.
moveComplete
.
emit
(
1
)
}
else
{
// starting with basics
let
mv
=
{
axes
:
axes
,
p1
:
p1
,
p2
:
p2
,
cruise
:
move
.
speed
,
entry
:
state
.
minSpeed
,
exit
:
state
.
minSpeed
,
accel
:
state
.
accel
}
// run it once
runSimpleAccel
(
mv
)
sendMoveToNetwork
(
mv
)
}
}
/*
------------------------------------------------------
JUNCTION DEVIATION
walk mq to generate permissible entry / exit speeds
by 'junction deviation' algorithm
------------------------------------------------------
*/
function
runSimpleAccel
(
move
)
{
// useful
var
accel
=
state
.
accel
var
ms
=
state
.
minSpeed
// should reference axis ids, not these moves ?
var
numAxis
=
move
.
p1
.
length
// have entry and exit speeds already because we're simplanner
// now that we know permissible cornering speeds,
// we'll calculate the trapezoid shapes
// this becomes very useful for turning moves over to stepper motors
// and will give us a time estimate for each move as well,
// we need / want that so that we can set a network buffer length
calcTrap
(
move
,
accel
,
false
)
let
time
=
moveTime
(
move
)
if
(
true
)
console
.
log
(
'
PLANNER: trapezoid time to
'
,
move
.
p2
,
time
)
if
(
time
<
0.1
)
{
console
.
log
(
'
------------------ !ACHTUNG! -------------------
'
)
console
.
log
(
'
------------------ !ACHTUNG! -------------------
'
)
console
.
log
(
"
WARN! move time here
"
,
time
)
}
}
/*
------------------------------------------------------
TRAPEZOIDS FROM JUNCTION DEVIATION ENTRY / EXITS
------------------------------------------------------
*/
function
calcTrap
(
move
,
a
,
debug
)
{
// have p1, p2, cruise, entry, exit
// add length, figure if full-accel, full-deccel, triangle, trapezoid, cruise ...
move
.
vector
=
MJS
.
subtract
(
move
.
p2
,
move
.
p1
)
var
d
=
DCRT
.
length
(
move
.
vector
)
var
vi
=
move
.
entry
var
v
=
move
.
cruise
var
vf
=
move
.
exit
// limits
var
maxExit
=
Math
.
sqrt
(
Math
.
pow
(
vi
,
2
)
+
2
*
a
*
d
)
var
maxEntry
=
Math
.
sqrt
(
Math
.
pow
(
vf
,
2
)
+
2
*
a
*
d
)
// seven possible cases
// HERE set move with type, accel / deccel lengths, calculate time for each, and total time
// then get on with writing a larger gcode window, bringing in some 'real' moves, and getting these
// out / back from steppers
if
(
d
<=
0
)
{
console
.
log
(
'
ZERO LENGTH MOVE
'
)
}
else
if
(
maxExit
<=
vf
)
{
if
(
debug
)
console
.
log
(
'
TRAP: full ramp up
'
);
move
.
type
=
'
ramp up
'
// full ramp up
// accel, cruise, and deccel time
move
.
t1
=
(
vf
-
vi
)
/
a
move
.
d1
=
d