News

Factorio self-loading construction train

Factorio is my favorite build-a-base game and the Pyanadons + Alien Life mod is my latest obsession. Huge bases are a logistics challenge, and I like to move fast. A common feature of my factories is a mall where machines build the equipment to expand the rest of the factory. Logistics drones carry things between the mall providers to make sophisticated, low-quantity equipment.

360h into Pyanadons

When a new sub-factory plan is ready, the parts need to be brought to the construction site. In an efficient factory the trip is done once. As the factory grows, so does the travel time to areas where new construction can take place.

over 60s to cross on the fastest train

Solution 1: Drones everywhere

One potential solution is to extend the logistic drone service area to the entire factory. When a new sub-factory has many thousands of parts that sends many hundreds of robots on long slow journeys carrying a few parts each. It will eventually get done….

A second problem with that method is that all-factory logistic zone will break any localized logistics setups. Sometimes it’s easier to have a local dedicated logistics zone instead of a mess of belts. The belts store a lot of valuable parts in an expensive buffer and the belt spaghetti could get really ugly.

This train station received nine different expensive products and there’s only comfortably room for 4 belts (8 products). Drones delivering from the station to A and from A to B makes life easy – provided the drones stay in their lane and don’t fly off to service every other logistic request in the factory. You gotta keep ’em separated.

Solution 2: Construction train

A better way is to bring everything on a train. Even a slow moving train is faster than hundreds of bots. Did you know in 2025 it’s still faster to move a truck full of hard drives than to transmit the same amount of data over the internet?

But I also don’t want to hunt-and-peck across the mall for every part in my blueprint. I need a way to tell my logisitics drones to fill a train for me.

This train is large enough to store equipment for even my largest builds (to date). The contents of the right-side belt, the blue inserters, the train train car, and the blue requester chest… are all on a green wire. More on that in a second.

A is a constant combinator into which I’ve dropped my latest blueprint. It has a red wire that connects to B, an arithmetic combinator.

B says red wire = red (what we want) - green (what we have) and sends that to C, the requester chest. As drones deliver the request become smaller and smaller.

D unloads the requester chest onto the belt so parts can be loaded onto the train. Left to its own devices it would spit out parts at random and then each car might not be efficiently packed. Since D has five filter slots, I use five selector combinators (E) to choose the five most plentiful items in the box. This typically results in all the belt first, then the pipes, then the rail, and so on. That also means the front of the train is packed with the most plentiful items.

Finally, F waits to see “is there a train” and “is there a demand set” and “is the demand met”? and if all those conditions are true then it sends signal A, which the train can use to depart the station. It will automatically go to the next station when it is ready, which is handy when I stay at a distant place and send the train home to fetch me things.

Final thoughts

To drop a blueprint onto a combinator, open the combinator and drop the blueprint on the “add section” button. (thanks, Jules!)

Here is the blueprint to drop into your base.

I love building large systems and Factorio’s Pyanadons mod is no exception. It has clearly had an effect on the node-based no-code system I’ve been building.

Here’s an earlier version of my sushi-belt mall, prior to logistics drones.

Here’s the same base all the way back at 67h, shortly after I unlocked trains.

News

Things Marginally Clever won’t do

We will never collaborate on sponsored posts.

We have no intention of inviting guests to post.

We are not interested in your rates for improving our social media reach.

If you represent one of these groups, please get help.

News Tutorials

Friday Facts 21: Python to Makelangelo

Makelangelo a great way to tinker with algorithmic art, procedural art, generative code, and more. Python is a popular language for building generative art. To send G-code to a Makelangelo plotter over a serial connection using Python, you can use the pyserial library. Here is an example script that demonstrates how to establish the connection and send G-code commands.

First make sure you have pyserial installed.

pip install pyserial

Then, open a serial connection to a USB connected Makelangelo.

import serial
import time

def send_gcode(port, baudrate, commands):
    try:
        # Open the serial port
        with serial.Serial(port, baudrate, timeout=1) as ser:
            time.sleep(2)  # Wait for the connection to establish

            # Send each G-code command
            for command in commands:
                ser.write((command + '\n').encode('utf-8'))
                time.sleep(0.1)  # Short delay between commands
                response = ser.readline().decode('utf-8').strip()
                print(f"Response: {response}")

    except serial.SerialException as e:
        print(f"Serial error: {e}")

# Define the G-code commands to send
gcode_commands = [
    "G28",  # Home all axes
    "G1 X10 Y10 Z0 F3000",  # Move to (10, 10, 0) at 3000 mm/min
    "G1 X20 Y20 Z0 F3000",  # Move to (20, 20, 0) at 3000 mm/min
    # Add more G-code commands as needed
]

# Send G-code commands to Makelangelo plotter
send_gcode('/dev/TTY0', 250000, gcode_commands)

Explanation

  1. Import serial and time: Import necessary modules for serial communication and timing.
  2. Define send_gcode function: This function takes the serial port, baudrate, and a list of G-code commands as arguments. It opens the serial port, sends the G-code commands one by one, and prints the responses from the plotter.
  3. Open the serial port: Using a with statement to ensure the port is properly closed after use.
  4. Send commands: Iterate through the list of G-code commands, send each command, and print the response from the plotter.
  5. Define G-code commands: A list of G-code commands to be sent to the plotter.
  6. Call send_gcode: Pass the serial port, baudrate, and G-code commands to the function.

Ensure that the port (/dev/TTY0) and baudrate (250000) match your Makelangelo plotter’s configuration. Adjust the G-code commands as needed for your specific tasks.

Final thoughts

You might also be interested in related plotter projects like vpype and vsketch.

News Projects

Friday Facts 20: Java Swing Dial UX

Dial is a Java Swing component designed to create a customizable dial interface. This component allows users to interact using the mouse wheel, click-and-drag actions, or keyboard keys. It features an ActionListener to handle turn commands, making it easy to integrate into various Java applications that require a rotary input method. It can be sometimes be more intuitive than a JSlider, which cannot “roll over” back to the starting value.

Key Features

  • Mouse Wheel Interaction: Turn the dial smoothly with the mouse wheel.
  • Mouse Click+Drag: Click and drag to adjust the dial.
  • Keyboard Control: Use the +/- keys to increment or decrement the dial value.
  • Rollover: Unlike JSlider, the dial can wrap around back to the start. Great for controlling an angle value.

Basic Usage

import com.marginallyclever.dial.Dial;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class DialDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Dial Demo");
        Dial dial = new Dial();
        
        dial.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Dial turned: " + dial.getValue());
            }
        });

        frame.add(dial);
        frame.setSize(200, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Final Thoughts

You can customize the appearance and behavior of the dial through its properties. Adjust the color, range, and initial value as needed to fit your application.

For detailed documentation, visit the GitHub repository.

News

Robot Overlord 2.7.0: Vehicles

Today I’m delighted to announce that Robot Overlord 2.7.0 is out and it adds vehicles. Build your own or use presets like front-wheel drive, rear-wheel drive, motorcycle, mecanum, omni, or tank.

Here are the basic driving controls:

Image

This is what it looks like in the scene graph:

all vehicles start with a CarComponent:

Some wheels can be steered by adding a ServoComponent in the suspension:

I’m especially pleased by the graph tool I made for the PID controller and Torque Curve.

A PID controller (Proportional, Integral, Derivative controller) is a type of control system used to regulate different types of processes. It’s like an auto-pilot mode for controlling systems. Imagine you’re driving a car. You want to keep your car at a constant speed, say, 60 km/hour.

  • The “Proportional” part is like your foot on the gas pedal. If you’re going below 60, you press the pedal down more. If you’re going above 60, you let up on the pedal. The more you are below the target, the harder you press, and vice versa.
  • The “Integral” part is like your memory of what you’ve done so far. If you’ve been below 60 for a while, even if you’re close now, you might press a bit harder on the gas pedal because you remember you’ve been going too slow. It helps to correct sustained, systematic errors (like if your car was carrying heavy weight in the back).
  • The “Derivative” part is like your anticipation of what’s coming. If you’re below 60 but rapidly accelerating, you might ease up on the gas a little, because you’re anticipating hitting the target soon. It helps to mitigate sudden changes (like if you’re about to go downhill).

The torque curve is the relationship between motor speed and motor power. The example graph below is for a NEMA 17 stepper motor used in the Makelangelo art robot.

There’s also a WheelComponent that holds the size and shape of the tires

And of course vehicles need at least one motor

Why cars?

The goal of Robot Overlord is to simulate any kind of robot including robot cars. I would like to see Robot Overlord become the sim/control app used everywhere: All the goodness of free open source, no funky linux like ROS. Tell your teachers, your friends, your preacher, your boss, your employees, your lover, your best friend…everybody.

Plus! The previous way of making robot arms had bones and was missing motors. Now that vehicles have been used to test motors all the arms can be upgraded to use the new system. In app I made one motor with one output and then copy/pasted to LEGO together a 6 axis robot arm. Stepping the motors makes the arm move.

That’s incredibly powerful modular design at work. Love it!

Final thoughts

This is the first version that can be downloaded in all three flavors: Windows, OSX, and Linux. Choose your favorite from the Robot Overlord store page. Huzzah!

2.8.0 will likely be an interim version that converts the existing robot arms to the new motor-driven system.

Full instructions for building custom vehicles are in the Robot Overlord wiki.

As always, you can find me on Discord where I often live code and talk robots.