Zero Gravity Motion Simulator Using String Suspension

by dgouws123 in Circuits > Robots

246 Views, 4 Favorites, 0 Comments

Zero Gravity Motion Simulator Using String Suspension

IMG_20251005_184942.jpg
IMG_20251005_184757.jpg

This Instructable details the process to design and build a device which suspends a model of a space ship in a bounded 3D space using 3 strings. Stepper motors extend and retract the strings in a coordinated way to control the XYZ position of the spaceship based on kinematics. A dynamic motion model (which runs on an Arduino Uno) of the simulated environment (space or low-gravity planetary surface) determines how the ship moves based on applied thrust (inputs from nunchuk controller). In this way, a user is placed in command of the ship's movement. He is tasked to steer the ship to complete a docking procedure with the nearby stationary vessel.

I wanted to express my interest in space by creating something novel and compelling. Additionally, I wanted to utilise my experience in robotics, microcontrollers and CNC machines. This space sim is an excellent application towards the fullfillment of those requirements. It aims to materialise something as esoteric and sci-fi as space flight into an object you can reach out and touch. Hopefully, it does so in a way which is more compelling than simply seeing a rendered camera's view in a modern video game.

My system consists of a model of a mobile ship and a stationary ship mounted to the base. The mobile ship is suspended by a system of three strings hanging over pulleys (eye hooks) and driven by stepper motors. Some mathematics based on Pythagoras' theorem is used to convert the XYZ position of the ship to the string lengths required to achieve it. The AccelStepper library is used to drive the steppers towards the commanded position at some velocity. On top of this abstraction, we run a simple physics model giving the position and velocity of the ship. Simple numerical integration( Δx = v. Δt and Δv = a. Δt) is used to propagate the state every 5 ms.

A Nunchuk controller is added to allow for user input. Input is limited to thrust in z (two buttons) and in the xy (joystick) directions. The thrust is assumed proportional to the acceleration of the ship in those directions.

Therafter, we add a magnet and nut to the mobile and fixed ship to assist in docking and a hall sensor to detect when the two make contact. A buzzer is added to give auditory feedback to the user as he approaches and to indicate a successful dock or a crash, depending on approach velocity.

Ultimately, the system could be used for realistic physical simulation of space operations or as an engaging demonstrator to give players a physical taste of movement through space not achievable in a video game.

Supplies

IMG_20251005_180717.jpg
IMG_20251005_182222.jpg
IMG-20250930-WA0020.jpg
1000063019.jpg

I used the following materials and equipment:

  1. 4mm MDF (Medium Density Fiberboard) sheets for the frame
  2. Fusion 360 and LightBurn software for design and manufacturing
  3. 20 W Atomstack Diode laser
  4. 3D printer for miscellanous small components.
  5. Arduino Uno microcontroller
  6. CNC stepper shield V3
  7. 3 x Stepper drivers (DRV8825)
  8. 3 x Nema-13 stepper motors
  9. Various wires and electrical connectors
  10. String or fishing line
  11. 3D Model of a spaceship pair for the docking game
  12. Magnet, magnetic nut
  13. Hall sensor (A3144E)
  14. Buzzer (3 pin, 5V, passive)
  15. Nunchuk and adapter.
  16. Screw eye hook
  17. Optionally, a 12V power supply and 5V buck converter for standalone operation.

Similar Work

Previous_work.png
Previous_work_2.png
Previous_work_3.png

Much work has been done on linear actuator and cable-based robots. Examples include delta 3d printers, string suspension robots, suspended electromagnets, suspended sports cameras, etc. Due to that, the kinematics are already well-established.

Applied to space simulation, two basic lessons are available, presenting the idea of moving a ship through a 3D space using strings and adding continuous, individually driven servos for movement. In research contexts, full 6-string systems are used for spacecraft dynamic validation and integrated with other components such as load cells and IMUs.

References available here:

  1. Motion idea with 3 hand driven strings.
  2. 3 Continous servo driven strings. No kinematics.
  3. Research Project topic
  4. Research paper on similar work
  5. Full scale, 1 passenger system for simulation.

However, on hobby level, few projects have attempted to simulate motion through space using a string actuator. I aim to address this.

The Kinematics

Base diagram.png
Kinematics_1.png
Base diagram_extended_object.png
F202I6XMG16DECK.jpg
extended_object_corrected.png
attachment_points.png

Kinematics is the math describing the relationship between the controlled geometric quantities (string length) and the resultant position and orientation of the object being controlled. For this project, we only require forward kinematics, which is based on the Pythagorean theorem. Other examples which require kinematics are 5-axis CNC machines and robot arms.

We place the base coordinate system (See diagram) some distance below the centre of the horizontal triangle formed by the three eye hooks. The coordinates of each eye hook in the base coordinate system is known from the CAD design.

In the simplest case, we assume all strings end at the same point on the ship. We therefore model the ship as a point mass. We use the Pythagorean theorem (See equations) to get the distance between the ship point and each eye hook point. This corresponds to the length of string required for that position. This can be used to place the ship anywhere within the triangular space.

However, in practice, the string lengths are only valid if the strings remain taught. This is important to preserve the illusion of smooth movement through space and adds several conditions:

  1. We should remain within the triangular area. This can be done with a position check.
  2. Downward acceleration must be kept below g to keep the strings straight.
  3. Abrupt changes in movement speed must be prevented or else the system will bounce around on the strings.

Once the above concepts are properly implemented, we generalise the system to an extended object (See the second diagram). This is the case if we wish to attach the strings to arbitrary points on the hanging ship and control both its position and orientation. The orientation is important since the ship must be axis-aligned during the docking procedure.

Unfortunately, this is mathematically impossible.

We could calculate the resulting position and orientation given any set of string lengths. This involves the 3 kinematic constraints and the 6 equations (3 force and 3 moment) for static equilibrium. Then the unknowns would be the position and orientation (6 parameters) and the tension in each string (3 parameters). This comes down to a well-posed set of 9 nonlinear equations in 9 unknowns.

But even if we solved this successfully, we would still only be able to command a 3-dimensional subspace in the full 6-dimensional position and orientation space. In general, an arbitrary position and orientation in the 6D space is unlikely to be achievable. Intuitively, even if you held the hanging ship in an arbitrary position using your hand and tightened all the strings, once you released it, it would still swing away to some other equilibrium position and orientation due to gravity.

We could overpower the equilibrium equations by adding another three steppers and strings and reducing it to only the kinematic problem, but that requires significant additional hardware and complexity.

Instead, we try and cheat.

It is sufficient to always keep pitch, roll and yaw at zero or at least when it is near the docking point. During the implementation of the point mass kinematics (see photo), we notice that the centre of gravity (CG) is some distance below the attachment point of the strings. This ensures that the prong remains vertical (pitch, roll = 0). Additionally, due to the fact that the strings are not exactly attached to the same point, the yaw orientation seems fixed, independent of the position. Despite technically being an extended body, the prong's orientation remains fixed!

The pitch and roll remain stable since the mass acts like a pendulum. The total tension is approximated as a resultant force co-linear with the gravity vector. Any tilt causes these to be misaligned, and a moment is created that re-aligns them.

For yaw, typically, the tension forces meet at the geometric centre. If the attachment points are slightly apart, twist will change the direction of the forces, which leads to a restorative moment acting to keep the yaw stable.

The above can be applied to the full extended body (see diagram) as well. We only need to add an attachment which allows all the strings to be attached at nearly the same position vertically above the CG. The distance between individual attachment points and the distance to the CG must be chosen appropriately. It results in a trade-off between time for yaw to settle and tilt error as a function of position.

Additionally, it is difficult to align such an attachment correctly when added to an existing object (see the second image). Therefore, it is wise to add a large number of pilot holes for fine-tuning the resultant equilibrium orientation.

Design of the Frame

IMG-20250930-WA0022.jpg
IMG-20250930-WA0021.jpg
laser cut frame v7.png
space_sim_bar.png
space_sim_frame_bodies.png

The frame is designed in Fusion 360. No strict conditions need to be met, but it must allow stable mounting of the stepper motors at known positions and be rigid enough to remain reasonably still if the ship moves. Otherwise, components are designed to be as large as possible while still fitting in the 400x400mm MDF sheets that fit on our laser-cutter.

The design consists of two triangular plates and 6 vertical bars to hold them together. The plates contain two parallel slots for each bar pair. A central hole is cut for accurate calibration. (With CNC machines, accuracy will never be as good as the first time on the machine bed. Therefore, try to think ahead for all possible fixture requirements.) More holes are cut at known locations to allow mounting the fixed ship and any additional features. Additionally, pilot holes are lasered to accurately place the eyehooks.

The steppers will be mounted on the vertical bars. The bars contain a large hole for the stepper body to fit in and smaller mounting holes for the bolts.

All the bars and plates are identical and symmetrical to avoid the need to keep track of which part goes where.

I opted not to add tolerance space and rather post-process and use a hammer to get everything to fit. You will need a pretuned cut profile (with kerf offset) for 4mm MDF prior to attempting to cut the parts.

Side note about method to create designs for Laser-cutting in Fusion 360:

Laser cutters require closed loops in vector drawings to cut the required shapes and to apply corrections (kerf offset). Fusion 360 sketches don't usually have this requirement and tend to have many open or crossing lines. The easiest way to fix this is to draw your shapes (with all desired construction lines) in a sketch, extrude the desired geometry by 1mm, create a new sketch on top of the extrusion and project the extrusion body to the new sketch. The created 2d geometries are guaranteed to only contain closed loops and can be directly imported into LightBurn for Laser cutting as DXF files.

The design file for the frame is attached.

Wiring the Arduino and Steppers

IMG-20250930-WA0016.jpg
IMG_20251005_180445.jpg
IMG-20250930-WA0015.jpg
IMG-20250930-WA0017.jpg
IMG-20250930-WA0018.jpg

The project requires the control of motors to shorten and lengthen the strings.

Stepper motors were chosen for this project because they are ideally suited for many rotations of accurate position-controlled movement. In contrast, position-controlled servos are limited to only a single rotation or less, while continuous servos have no accurate way of going to a specific position without an encoder.

For convenience, a GRBL CNC shield (very cheap) for Arduino Uno is used. It allows immediate connection with stepper controllers and connectors for the motors. The motors are connected to the CNC shield using standard 4-wire cable and an additional custom connection cable. The u-step selection pins were pulled high with a piece of bare wire.

The stepper motors are mounted to the frame using standard M3 bolts.

A pulley is 3d printed and attached to each shaft to wind and unwind the strings. The strings are cut to longer lengths than that of the frame, attached to the pulleys, fed through the eye hook and attached to the controlled object.

A few other notes:

  1. Our lack of a threaded rod leads to the minimum step increment being fairly coarse. We address this by making the pulley radius as small as possible and using DRV8825 stepper drivers (purple colour, photo outdated) for the 32x microstepping.
  2. The NEMA 13 steppers were scavenged from an old project. Cheaper ones will likely also suffice if available.
  3. Use a drill bit one size smaller than the shaft diameter to ream the pulley for a tight press-fit.
  4. Initially, the pulleys were printed from PLA, then PETG, then finally ABS. Steppers become very hot during operation, causing pulley deformation and slip. Printing from ABS or using some other temperature-stable material is highly recommended.

Add the Nunchuk Controller

IMG_20251005_180258.jpg
IMG_20251005_181806.jpg

The nunchuk controller is added to allow user input. Off-the-shelf adapters are used to expose the I2C connections required for communications without cutting the wires. Standard Dupont cables are used to connect the adapter to the 5V I2C header on the CNC shield. While the nunchuk is rated 3.3V, it commonly tends to survive 5V.

While libraries (like Wiichuck) exist which give a detailed and mature API for communication with the Nunchuk, we opt to do a bare bones reimplementation of the Nunchuk communication protocol. The Arduino Uno has very limited program memory and SRAM, and these libraries tend to consume most of it.

Usage is quite standard. Poll every 100ms (reduce to 10ms for better responsiveness) to keep the processor available for the physics. Request data and only read it on the next loop to allow the system to handle other tasks while waiting for the communication protocol. Received data contains the states of the buttons, joystick and accelerometer. Only the buttons and joystick states are saved for later use.

Practically, the joystick will correspond with XY movement while the buttons are used for up and down Z movement.

Minimal code snippet for Nunchuk communication:

#define NUNCHUK_ADDR 0x52
uint8_t nunchuk_buf[6];

void nunchuk_init() {
Wire.begin();
Wire.beginTransmission(NUNCHUK_ADDR);
Wire.write(0xF0);
Wire.write(0x55);
Wire.endTransmission();
Wire.beginTransmission(NUNCHUK_ADDR);
Wire.write(0xFB);
Wire.write(0x00);
Wire.endTransmission();
}

// --- Nunchuk read ---
bool nunchuk_read() {
Wire.requestFrom(NUNCHUK_ADDR, 6);
if (Wire.available() < 6) return false;
for (int i = 0; i < 6; i++) nunchuk_buf[i] = Wire.read();
// send next request
Wire.beginTransmission(NUNCHUK_ADDR);
Wire.write(0x00);
Wire.endTransmission();
return true;
}

Code and Initial Motion Test

Initial Motion test for Space Sim instructable
IMG-20250930-WA0014.jpg
IMG-20250930-WA0011.jpg
IMG-20250930-WA0013.jpg

Video link: https://youtube.com/shorts/oy38-hppQV4

Now, we need to verify that the steppers, the Nunchuk and the kinematics work correctly.

An initial test was done using only the components described above to drive a small point mass (copper prong of an old electrical plug). The basic motion controller was implemented and tested.

We print a conical fixture and attach it to the centre of the frame. We use the point as the origin of the movement space coordinate system.

Since steppers (open loop) have no internal absolute position sensing we require a calibrated position to start the system at, or zero each stepper after startup. This same problem plagues stepper-based CNC machines. We add a 3D-printed conical fixture at a known point in the 3d envelope and choose the tip as the origin of the movement space. A calibration mode, which simply equates controller input with instantaneous XYZ velocity, is added to allow easy recalibration if the system drifts.

Code flow for initial motion test:

  1. Initialise AccelStepper and Nunchuk. Start in calibration mode. Assume the current position of the mass is the origin. A kinematics function is used to determine the corresponding string lengths and overwrites the current stepper position with those lengths.
  2. Every 100 ms, attempt to read the nunchuk.
  3. Process the inputs and save to variables.
  4. Also check if both buttons have been held in for more than three seconds. If so, switch between calibration mode and simulation mode. When switching from calibration to sim mode, reset the current position as the origin.
  5. Every 5 ms, run the physics loop.
  6. If we are in calibration mode, set object velocity proportional to control inputs and increment position accordingly.
  7. If we are in simulation mode, set object acceleration proportional to control inputs (thrust is proportional to acceleration).
  8. Add some clamping to prevent position and speed runaway.
  9. Convert object position and velocity to stepper commands via the speed control method.

Notes:

  1. Steps per mm factor = steps_per_rotation*usteps_per_step/(pulley_diam_mm * PI) = 200.0 * 32.0 / (10.0 * M_PI)
  2. The AccelStepper library was used to drive the steppers.

Stepper speed control method:

  1. Usually, this lib requires a maximum speed and acceleration and a position command. It then calculates a trapezoidal speed profile, speeds up to max speed, runs and slows down to reach the destination. A non-blocking function is called at high frequency to generate the steps.
  2. Since we already compute the object position and velocity, and since the kinematics causes a non-linear mapping, the above is not suitable. Instead, we use speed mode.
  3. At each 5ms interval, we assume the steppers have reached the position commanded in the previous loop. For each stepper, we request the current true position (string length) from AccelStepper. We then calculate the speed required to reach the next target point given the physics period and current position (v = (L - Lold)/period). The stepper is commanded to move at that speed in the required direction until the next loop. The true position of the stepper (instead of the last commanded position) is used to remove numerical drift from only giving speed and time commands.
  4. In this way, our physics sim directly takes control of the trajectory calculations and prevents unnecessary computation from AccelStepper.

3D Printed Model of Space Ship Pair

IMG-20250930-WA0010.jpg
IMG_20251006_181902.jpg
IMG-20250930-WA0007.jpg
IMG-20250930-WA0008.jpg
IMG-20250930-WA0009.jpg
IMG_20251006_181855.jpg

For theatrical effect, I required a pair of spaceships to dock. Options range from the times of the space age (Apollo-Soyuz Test Project (1975)) to modern commercial systems (SpaceX Crew & Cargo Dragon Dockings). I chose the docking between the lunar lander and the command module of the Apollo 11 mission to recreate a well-known historical event. A model pair (found here, created by Cindy Jory) suitable for docking was available from Thingiverse.

The original ship pair (good image here) was largely coloured in a combination of metallic silver, black, and yellow. As I don't have access to filament matching those colours, I decided to take artistic liberty and simply try to emphasise detail rather than being accurate. The model is reproduced in a combination of transparent grey and white PLA.

Note that I have not deeply researched the actual order of the docking and moon landing events. My attempt at recreating the docking is meant primarily as a demo of the system and is not necessarily historically accurate.

The command module was modified (in Fusion 360) to make space for the docking sensor assembly mounted inside. Additionally, a bracket was designed and printed to mount it to the base and hide the required wires. The pieces making up the model were printed and assembled using superglue.

Docking Mechanism and Sensor

IMG_20251003_204348.jpg
IMG_20251003_204436.jpg

A magnet and a nut pair is used to ensure a satisfying completion event to the docking run. The magnet should only be strong enough to hold the ships together if supported by the strings, which should be able to pull them apart again without human intervention. Some extra printed material is placed between them to ensure this.

Additionally, I mounted a hall sensor (this one) in the fixed ship to detect the moment the two ships come in contact. This ensures that inaccurate calibration and slippage on the pulleys do not cause the position of the base ship to drift if an open-loop software check is used.

The simulation and steppers are frozen the moment the hall sensor detects a dock. The velocity of the ship is checked using the velocity state in the physics model. If the approach or sideways velocity is less than some reasonable threshold (5 mm/s), the docking is judged a success and a win message with stats is printed to the serial port.

Note that the hall effect sensor is a digital device with an open-drain output. An internal pull-up resistor is used when connected to the Uno.

Buzzer

IMG_20251003_204534.jpg

A simple buzzer (passive) is added to give some auditory feedback. We can adjust the pitch, volume (only dependent on pitch) or rate of beeps depending on the situation to qualitatively give additional info regarding approach velocity or distance during a docking run. Clear feedback makes the user experience more enjoyable.

A merry tune (several rising notes) is played on successful docking, and a suitable bad tune (single long shrill beep) if the docking resulted in a crash.

Care must be taken to implement the buzzer control in a non-blocking fashion to avoid disturbing the other loops.

Autopilot

Autopilot_equations.png

It was recommended that I add an autopilot to demonstrate how an actual control system would handle the approach. For that purpose, I decided to create a function which takes in the position, velocity and target point and generates control inputs (directly overwriting commands from the nunchuk) to manoeuvre the ship towards the target.

I wanted it to approach the stationary ship in a semi-human-like manner, where it might oscillate around the target a few times in the radial direction before settling on the target and finally doing a slow axial approach. From a control systems perspective, such a response can be implemented using a second-order PD controller. Illustration of second-order response here.

For reference, the mathematics required to generate the control signal in 1 dimension is given in the image. ChatGPT assisted in generating and implementing the math. We assume that the control signal u(t) is equal to our acceleration (scale for nunchuk input). The error e(t) is the difference between our position and the target (x_t). (3) states that we wish for the error to follow a second-order response, i.e. the solution to that second-order differential equation. We can tune how that response looks by changing the constants omega_n and zeta.

We then take the first derivative of the error e_dot(t) in (4). Since the target x_t is constant, it falls away. We take the derivative again and see that it is equal to the negative control signal. We then substitute (2), (4) and (5) into our differential equation and solve for u(t) to calculate the required control signal at each point in time based on the current position and velocity to ensure our error follows the desired second-order response.

Each of the three axes can be split to individually use the controller function with different parameters depending on the desired settling time and oscillation. I choose the YZ directions to oscillate somewhat (zeta = 0.7) while the X (axial) direction is very overdamped (zeta = 2.0). Additionally, the dynamics of the YZ directions (wn = 1.0) is set to be faster than that of the X direction (wn = 0.6).

The controller is implemented as a function and called at the same frequency as the nunchuk is polled.

Code

The code is extended from the previous motion test to integrate the discussed components and functionality.

Code flow:

  1. Initialise AccelStepper, Nunchuk, buzzer and hall sensor. Set the current position of the hanging ship as the origin.
  2. Every 100 ms, attempt to read the nunchuk.
  3. Process the inputs and save to variables.
  4. Also, check if both buttons have been held in for more than three seconds. If so, switch between calibration mode and simulation mode.
  5. Check the autopilot switch. If set, overwrite the control inputs.
  6. Check Hall-sensor:
  7. If set, Check absolute velocity.
  8. If it exceeds threshold, Lose, destroy ship and play loss tune. Else Win the game.
  9. Reset to calibration mode.
  10. Update the buzzer beep rate based on distance from dock point.
  11. Every 5 ms, run the physics loop.
  12. If we are in calibration mode, set object velocity proportional to control inputs and increment position accordingly.
  13. If we are in simulation mode, set object acceleration proportional to control inputs (thrust is proportional to acceleration).
  14. Add some clamping to prevent position and speed runaway.
  15. Convert object position and velocity to stepper commands via the Speed control method.

Final Product

IMG_20251006_181836.jpg
IMG_20251006_181848.jpg
IMG_20251005_184957.jpg
IMG_20251005_183330.jpg
F3PNLKKMG8A18DF.jpg
IMG_20251005_184532.jpg

After significant debugging and incremental development, the simulator reached a demonstrable condition suitable for display and operation at an Open Day.

For stability, all loose components were hot-glued into place. A 220V to 12V onboard power supply was added to power the steppers in a non-workshop setup. A 5V buck converter is used to power the Arduino and remove the necessity of a laptop.

The cables and components were left uncovered to better allow explanation of how the system works during a demo.

Images are attached showing the system in a mostly complete state during significant events such as calibration, approach towards the stationary ship and after docking.

The final code file required to drive the system is attached.

Gameplay Video

Demo of Space Ship Sim suspended by strings

Attached is a video(https://youtu.be/lCfLBebjyTI) demonstrating the operation of the simulator:

The system starts up with the hanging ship near the origin and is manoeuvred in calibration mode until sufficiently close to the origin.

Therafter, we switch to sim mode and manoeuvre by remote control until close to the stationary ship. The buzzer beeps at a higher and higher rate as we get closer. We reduce speed and attempt to approach without drifting off to the side. Once close enough, the magnet pulls us in and triggers the hall sensor. The speed was low enough for a successful docking.

The system switches back to calibration mode after the game ends, and we manually move to the origin. We switch to sim mode and give the ship some position and velocity, and flip the toggle switch to enable the autopilot. Thereafter, the autopilot guides the ship towards the stationary ship and docks successfully.

Conclusion

In conclusion, a space ship docking simulator was constructed and programmed. It successfully allows a user to experience a simplified process of aligning two spaceships and bringing them to dock in a tangible, hands-on way.

Ideas for future expansion:

  1. The system could be modified to simulate landing on an alien planet by adding some constant downward acceleration. Some rough terrain could be fixed under the lander such that the user must carefully choose a safe position and make a slow descent. Thought is required on how to properly detect the moment of touchdown. Perhaps some micro limit switches could be useful.
  2. Red LEDs could be attached to the lander thrusters and driven using PWM based on the Nunchuk input. This would give further feedback and spectacle on how the thrusters intuitively affect the motion of the ship.
  3. We could add three additional steppers to give full bounded control of the position and orientation of the hanging ship. Not technically very difficult, but we would need a CNC shield with access to six stepper drivers and motor ports. The mathematics would be purely geometric.

Thanks for reading