Knitout (.k) is a file format that can represent low-level knitting machine instructions in a machine-independent way. The format is easy to read and write from code, and reasonably human-readable. It is hoped that knitout can serve as an output file format for design tools, and an input file format for knitting machines and simulators.
Knitout has no relation to the custom sock vendor of the same name.
The remainder of this document describes the format itself, the design principles behind the format, and ends with some comments about particular decisions.
Please do not hesitate to get in touch with ideas, comments, or improvements for the specification. Without your input, knitout cannot grow into a useful specification.
To provide feedback, use the Issues page. You may also contact the authors directly using the firstname.lastname@example.org e-mail alias.
Knitout is a straightforward list of knitting instructions to execute to create a knit object, along with a header describing specific information about the machine it is designed to run on.
Knitout files are named with the
Knitout files contain UTF8-encoded text.
Knitout is line-oriented, and knitout files use the LF character to terminate lines (
Programs that write knitout format files should name then with a
encode them as UTF8,
use only the "space" (U+0020) and "tab" (U+0009) characters for whitespace,
and use the LF character (U+000A) as a line ending.
Programs that read knitout files should support files produced in this way, and may support other extensions, encodings, whitespace characters, and line endings (though they should warn that the file is not standard).
Knitout files begin with a magic string
;!knitout-VERSION followed by a linefeed.
VERSION is an integer indicating the current version.
The version number will be incremented when features are moved from extensions into the main language.
Programs that write knitout should always use the latest version of which they are aware. Programs that read knitout must accept any version number, but should warn if the version is later than one they support.
;;Machine: SWG091N2 ;;Gauge: 15 ;;Yarn-5: 50-50 Rust ;;Carriers: 1 2 3 4 5 6 7 8 9 10 ;;Position: Right
After the magic string, knitout files contain a series of special comments (starting with
;;) known as the "comment header."
These comments give additional information about the machine intended to execute the knitout code in the file.
Each comment header begins with string "
;;", followed by the header name, followed by the string "
: ", followed by the header value.
The following headers are required because their values influence the topology of the finished knit item:
|Carriers||C1 C2 C3 ...||space-separated list of carrier names; carriers are given in front-to-back order. Note that these names can be any string; knitout backends are expected to map these strings to machine carriers.|
Tools that write knitout must include a
tools that read knitout must warn if a
Carriers header is missing, though they may also continue to process the file.
The following headers are optional:
|Machine||M||the model name M of the target machine|
|Gauge||G||the gauge G (in needles/inch) of the target machine|
|Yarn-C||type color||yarn to load in carrier C|
|Position||P||where to place the operations on the needle bed; Left, Center, Right, and Keep are standard values|
knit + f14 A B ;knit together knit + f15 A B knit + f16 A B ;note to self: maybe put in a tuck here? knit + f17 A knit + f18 A knit + f19 A
After the comment header, all lines in the file contain an (optional) operation followed by an (optional) comment. The operation is everything up to the first ';' character, the comment is everything after:
knit + f14 A B ;knit together ^--operation--^ ^--comment--^ knit + f14 A B ^--operation-^ (no comment) ;note to self ^-comment--^ (no operation)
The operation is a whitespace-separated list of tokens. Leading and trailing whitespace may appear and is ignored. The first token is the opcode, and the remaining tokens [if any] are the parameters.
|in||CS||Indicate that the given carrier set should be brought into action from the yarn grippers when next used.|
|inhook||CS||Indicate that the given carrier set should be brought into action using the yarn inserting hook when next used. The inserting hook will be parked just before the first stitch made with the carriers.|
|releasehook||CS||Release the yarns currently held in the yarn inserting hook. Must be proceeded by a call to inhook with the same carrier set and at least one knitting operation.|
|out||CS||Bring a set of carriers out of action by directly moving into the grippers.|
|outhook||CS||Bring a set of carriers out of action, using a yarn inserting hook to bring their yarns to the grippers.|
|stitch||L T||Before forming a loop, pull needle by L machine units. After forming a loop, pull needle by T machine units.|
|rack||R||Set the offset of the back bed relative to the front bed.|
|knit||D N CS||Pull a loop formed in direction D by the yarns in carriers CS through the loops on needle N, dropping them in the process. Knitting with an empty carrier set will drop.|
|tuck||D N CS||Add a loop formed in direction D by the yarns held by carriers in CS to those already on needle N. Tucking with an empty carrier set will pull on the stitches without doing anything else (an "a-miss").|
|split||D N N2 CS||Pull a loop formed in direction D by the yarns in carriers CS through the loops on needle N, transferring the old loops to opposite-bed needle N2 in the process. Splitting with an empty carrier set will transfer.|
|drop||N||Synonym for "knit + N".|
|amiss||N||Synonym for "tuck + N".|
|xfer||N N2||Synonym for "split + N N2".|
|miss||D N CS||Move the specified carriers as if they had just formed a loop in direction D at location N. (Not generally needed, used when performing explicit kickbacks or purposeful yarn capture.)|
|pause||Pause the machine until the operator enters a command to continue. (Not generally needed, but can be useful when, e.g., having the operator change yarns.)|
|D||"+", "-"||Direction||A direction on the machine bed. "+" indicates increasing needle number (typically, rightward movement), "-" indicates decreasing needle number (typically, leftward movement).|
|N||"f1", "b-2", "fs3"||Needle||A machine needle. Consists of a location prefix followed by a number. On a V-bed machine, needles are prefixed "f" and "b" for front and back. A V-bed with slide needles adds "fs" and "bs" for front and back sliders.|
|CS||"A B", "2", ""||Carrier Set||List of zero or more carrier names. Carrier names are strings that do not contain the ' ' (space) character.|
|L or T||"2", "-7.5", "30"||Stitch Value||A floating point number giving the number of machine units to retract a needle. Used with the "stitch" instruction. The meaning of a stitch value may vary between machines and manufacturers; be aware that negative stitch values are supported by at least one manufacturer.|
|R||"4", "5.0", "2.25", "-1.75"||Racking Value||Number indicating the offset of the front bed relative to the back bed. That is, at racking R, back needle index B is aligned to front needle index B+R. Needles are considered aligned if they can transfer. That is, at racking 2, it is possible to transfer from f3 to b1. May be fractional on some machines. E.g., on Shima machines, 0.25/-0.75 are used for all-needle knitting.|
Support for extending knitout is supplied through the extension headers namespace (X-*) and the extension opcode namespace (x-*). Programs that read knitout files should warn upon encountering an extension header or opcode they do not support; but should otherwise ignore the header or opcode.
To aid in debugging, a special type of comment is provided that identifies the source code location corresponding to the current line in the knitout file.
These "source comments" always begin with the string "
!source: ". Anything after this is considered the source location.
Tools that parse knitout files should make no assumptions about the format of source locations, and should print source information intact when reporting errors.
knit + f1 A ;!source: knit.js:53 knit + f2 A ;!source: helper.cpp -- do_knit().2
Knitout operations are straightfoward to interpret when generating machine control code. However, knitout files don't provide any direct guidance on two important issues: carriage passes and kickbacks.
In general, backends should attempt to produce machine instructions that fabricate a given knitout file in as few passes as possible, with the constraint that the result must be "as if" the stitches and rackings were performed one-at-a-time in the order written.
When writing knitout files, one should generally be assume that a backend will at least unify stitches into carriage passes, instead of performing each stitch in its own pass. Backends may go further, unifying stitches with different carriers on different parts of the bed into single passes, or using multiple knitting systems to perform multiple stitches on the same needle in a single pass.
Kickbacks are misses performed to get yarn carriers out of the way of other operations. Knitout uses "implicit kickbacks" -- that is, kickbacks are not written into the knitout file directly, but are instead implied by other operations. Implicit kickbacks are always performed "as if" they happen just before they are needed. Backends may choose to perform them earlier if this would not influence the outcome of the construction process.
knit + f1 A xfer f2 b2 ;kickback: yarn from f1 to A would interfere knit + f10 B knit + f9 C ;no kickback, carrier from f10 is to the right knit + f11 C ;kickback: yarn from f10 to B would interfere
It is important to note that for the purposes of implicit kickbacks, backends should always treat yarns as if they are attached to the last stitch performed by the carrier, even if this stitch was a miss. This means one can use miss stitches to override or avoid implicit kickback behavior.
knit + f1 A miss + f2 A xfer f2 b2 ;not a kickback: yarn from f1 now considered to end to the right of f2 knit + f1 A miss - f1 A xfer f2 b2 ;not a kickback: carrier parked left of f1
This example file uses an alternating-tuck cast-on, followed by two rows of plain knitting, and drops instead of binding off.
;!knitout-2 ;;Machine: SWG091N2 ;;Gauge: 15 ;;Yarn-5: 50-50 Rust ;;Carriers: 1 2 3 4 5 6 7 8 9 10 ;;Position: Right inhook 5 tuck - f10 5 tuck - f8 5 tuck - f6 5 tuck - f4 5 tuck - f2 5 tuck + f1 5 tuck + f3 5 tuck + f5 5 tuck + f7 5 tuck + f9 5 releasehook 5 knit - f10 5 knit - f9 5 knit - f8 5 knit - f7 5 knit - f6 5 knit - f5 5 knit - f4 5 knit - f3 5 knit - f2 5 knit - f1 5 knit + f1 5 knit + f2 5 knit + f3 5 knit + f4 5 knit + f5 5 knit + f6 5 knit + f7 5 knit + f8 5 knit + f9 5 knit + f10 5 outhook 5
This section provides notes on the thinking behind the design choices that went into knitout.
Low-level. The format is low-level. It contains no flow-control, abstractions, or grouping primitives.
Output-oriented. Knitout contains exactly the instructions required to fabricate a knit object.
Debug-able. As an output language, it is important that instructions in a knitout file can be tied back to their source in design programs. Thus, if there is a problem in fabrication or simulation, an error can be reported with a reasonable source location.
Easy to use. It should be simple to write software that reads or writes knitout files.
C: Should we use implicit or explicit kickbacks?
Explicit kickbacks make it easier to write a backend, but harder to write design tools, write knitout files by hand, or to interpret what knitout files are producing.
We expect that more frontend tools will be written than backend tools, and prefer the clarity that comes from not having to constantly think about yarn capture when producing a knitout file.
miss opcode allows frontend authors who wish to schedule their own kickbacks to do so.
It may make sense to introduce an extension header ";;X-Kickbacks: Explicit" to control this behavior.
C: Should the format support 'drop', 'amiss', and 'xfer'?
R: Yes. These are synonyms for 'knit', 'tuck', and 'split' with no yarns; which makes them redundant. On the other hand, they are expected and would certainly be provided by any interface; also, having these in the language avoids the weirdness of needing to specify a left/right direction for a transfer.
C: How to support the wide variety of takedown systems and features? (E.g. fabric presser, rollers, combs, segmented combs.)
R: For now, we leave this for extensions; if common themes begin to emerge, we will make the features core operations. We are likely to support an "x-presser on/auto/off" operation for the SWG backend.
C: One generally can't bring a yarn into action without actually making a stitch with it. Should we combine 'in[hook]' and knitting instructions? Should we require that it be followed by a knitting instruction?
R: We considered, but rejected, several resolutions:
Each of these possible resolutions seems to make it harder to read, write, or understand knitout files. Instead, we changed the language of the specification to make it clear that 'in[hook]' marks carriers to be inserted when next they are used, instead of inserting them directly.
In addition, we suggest that programs that read knitout files should produce a warning if carriers are marked for inserting but not used for a long time.
C: Should the back bed move left or right relative to the front bed for positive racking values?
R: Positive racking values move the back bed right. Here are two justifications, both of which are relatively weak:
(However, in knitout 0.4, racking values worked the opposite way.)