SCARA kinematic

I it wasn’t for the fact that the output is not what you were expecting, I would say that as a plant container it looks rather cool. A bit of smoothing and you could sell the misprints in a garden centre.
Sorry I have nothing useful to add in this case other than :+1: for attempting such a massive project.

1 Like

It’s a fatal mistake to change the hypotenuse formula in polar_stepper_radius_calc_position. It’s better not to touch her :sweat_smile:

Good day! This time we used the formulas that are shown in the pictures, with the help of them we decided to calculate the two angles by which we need to rotate the joints of both hands. But, unfortunately, an error occurs again with division by zero - ValueError: cannot convert float NaN to integer.

2

Even if you remove the calculation of one angle where a fraction is present, this error still occurs. What should we pay our attention to to avoid this mistake?

Internal error on command:"G28"
Traceback (most recent call last):
File "/home/biqu/klipper/klippy/gcode.py", line 198, in _process_commands
    handler(gcmd)
File "/home/biqu/klipper/klippy/extras/homing.py", line 268, in cmd_G28
    kin.home(homing_state)
File "/home/biqu/klipper/klippy/kinematics/polar.py", line 85, in home
    self._home_axis(homing_state, 0, self.rails[0])
File "/home/biqu/klipper/klippy/kinematics/polar.py", line 71, in _home_axis
    homing_state.home_rails([rail], forcepos, homepos)
File "/home/biqu/klipper/klippy/extras/homing.py", line 185, in home_rails
    hmove.homing_move(homepos, hi.speed)
File "/home/biqu/klipper/klippy/extras/homing.py", line 77, in homing_move
    self.stepper_positions = [ StepperPosition(s, name)
File "/home/biqu/klipper/klippy/extras/homing.py", line 77, in <listcomp>
    self.stepper_positions = [ StepperPosition(s, name)
File "/home/biqu/klipper/klippy/extras/homing.py", line 31, in __init__
    self.start_pos = stepper.get_mcu_position()
File "/home/biqu/klipper/klippy/stepper.py", line 146, in get_mcu_position
    return int(mcu_pos - 0.5)
ValueError: cannot convert float NaN to integer
Transition to shutdown state: Internal error on command:"G28"

Kinematics files:
kin_polar.txt (1.5 KB)
polar.txt (5.2 KB)

My coding skills are basic at best, but I tend to have like 500 debug statements in such cases that return every value. Turning “not a number” into integer sounds difficult :upside_down_face:

1 Like

Good day! Can you tell me by what means/methods I can see what variable values are calculated in Klipper? Or how to use these “debug statements”?

Is this what you’re talking about: Debugging?

Im talking about adding an abundance of logging.warning() to the code path that is crashing for you to find out which calculation might return a NaN

1 Like

The math formulas you showed seem like the ones you want. Be sure to shift the nozzle coordinates to a coordinate system relative to the arm, and then use those formulas. Also, be sure to fully implement the Python calc_position() code (it should take the stepper motor positions, calculate the xy coordinates relative to the arm, and then shift that to coordinates relative to the bed).

-Kevin

Did I understand you correctly that this can be implemented using G92? Or am I thinking about something completely wrong?

Unfortunately, I can’t understand this part :frowning:

By convention, the (0,0) XY coordinate used in a g-code file is the front-left corner of the bed. However, the math formulas you cited above assume the center of the main arm is at XY coordinate (0,0). So, in order to use the math formulas, one would typically translate the bed coordinates to the arm coordinates (something like struct coord c = move_get_coord(m, move_time); double arm_x = c.x + arm_offset_x, arm_y = c.y + arm_offset_y; ...).

-Kevin

1 Like

Good day, it’s me again! Failed to set offset for the axes; division by zero occurs again. Tried different offset values, but without success. Maybe someone can point out the mistake.

But let’s not just talk about sad things, you can see how beautiful the layers turned out

polar.txt (5.2 KB)
kin_polar.txt (1.8 KB)
(The formulas are slightly different, but they were checked in Excel and CAD, so I hope there are no errors)

1 Like

The most interesting thing is that the variables in stepper.py (function get_mcu_position) are equal to zero:

#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.01 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.06 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.00 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.00 
mcu_pos  - 0.00 
#################

Starting heater checks for extruder

#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.06 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.16 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.00 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.00 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - 0.00 
self._mcu_position_offset - 0.00 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - 0.00 

_step_dist  - 0.00 
mcu_pos  - 0.00 
#################


#################
self.get_commanded_position() - nan 
self._mcu_position_offset - nan 
mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - nan 

_step_dist  - 0.00 
mcu_pos  - nan 
#################

Internal error on command:"G28"
Traceback (most recent call last):
  File "/home/biqu/klipper/klippy/gcode.py", line 211, in _process_commands
    handler(gcmd)
  File "/home/biqu/klipper/klippy/extras/homing.py", line 268, in cmd_G28
    kin.home(homing_state)
  File "/home/biqu/klipper/klippy/kinematics/polar.py", line 85, in home
    self._home_axis(homing_state, 0, self.rails[0])
  File "/home/biqu/klipper/klippy/kinematics/polar.py", line 71, in _home_axis
    homing_state.home_rails([rail], forcepos, homepos)
  File "/home/biqu/klipper/klippy/extras/homing.py", line 185, in home_rails
    hmove.homing_move(homepos, hi.speed)
  File "/home/biqu/klipper/klippy/extras/homing.py", line 77, in homing_move
    self.stepper_positions = [ StepperPosition(s, name)
  File "/home/biqu/klipper/klippy/extras/homing.py", line 77, in <listcomp>
    self.stepper_positions = [ StepperPosition(s, name)
  File "/home/biqu/klipper/klippy/extras/homing.py", line 31, in __init__
    self.start_pos = stepper.get_mcu_position()
  File "/home/biqu/klipper/klippy/stepper.py", line 156, in get_mcu_position
    return int(mcu_pos - 0.5)
ValueError: cannot convert float NaN to integer
Transition to shutdown state: Internal error on command:"G28"

It was output like this:

def get_mcu_position(self):
        logging.info("")
        logging.info("#################")
        mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset
        mcu_pos = mcu_pos_dist / self._step_dist
        logging.info("self.get_commanded_position() - %.2f ", self.get_commanded_position())
        logging.info("self._mcu_position_offset - %.2f ", self._mcu_position_offset)
        logging.info("mcu_pos_dist = self.get_commanded_position() + self._mcu_position_offset  - %.2f ", mcu_pos_dist)
        logging.info("")
        logging.info("_step_dist  - %.2f ", self._step_dist)
        logging.info("mcu_pos  - %.2f ", mcu_pos)
        logging.info("#################")
        logging.info("")
        if mcu_pos >= 0.:
            return int(mcu_pos + 0.5)
        return int(mcu_pos - 0.5)

Hi everyone !
Is there any way to see/output what is inside the function move_get_coord (coordinate values)?

Apparently the division by zero is due to acos and atan :expressionless:

Greetings to all! We share our results again:
• We decided to take the class of Cartesian kinematics as a basis instead of Polar, since it involves homing of both axes (it’s not very pleasant to return home only along the Y axis);
• We slightly changed the formulas themselves, and also selected offsets for them (like the difference in arm lengths);
• Moved the X axis breakpoint according to the video:

With such settings and offsets, the axes are zeroed very well, unlike our previous attempts. Ultimately, it was possible to achieve that when homing, stepper_x is at an angle of 90 (1.570796 * (180/pi)) degrees, and stepper_y is at 180 (3.141593 * (180/pi)) degrees, which is exactly folded position of the hands according to the above formulas.

Physically and kinematically, the printer can draw lines diagonally, we can’t edit the gear_ratio yet, so most likely the joint draws an arc of a large radius. Kinematically, the printer calculates the coordinates correctly, you can see this in the picture: DropMeFiles – free one-click file sharing service

The problem is that we cannot draw a rectangle/square to calibrate gear_ratio, and we cannot fully see how the printer moves in addition to the diagonals, since the error stepper.error: Internal error in stepcompress occurs. The error occurs when the X and Y values are very different from each other in the G1 command:


Any ideas why this might be happening?

klippy.log (458.4 KB)
scara.txt (4.6 KB)
kin_scara.txt (2.1 KB)

We just noticed that when one of the coordinates changes, the second coordinate is not recalculated. Most likely this is why the error appears, and we assume that it is related to scara_stepper_alloc (based on Cartesian):

struct stepper_kinematics * __visible
scara_stepper_alloc(char axis)
{
    struct stepper_kinematics *sk = malloc(sizeof(*sk));
    memset(sk, 0, sizeof(*sk));
    if (axis == 'x') {
        sk->calc_position_cb = scar_stepper_x_calc_position;
        sk->active_flags = AF_X;
    } else if (axis == 'y') {
        sk->calc_position_cb = scara_stepper_y_calc_position;
        sk->active_flags = AF_Y;
    } else if (axis == 'z') {
        sk->calc_position_cb = scara_stepper_z_calc_position;
        sk->active_flags = AF_Z;
    }
    return sk;
}

Any ideas on how to fix this?

scara.txt (4.6 KB)
kin_scara.txt (2.1 KB)

Hello everyone! I can’t describe my joy that the rectangle has become very similar to a rectangle :blush:

It can be seen from the figure that the dimensions do not match slightly (the error can reach up to 5 mm), and the angle is not quite 90 degrees, but compared to what was obtained before all the time, this is just heaven and earth.

After my previous post they immediately tried to set the flags:

 struct stepper_kinematics *sk = malloc(sizeof(*sk));
    memset(sk, 0, sizeof(*sk));
    if (axis == 'x') {
        sk->calc_position_cb = scar_stepper_x_calc_position;
    } else if (axis == 'y') {
        sk->calc_position_cb = scara_stepper_y_calc_position;
    } else if (axis == 'z') {
        sk->calc_position_cb = scara_stepper_z_calc_position;
        sk->active_flags = AF_Z;
    }

    if (axis != 'z')
    {
         sk->active_flags = AF_X | AF_Y;
    }

But unfortunately, because of this addition, the homing began to behave poorly, the axes move simultaneously when one of them is homing. Therefore, it was decided to see what would happen in polarity with these formulas and offsets. The result is what you can see in the picture above.

All that remains is to deal with jerks during the G1 command, do normal homing, return the hand to its original position (apparently, adding some offsets too)

polar.txt (5.3 KB)
kin_polar.txt (1.8 KB)
generic-bigtreetech-manta-m8p-V2_0.cfg (4.8 KB)

4 Likes

Congratulations! I know it’s not perfect but it looks like you’re getting there.

Nice job. I appreciate you telling people how things are going.

1 Like

But with homing along two axes, nothing works. I don’t know what I can grab onto, I tried using def home(self, homing_state): as in 5-bar SCARA, but without success - Stepper too far in past :expressionless:

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.