aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/chelper
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2019-10-19 21:04:42 -0400
committerKevin O'Connor <kevin@koconnor.net>2020-01-06 11:52:42 -0500
commitac863a95b6689a0975e259512b9e49add306f2b4 (patch)
tree4014f8262e103aaf572e41696b1c5be9578a442b /klippy/chelper
parenta56484c98b4369505c62a85f3fd6b4483f453e65 (diff)
downloadkutter-ac863a95b6689a0975e259512b9e49add306f2b4.tar.gz
kutter-ac863a95b6689a0975e259512b9e49add306f2b4.tar.xz
kutter-ac863a95b6689a0975e259512b9e49add306f2b4.zip
rotary_delta: Initial support for rotary delta kinematics
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/chelper')
-rw-r--r--klippy/chelper/__init__.py10
-rw-r--r--klippy/chelper/kin_rotary_delta.c73
2 files changed, 81 insertions, 2 deletions
diff --git a/klippy/chelper/__init__.py b/klippy/chelper/__init__.py
index b76a795a..73058081 100644
--- a/klippy/chelper/__init__.py
+++ b/klippy/chelper/__init__.py
@@ -17,7 +17,7 @@ COMPILE_CMD = ("gcc -Wall -g -O2 -shared -fPIC"
SOURCE_FILES = [
'pyhelper.c', 'serialqueue.c', 'stepcompress.c', 'itersolve.c', 'trapq.c',
'kin_cartesian.c', 'kin_corexy.c', 'kin_delta.c', 'kin_polar.c',
- 'kin_winch.c', 'kin_extruder.c',
+ 'kin_rotary_delta.c', 'kin_winch.c', 'kin_extruder.c',
]
DEST_LIB = "c_helper.so"
OTHER_FILES = [
@@ -86,6 +86,12 @@ defs_kin_polar = """
struct stepper_kinematics *polar_stepper_alloc(char type);
"""
+defs_kin_rotary_delta = """
+ struct stepper_kinematics *rotary_delta_stepper_alloc(
+ double shoulder_radius, double shoulder_height
+ , double angle, double upper_arm, double lower_arm);
+"""
+
defs_kin_winch = """
struct stepper_kinematics *winch_stepper_alloc(double anchor_x
, double anchor_y, double anchor_z);
@@ -138,7 +144,7 @@ defs_all = [
defs_pyhelper, defs_serialqueue, defs_std,
defs_stepcompress, defs_itersolve, defs_trapq,
defs_kin_cartesian, defs_kin_corexy, defs_kin_delta, defs_kin_polar,
- defs_kin_winch, defs_kin_extruder
+ defs_kin_rotary_delta, defs_kin_winch, defs_kin_extruder
]
# Return the list of file modification times
diff --git a/klippy/chelper/kin_rotary_delta.c b/klippy/chelper/kin_rotary_delta.c
new file mode 100644
index 00000000..7859f6fc
--- /dev/null
+++ b/klippy/chelper/kin_rotary_delta.c
@@ -0,0 +1,73 @@
+// Rotary delta kinematics stepper pulse time generation
+//
+// Copyright (C) 2019 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include <math.h> // sqrt
+#include <stddef.h> // offsetof
+#include <stdlib.h> // malloc
+#include <string.h> // memset
+#include "compiler.h" // __visible
+#include "itersolve.h" // struct stepper_kinematics
+#include "trapq.h" // move_get_coord
+
+// The arm angle calculation is based on the following two formulas:
+// elbow_x**2 + elbow_y**2 = upper_arm**2
+// (effector_x - elbow_x)**2 + (effector_y - elbow_y)**2 = lower_arm**2
+
+// Calculate upper arm angle given xy position of effector joint
+// (relative to shoulder joint), upper arm length, and lower arm length.
+static inline double
+rotary_two_arm_calc(double dx, double dy, double upper_arm2, double lower_arm2)
+{
+ // Determine constants such that: elbow_y = c1 - c2*elbow_x
+ double inv_dy = 1. / dy;
+ double c1 = .5 * inv_dy * (dx*dx + dy*dy + upper_arm2 - lower_arm2);
+ double c2 = dx * inv_dy;
+ // Calculate scaled elbow coordinates via quadratic equation.
+ double scale = c2*c2 + 1.0;
+ double scaled_elbow_x = c1*c2 + sqrt(scale*upper_arm2 - c1*c1);
+ double scaled_elbow_y = c1*scale - c2*scaled_elbow_x;
+ // Calculate angle in radians
+ return atan2(scaled_elbow_y, scaled_elbow_x);
+}
+
+struct rotary_stepper {
+ struct stepper_kinematics sk;
+ double cos, sin, shoulder_radius, shoulder_height;
+ double upper_arm2, lower_arm2;
+};
+
+static double
+rotary_stepper_calc_position(struct stepper_kinematics *sk, struct move *m
+ , double move_time)
+{
+ struct rotary_stepper *rs = container_of(sk, struct rotary_stepper, sk);
+ struct coord c = move_get_coord(m, move_time);
+ // Rotate and shift axes to an origin at shoulder joint with upper
+ // arm constrained to xy plane and x aligned to shoulder platform.
+ double sjz = c.y * rs->cos - c.x * rs->sin;
+ double sjx = c.x * rs->cos + c.y * rs->sin - rs->shoulder_radius;
+ double sjy = c.z - rs->shoulder_height;
+ // Calculate angle in radians
+ return rotary_two_arm_calc(sjx, sjy, rs->upper_arm2
+ , rs->lower_arm2 - sjz*sjz);
+}
+
+struct stepper_kinematics * __visible
+rotary_delta_stepper_alloc(double shoulder_radius, double shoulder_height
+ , double angle, double upper_arm, double lower_arm)
+{
+ struct rotary_stepper *rs = malloc(sizeof(*rs));
+ memset(rs, 0, sizeof(*rs));
+ rs->cos = cos(angle);
+ rs->sin = sin(angle);
+ rs->shoulder_radius = shoulder_radius;
+ rs->shoulder_height = shoulder_height;
+ rs->upper_arm2 = upper_arm * upper_arm;
+ rs->lower_arm2 = lower_arm * lower_arm;
+ rs->sk.calc_position_cb = rotary_stepper_calc_position;
+ rs->sk.active_flags = AF_X | AF_Y | AF_Z;
+ return &rs->sk;
+}