What i've done is add new drive system called scara.Then i add some new functions for converting.First function is scara inverse kinematics, this is to convert cartesian coordinate to scara.Second function is scara forward kinematics, this is to convert scara coordinate to cartesian.Third function is dummy convert cartesian to delta. This is because i include scara drive to non linear, and i see there are some functions use the function.

The main idea is cartesian use x & y axis linearly, i use x & y axis circulary. While z axis is the same as cartesian.So cartesian step per unit is step per mm, scara step per unit is step per degree.

The main different converting cartesian to scara compare to convert to delta is which one to convert first. i see that repetier firmware convert mm to steps then convert to delta towers in steps.While scara have to convert coordinate in mm to coordinate in degree first then convert in steps.

That's why i try to convert all the command in cartesian to scara in units then convert to steps.

My questions are1. What functions that i have to modify. I add conversion scara-cartesian in motion.cpp, I found ispositionallowed(), updatederivedparameter(), moveto(), movetoreal(), setdestinationstepsfromgcode() in printer.cpp that i've modify, do i miss something?.

2. I'm confused with moveto() and moveto() function. A. I read the code and the comments but i dont really understand what is the different. Can you please explain what is the meaning of untransformed move, transformed cartesian coordinate, absolute cartesian space, mapping real(model) space to printer space.?B. In moveto() function. If i'm not mistaken, It's written if value is not ignored, then destinationsteps = (value + offset) * steppermm.What happen if it's ignored, what is the value of destinationsteps?I mean if moveto(5, ignore, ignore, ignore)I believe the x value is 5, what is the value of y?Because when convert cartesian to scara it need both x & y coordinate to get how much steps x & y motors should go.

3. Questions about homing. A. My scara have 2 parameters, armlength & forearmlength. X motor to move arm, y motor to move forearm.The ideal home coordinate is x motor at 0 degree and y motor at 180 degree. But it is not the fact. Let say x motor at 5, y motor at 175. What is this suppose to call? X offset & y offset or must be something else?

B. I set my print bed at the left side of the center axis (x motor). Because of x & y motor home coordinate is not ideal, it's forming a distance. I call it scara minimum radius, the maximum radius is armlength + forearmlength. In between min & max radius is my print bed area. Let say min radius is 50mm, max radius is 250mm and i want to put my print bed at leftside. So my printbed center is at (-150,0) cartesian position from x motor axis. Which one suppose to be the (0,0)? The x motor axis, nozzle position when touch endstop, center of printbed, or somewhere else?I am thinking it suppose to be the x motor axis, but i'm thinking how to use repetier host & cura about the printer shape.

That's all for now, hopefully it's too many questions & i hope you can kindly guide me.

Comments

Sounds great. Hope you work against dev tree and make a pull request once you are done!

Implementing new systems should be quite simple in repetier. First select new drive system as you did and check it is recogniced as NONLINEAR_SYSTEM, which is what you need. You need only to program homing and your own version for

You see it gets transformed (meaning rotation of bed) and then converted to steps. So currentPositionSteps and destinationSteps are in cartesian printer format with steps per mm resolution. Your problem is X and Y which has nothing to do with rotation. So select for x and y a virtual resolution. So say you take 1000 for both. Using axisStepsPerMM you can convert this back into floats if needed or you keep computing with integers if that is faster. Next you implement

input is cartesianPosSteps = destination coordinates in steps as described

output deltaPosSteps = real motor position, so z stays the same and x and y are A/B rotations. You need to introduce a new parameter for your real motor resolution to do the conversion.

Last you need to write your own homing routine (see printer.cpp how we already have 3 implementations for different drive systems). There are lots of delta parameter in eeprom you can misuse for your system, e.g. setDeltaTowerXOffsetSteps for homing offsets. Please update eeprom input/output so it shows user correct names for scara then.

You might need to make some assumptions how bed coordinate is orientated relative to arm. If we assume arm is to right a natural coordinate system would have xmin/ymin on the left front. Or you take bed center as origin, both would work.

Below some doc I wrote for orientation. I hope this covers your first questions. Ask again if you need more help.

1. let say if I want extruder move to (-10,10) at this coordinate system. which function should I use? moveTo(-10,10,ignore) or moveToReal (-10,10,ignore). what is the difference result if I use moveTo and moveToReal in this case?

2. the bed is at the left side of (0,0), I set the farest bed side from (0,0) is (-50,0), the nearest side of bed is (-10,0), so the center of bed is (-30,0). Do I need OffsetX, OffsetY in this coordinate system?

3. I want shoulder(X motor) as the center of coordinate as map, not the bed center, because inverse kinematics equation that I use base on this mapping. if user give (X,Y) cartesian coordinate, I have to transform it to scara coordinate with this equation.

B = acos ((X^2+Y^2-L^2-M^2)/(2*L*M))

A = atan (Y/X) - atan (M*sinB/(L+M*cosB)

A is X motor scara coordinate in rad, B is Y motor scara coordinate.

as you can see the equation need both X and Y cartesian coordinate to get successful transformation.

I see in moveToReal, for example...

if(x == IGNORE_COORDINATE)

x = currentPosition[X_AXIS];

I understand that if user command moveToReal(Ignore, -20, ignore, ignore), than the x value will be currenPosition[X_Axis]

so if I transform the given coordinate, it would be ( currentPosition[X_Axis] , -20)

but I don't understand moveTo function, it doesn't say anything about if ignored.

I mean if user command moveTo(ignore, -20, ignore, ignore), what is the value of x if the coordinate have to be transformed to scara with the equation above?

btw, I make changes log for the modification that I made. because I am not really a programmer, can you please help me to check my work. I don't know am I doing the right thing.

transformToPrinter switches from ideal coordinates to coordinates corrected by rotation.

moveTo does not use the transformation while movetoReal includes transformations, so what users use at the end is moveToReal while for homing you will use moveTo as you want to ignore transformations there.

Making O1 origin is a bad idea. Then 0,0 would be outside bed and all Y coordinates are negative. That is very counter intuitive. You axis are wrong. We use a right handed coordinate system. The way you have drawn it all objects will be mirrored. Switch x and y and it looks good. Make x = 0 = left side. y = 0 could be middle to give you some advantage on transformation. Modifying coordinate system for your computations is a simple addition, so don't center too much on what's best for your formula, think more from usage point.

Don't think too much about coordinate systems. You only transform in transformCartesianStepsToDeltaSteps and there you get positions in steps as entered for x/y. All transformations are already done so you only do your simple math. So add offset to xy and compute A/B.

I hope you are using the due as your math is very slow. Don't use power 2 - use x*x which is much faster. asin/acos/atan are among the most expensive math computations. If you can replace equations with sqrt instead do it.

Tx for your explanations and advices.I will avoid using pow ect. But scara arm units conversion to steps options are only degree and rad. To convert angle to linear as far as i know only use sin cos tan asin acos atan functions. I have no idea how to replace those functions.

From your explanation, i think i can't use moveto() function. Even if i have to use them, the x and y in moveto() must not treated for cartesian coordinate. I mean i have to use them for scara coordinate directly. so for instance moveto(5, ignore) means x motor rotate 5 unit, y motor doesnt move. Is this right?

Sorry... you are right for the map. I mean ^y, >x. And all x coordinates are negative.And you are right that it will be not intuitive.

For the bed, actually the maximum usage is not square nor cicle. It's half circle, but it seems there is no such bed shape provided in repetier host, so the option is only square or circle. Which one you suggest will be better? Square or circle?

Please correct me, if the origin is bed center. Bed center is (0,0) and O1 let say (30,0).If i insist O1 is (0,0) then bed center is (-30,0) and this is not intuitive for user.To make bed is origin, simply use offset... x offset?I confuse x offset should be 30 or -30 in this case ???

moveTo is always cartesian. You should not think about that too much. Your job is to make the right transformations. Most problematic will be homing where you want to set target motor position directly in your polar coordinates I guess. I think you need a new inject method for this - in your case a simplified "queueNonlinearMove" function that has no transformation.

DOn't think about the offsets we already have. These are for G92 and do change the coordinate system the user uses but not the resulting coordinates. Just add a variable for this on your own taken from delta variables, e.g. diagonal correction variables for x offset, Arm a/b length. Then you can correct in eeprom.

Bed shape is what you put on your printer not what you can reach. So I'd take a square bed and position it such that you can reach all positions. Scara has a big working radius and I know it is more a circle around arm. So if you want extreme take a circular bed and don't use the center:-)

Origin of coordinate system is also rotation point. This is important if you start autoleveling bed. It's always nice to have a point that does not change height due to rotation. Math will cover different origin, but it could result that all bed position have negative/positive correction which does not feel so good. SO many things are more like how would users expect things and not what is the mathematical simplest solution.

I do worry about moveto(), because i see it used many times (i haven't check them all) and it might causing problems. I dont know what will happen to atan(y/x) if y or x is ignored

So... you are suggesting to use O1 to be origin(0,0), but to make comfortable for users, make a dummy origin that intuitive, then all dummy coordinate transformed/corrected relative to O1?Isn't it the same as offset?Why not just use x offset then in user languages call it correction?

For homing i'm not worry too much it's less difficult then delta, and not so much different with cartesian. I don't need to do anything for z. Just transform xy linear to scara. The only problem that don't know what to do is i want it home z first, then y, then x.

Autobed leveling is important to me. That is one of the thing i love about repetier firmware.I design this scara bot for open bed, which means users can modify bed according to their applications.They may directly print on a floor, a glass, a plate, a wood, a metal or anything. I don't give any boundary to limit the bed, it even possible to print if you put the machine on a table then print on floor. And it even possible to modify to print to wall. So autoleveling is a must everytime user changing bed.

Autolevel is something that i worry too. Is it use moveto function? If you say moveto must be cartesian, then i can't use it. I guess i must make changes to all commands that use moveto().

Btw, this is just an information that i hope useful for you. I use repetier firmware for my delta printer.I learned about delta for months to get a proper way to calibrate. I search anywhere to get it but havent found any calibration procedure that satisfy me. So i make my own calibrating steps and succesfully get accurate result. Including how to find accurate diagonal & radius for each tower.

For calibrating delta accurately, calculating steps from a point at any towers to it's endstop is crusial. We can't get accurate diagonal & radius without this.

I know there is a command in repetier firmware gcode to do this, i was use it and found that it is not correct for some points (especially if we move extruder near z tower, we'll get strange behaviour). Try to check distance in steps for coordinate (0,90), (0,85), (10, 80), (-10,80). It happens to my printers that one of the value doesnt change for all that points.

I found it because transformcartesiantodelta() and step limits in the calculation. So i make another gcode, another function and another integers without transformation and limits to fix it and get accurate result. I hope you add a gcode to calculate steps to endstop without transformcartesiantodelta and limits in the next version.

I modified distortion:: in printer.cppIt map distortion in steps, I add elif drive_system == scara that map distortions in mm, but when store to eeprom i transform it to scara coordinate.When call from eeprom, i transform it again to cartesian in mm.

I haven't change anything in bedleveling.cpp, but I've checked and found moveto() used many times.

What if i add elif drive_system scara in moveto(... if x ignored, x =lastcmdpos x axis ?Is this solving my problem or it will causing other problems?

You are not supposed to change moveTo!!! It is a helper function and takes coordinates in cartesian coordinates and all callers expect it to be using cartesian coordinates. It is cartesian without applying bed leveling correction.

Same with distortion map. These corrections are applied in cartesian coordinate system and need no special case. I didn't need it for delta so you never need it. In delta we also have cartesian and delta coordinates and the only place we transform is transformcartesiantodelta. It is really that simple.

Regarding x offset. The one I mean is the one set by G92 and homing resets this to machine origin which is the only origin that counts. And we want this on bed so we can not use it.

In your transformation you are using int32_t so max. value is +/-2147483648 so squaring some steps > 46340 will overflow the value and you have garbage.

Your homing neglects the fact that moveRelativeDistanceInSteps moves in cartesian not in scara coordinates. As I already said you need a special own function to move directly in scara coordinates. Don't implement home x/y as they are not possible. You can do homeZ since z is independent and homeScara if x and y is set, so pure G28 would home all.

is a pain for programmer. #if is preprocessor compare so only works on const and it is always true if you omit # because you assign all axis true value and do not compare as you think. I guess you meant

First more then 1kb free ram is ok. If you get below reduce subdivisions of move to get more free ram.

Your homing understanding was incorrect I think. Think more abstract here. The reason for homing is to have a known starting position so X,y = 0,0 is at bed center. For Z it's just min/max endstop and easy. For xy position you need to know the angles of your scara, so cartesian koordinates do not help as you need to know the angles for this. So home XY means put scara angles at defined position. So you move here the angles towards your endstop in a way nothing gets damaged. So I assume first big arm, then second arm. Then you know where you are and can also set the cartesian coordinates.

Your second version looks better but you need to base queueScaraMove on queueNonlinearMove more closely. Your version looks more like the cartesian version, but you are nonlinear and need to fill in the submoves of a move correctly. Here the critical part is that each move stays inside int16_t range for steps.

Speaking of precision int32_t = long for 8/32 bit, int64_t is long long, but don't use it. Better convert it to float before squaring, then you have no range problems. Later you need it as float anyway for acos etc.

so when they touch endstop x angle should be 5, y angle should be 175. this can be transformed to cartesian coordinate, I call this cartesian endstop coordinate, let say Xe, Ye.

when it folded at endstop, there is a distance between shoulder and extruder. we can't print under that distance, so I define it as scara min radius. the max radius is arm + forearm length, we can't reach over that distance.

I define bed center and shoulder distance is average of min and max radius, so bed center is (0,0) and (Xe,Ye) is coordinate relative to bed origin.

I did make the second version based on cartesian movement. because I think this is only used for homing and rotating the arm or forearm, not used for Gcode or linear move command...

My plan is move to endstop with scara move, translate the position to cartesian, then move to origin 0,0 with cartesian move... is it possible do this ?

I agree that homing route is to prevent something hit by the arm, I think the most dangerous is when the go to endstop, go from endstop is not dangerous. But I will reconsider about move from endstop...

And because the function is not translating cartesian command to scara, I think sub segment is not nescessary... please correct me if this is wrong.

>And because the function is not translating cartesian command to scara, I think sub segment is not >nescessary... please correct me if this is wrong.

wrong! You always get the nonlinear bresenham algorithm for motion, so you must fill in the required data structures or nothing will happen or firmware will crash.

>btw, what is sub division?

Normally in linear systems we have 16 moves. For nonlinear this would be bad as we need to divide longer moves in many small moves. So normally we would need 100 moves in buffer, but that slows down path planning to much. So what we have is 1 move = buffer entry = 1 gcode if possible. This move is split into x submoves with nonlinear move changes being linearized. If we can not have enough submoves as move is to long we also split it into more moves put into 1. level buffer. So every 1. level buffer move as x submoves from which we know they are on a line so we can optimize computations. These are stores as 16bit values to further reduce ram usage, so that is an other constraint. And this subdivision is what the nonlinear version does in addition which makes the code a bit longer.

Also for nonlinear systems we introduced a virtual axis for bresenham algorthim as primary axis, because the dominant axis could switch from nonlinear behaviour. So we map the current dominant move for each segment to virtual axis.

the other movement I need is to calibrate the exact arm length & forearm length by measuring the linear distance with a caliper by rotating an axis some degree. this is also rotate one axis at a time, any other axis must not move at all.

the last thing I need is to find endstop position in angle. to find this, I also need to rotate one axis only.

if I use bresenham algorithm, isn't that mean that I have to translate an axis rotation movement to cartesian movement, divide them to sub segments, then translate again to axis rotation and I get a possibility of moving other axis that I don't want to?

For your understanding, bresenham is always called for all moves as it is the only function moving the steppers. For bresenham x,y,z are the motors not coordinates. Normal queue delta has created them by calling your transformation to know how much steps per motor are used. You did the same now without the transformation since you want to move motors directly here. So that seems to be correct.