Skip to content

Conversation

@classicrocker883
Copy link
Contributor

@classicrocker883 classicrocker883 commented Jun 27, 2025

Description

Supposed to be able to rotate the workspace/bed.

Preliminary code, needs work+testing so far works well.
One stipulation I can make is when using G68 for square beds rotation should be in 90 degs. like +/- 90|180|270
Delta beds would not have this issue.

Another thing is when testing, you must use both X and Y in the coordinates - something like G1 X100 Y90
That is for now...
so, TODO: make it so can use either X or Y in Gcode moving commands.

See #27898

Requirements

Benefits

Configurations

Related Issues

@DerAndere1
Copy link
Contributor

DerAndere1 commented Jul 1, 2025

If using the LinuxCNC-compatible G10 L2 P- R- syntax for coordinate rotation is not desired, can Marlin use the Haas/Fanuc/RepRapFirmware-compatible G68 command instead of repurposing G7?

@classicrocker883
Copy link
Contributor Author

If using the LinuxCNC-compatible G10 L2 P- R- syntax for coordinate rotation is not desired, can Marlin use the Haas/Fanuc/RepRapFirmware-compatible G68 command instead of repurposing G7?

so G7 doesn't appear to be used in Marlin, neither for G68. I suppose we could rename to G68 then? only reason for G7 was because it was close to G10

it sounds like G10 from LinuxCNC is just like G68, so that might work better

@classicrocker883 classicrocker883 changed the title Add G7 rotate workspace (G10 LinuxCNC) Add G68 rotate workspace (G10 LinuxCNC) Jul 1, 2025
@DerAndere1
Copy link
Contributor

Cool. Thanks. Can you briefly verify

-that G68 without x and y parameters rotates around the current Position and

-that the direktion if the rotation follows the conventions? I found this example for how it should work:

G68 X0 Y0 R90	(Rotates coordinate system 90° CCW around origin)
G01 X10 Y0	(Now moves along positive Y axis in machine coordinates)
G69	(Restores original coordinate system)

source:
https://cnccode.com/2025/06/23/g68-g69-in-cnc-mastering-coordinate-system-rotation-with-real-world-applications/

@DerAndere1
Copy link
Contributor

I have some untested suggestions for improvement in this commit:
DerAndere1@83c8817

You can ignore changes to G10

@classicrocker883
Copy link
Contributor Author

classicrocker883 commented Jul 2, 2025

yes improvements for sure. in my testing with the simulator there seems to be some promises: G28 homes normally at any angle. but I think maybe that rotations should stick to +/- 90|180|270 for cartesian square beds. for Delta i suppose doesn't matter, but for consistency maybe have that can also stick to 90 deg increments?

im not sure if it rotates around the current position, but it rotates around the center (BED_SIZE / 2). and that was the issue I ran into, it started to rotate around its relative position. so, say you enter G1 X100 it goes to a different position every time (when rotation set). that would me it needs to know an absolute position/ or maybe saved position?

and thanks I will look into your commit and try it out 👍

@DerAndere1
Copy link
Contributor

Workspace rotation is mainly used to simplify Gcode programming of parts with rotational symmetry. That rotational symmetry can be arbitrary (e.g. turbines with 3, 4, 5, 6,...100 blades) no restriction of angels please, that would marke behaviour once again incompatible with other controllers. Choosing angels wisely is task of the gcode programmer/CAM software/slicer

@DerAndere1
Copy link
Contributor

Maybe the inverse_rotate_gcode_coordinates function has to be implemented as part of the get_destination_from_command function in gcode.cpp, taking into account current_position so that variables current_position and destination and cartes remain in cartesian Machine space

@classicrocker883 classicrocker883 marked this pull request as ready for review July 12, 2025 09:29
Copy link
Contributor Author

@classicrocker883 classicrocker883 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked out your code, seems to have some issues/typo

I did work on it a bit more and so far I have something working in my testing.

will need some more work as to make it so degrees are only +/- 90|180|270
I added this for square/non-Delta types

can you test it out using MarlinSimulator? I want to say it looks promising now

@DerAndere1
Copy link
Contributor

DerAndere1 commented Jul 14, 2025

With your G68 followed by multiple G1 commands I still got erratic movement. That is probably because G1 without X or Y resulted in destination[i} = current_position[i], see function get_destination_from_command in gcode.cpp.

With quite a bit of efford I got G68 working as documented in the Haas manual at https://www.haascnc.com/service/codes-settings.type=gcode.machine=mill.value=G68.html.

  • syntax: G68 X Y R. X and Y should specify the center of rotation (no movement) for the active coordinate system. If X or Y are not specified, it should set the rotation center to the current position at the time when G68 is commanded.
    R specifies the angle in degrees. It must be allowed to set arbitrary angles to be compatible with all the other CNC controls. Software endstops in Marlin ensure that motion never exceeds the set limits in case the Gcode was not checked in CAM software.

In addition I have the P parameter working like in LinuxCNC G10.

  • syntax: G68 P X Y R, Here, P should never change the active coordinate system. It should just specify for which coordinate system the rotation is set. Changing the active coordinate system should be done with G54...G59.
  • G68 P0 X Y R sets rotation for the active coordinate system. G68 P1 X Y R sets rotation for the first coordinate system (the coordinate system that can be selected with G54)

Have a look at the last few commits of my branch: https://github.com/DerAndere1/Marlin/tree/coordinate_rotation

@classicrocker883
Copy link
Contributor Author

oh nice. yeah that was something I noticed too - G1 moving commands without X or Y results in weird behavior, I might have forgot to mention it but I did write it in the Description at the top

Another thing is when testing, you must use both X and Y in the coordinates - something like G1 X100 Y90
That is for now...
so, TODO: make it so can use either X or Y in Gcode moving commands.

that is something that can probably be fixed easy

@DerAndere1
Copy link
Contributor

It is already fixed at https://github.com/DerAndere1/Marlin/tree/coordinate_rotation. I tried to integrate individual changes from my branch in your branch. So far, correct motion was only achieved when introducing the additional raw_destination variable.

@thinkyhead
Copy link
Member

Seems like this could supplant #21792 especially with the additional fixes from DerAndere1/Marlin/tree/coordinate_rotation . I will doublecheck and close that PR.

@thinkyhead
Copy link
Member

Also consider G69 (Reset rotation) and G50, G51 which pertain to scaling — particularly useful for linear plotters.

@DerAndere1
Copy link
Contributor

G69 is already added to my branch. I removed the P parameter from G68 because it will lead to confusion later if someone wants to add the G68.2 3D rotation command, where P selects between different modes. When I am at my PC I will have a look at PR 21792 for additional goodies and prepare a clean pull request targeting classicrocker's branch

@DerAndere1
Copy link
Contributor

PR with improvements, including G50, G51 scaling is open at classicrocker883#3

if (skip_move)
if (skip_move) {
#if ANY(SCALE_WORKSPACE, ROTATE_WORKSPACE)
raw_destination[i] = current_position[i];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks to me like …

The current_position will contain a position that was already scaled and rotated. You must unrotate and unscale the current_position or set some flag that indicates that the raw_destination[i] coordinate is already rotated and scaled, and then don't rotate or scale that axis below.

Copy link
Contributor Author

@classicrocker883 classicrocker883 Aug 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made flags that is set when there is rotation/scaling, not sure if thats the right approach but its there for now.

main concern is getting move commands to take a single one like G1 X100, using X+Y works fine, not sure what logic needs changing.

#endif

#if ENABLED(SCALE_WORKSPACE)
if (!(NEAR(scaling_factor.x, 1.0f) || NEAR(scaling_factor.y, 1.0f) || NEAR(scaling_factor.z, 1.0f))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be: if (!(NEAR(scaling_factor.x, 1.0f) && NEAR(scaling_factor.y, 1.0f) && NEAR(scaling_factor.z, 1.0f)))?

Frankly, there will never be any case where a scaling factor is 0.99999 or 1.000001 when it was explicitly set to 1.0 by any method. So it should be absolutely fine to use if (scaling_factor.x != 1.0f || scaling_factor.y != 1.0f || scaling_factor.z != 1.0f).

#if HAS_Z_AXIS
if (use_current_pos && parser.seen('Z')) {
if (parser.seenval('Z')) {
SERIAL_ECHO_MSG("G51: Do not use value for Z-axis scaling center with 'C' parameter!");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not how Marlin does these kinds of messages. Be short, concise, and considerate of tiny boards. See other G-codes for general guidance on how to format messages and keep them short. Marlin is deployed on very small boards with very limited resources, and that remains one of our primary considerations.

*/
bool GcodeSuite::select_coordinate_system(const int8_t _new) {
if (active_coordinate_system == _new) return false;
if (TERN0(ROTATE_WORKSPACE, !NEAR_ZERO(gcode.rotation_angle))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is very unlikely that the rotation_angle will be anything other than 0.0 when set explicitly to 0.0 so this can safely be !gcode.rotation_angle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surely you mean if there is rotation_angle?
if != 0 means there is rotation.

@thinkyhead
Copy link
Member

Pro Tip: When the rotation angle is set, calculate and cache the sin and cos of the angle and then use those cached values instead of calling sin() and cos() all the time in the motion code.

I leave this one to you.

@classicrocker883
Copy link
Contributor Author

classicrocker883 commented Aug 4, 2025

made some fixes according to comments, not all but some.

one issue that remains is when using like G1 X100 with single move command results in odd behavior. i suppose it corrects itself when entered again, but it works normally with two coordinates - G1 X0 Y0

reworked gcode.cpp to make this work with single move coordinates

@classicrocker883 classicrocker883 changed the title Add G68 rotate workspace (G10 LinuxCNC) Add G68/G51 rotate/scale workspace (LinuxCNC) Aug 5, 2025
@thinkyhead
Copy link
Member

My text editor is trippin' today, dropping two characters here and there….

@classicrocker883
Copy link
Contributor Author

classicrocker883 commented Aug 6, 2025

My text editor is trippin' today, dropping two characters here and there….

mischievous and deceitful, chicanerous and deplorable

@DerAndere1
Copy link
Contributor

Requiring G51 C to use the current position as the scaling center is not my preferred solution for dealing with the situation when rotation AND scaling are active. Maybe we have to enforce that rotation center and scaling center are identical in that case. But, conventionally, if rotation is cancelled with G69 and then G51 without C is sent, Marlin should use the current position at the time of the G51 command as the default scaling center.

@thinkyhead thinkyhead added this to the After 2.1.3 milestone Sep 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Rotate the print by 90, 180, and 270 degrees on square beds.

3 participants