How to structure code for good readability (FANUC)
This guide is based on an S-430i robot from the year 2000, running SYSTEM R-J3. But can be of use for other projects because it covers some important stylistic choices your client and co-workers will thank you for.
How-to contents
- Before writing
1.1. Discuss consistent coding style
1.2. Discuss consistent and clear naming
1.3. Structuring code in sections - While writing
2.1. Organize code in blocks
2.2. Comment thoughtfully
2.3. Limit line length
2.4. Write modular code
2.5. Use meaningful defaults
2.6. Avoid deeply nested logic
NOTE: Why stylistic choices matter even more on FANUC SYSTEM R-J3
This FANUC system lacks modern communication interfaces and open software support required for ROS or other communication architectures.Due to its proprietary protocols, programming must be done on a teach pendant running KAREL on a TP (Teach Pendant). Code is encrypted and cannot easily be exported via cable. It is like coding on an old TI calculator. The TP can only display 10 lines at once on a monochrome LCD screen.
1 Before writing
Tips for getting started on a script. Instead of immediately starting with a hasty test script and adding to it till it becomes final. Think about what it’s going to look like in the bigger picture.
1.1 Discuss consistent coding style
Some important things to consider and discuss.
- Language: This is an English minor with Dutch clients. Either should be fine but make sure you make a good choice.
- Variable format: The format should fit your needs.
In our case with limited screen size: camelCase or PascalCase
snake_case for word clear separation and ALL_CAPS for constants.
1.2 Discuss consistent and clear naming
Names should convey intent clearly.
- Variables: Short but descriptive
targetPos
instead oftp
- Functions: Use action verbs
checkLimits
1.3 Structuring code in sections
- For FANUC TP: Functions can’t be written with KAREL, but programs can be used as one. To avoid cluttering split into programs accessed from
MAIN
.
MAIN
GETBASE
PICKPOLES
PLACEPOLES
...
- Split in at least
MAIN
andfunctions
MAIN
contains at least:- Initialization: Define variables and defaults.
- Setup: Set up configurations and parameters.
- Main logic: Keep this modular to improve readability.
- Cleanup: Handle shutdown processes.
2 While writing
2.1 Organize code in blocks
Group related lines together and split those that are not with a empty line.
2.2 Comment thoughtfully
Keep comments concise and to the point. Explain what the code is for.
Also note it when something is temporary so you don’t forget to fix it.
“nothing is more permanent than a temporary solution”
2.3 Limit line length
- When working on a big screen:
Long lines can be hard to read. Consider splitting it over more lines - When working on a TP without a keyboard:
“Why waste time say lot word when few word do trick?” - Kevin (The Office S8E2)
Bad example for coding FANUC movements
!Moves down at an angle and then tilts back while moving sideways PR[1] = LPOS PR[1,3] = PR[1,3] - 75 PR[1,5] = 35 L PR[1] 100mm/s FINE PR[1] = LPOS PR[1,5] = 0 PR[2] = LPOS PR[2] = PR[2] - PR[2] PR[2,1] = 100 L PR[1] 100mm/s FINE Tool_Offset, PR[2]
Good example for coding FANUC movements
!move down tilted PR[1] = LPOS PR[1,3] = PR[1,3] - 75 PR[1,5] = 35 L PR[1] 100mm/s FINE !Tilt back to side PR[1] = LPOS PR[1,5] = 0 PR[2] = LPOS PR[2] = PR[2] - PR[2] PR[2,1] = 100 L PR[1] 100mm/s FINE Tool_Offset, PR[2]
2.4 Write modular code
Break the logic into small, reusable blocks to improve maintainability. Each function should perform a single task:
call moveToTarget(); // Handles motion to target
call checkSafety(); // Checks for collisions
For FANUC TP:
Call modular block to turn Digital out 0-10 off from IO!turn IO off JMP LBL[10]
Modular code block
!turn IO off LBL[10] R[1] = 0 LBL[11] IF R[1] > 10, JMP LBL[12] DO[R[1]] = off R[1] = R[1] + 1 WAIT .1s JMP LBL[11] LBL[12]
2.5 Use meaningful defaults
Default values reduce the need for constant re-initialization. Define these early to save space and time. Use them for:
- Speeds:
maxSpeed = 100
- Positions:
Home = [0,0,0,0,0,0]
- Progression: If needed keep track of executed steps, split into multiple values to increase readability.
- Don’t do this:
stepsExecuted = 0
tillstepsExecuted = 12
- Do this:
basePlaced = 0
(or 1)
polesPlaced = 0
(till 4 counting up or down)
shelvesPlaced = 0
(till n counting up or down)
cartFinished = 0
(or 1)
- Don’t do this:
2.6 Avoid deeply nested logic
Nested logic can quickly become unreadable. Refactor into flat, clear structures.
CodeAesthetic does a great job explaining it in the video:
https://youtu.be/CFRhGnuXG-4?si=1obKcW4k62p6p4Uu
// Avoid this:
if (condition1) then
if (condition2) then
if (condition3) then
...
// Prefer this:
if (condition1 and condition2 and condition3) then
...
For FANUC TP:
“Nesting” can only be done by calling programs. Never nest more than 2 times deep. Also make sure there is a clear difference between the level.
On level one is MAIN, it calls all other programs on level 2 that contain steps/functions. Try and avoid the 3rd level, reserve it for common repetitive tasks like detecting something with a skip condition or doing a specific combination of complicated movements.If you need a fourth level. Consider changing your code structure. (Maybe end the nested program before jumping to another)
1 2: nested in 1 3: nested in 2 MAIN
GETBASE
FINDHOLE
PICKPOLE
PLACEPOL
...