Position counts to user units?

Moderators: TomKerekes, dynomotion

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Position counts to user units?

Post by Moray » Fri Sep 21, 2018 9:59 pm

I suspect this will be quite a big question, but I'm looking for some pointers.

So far I've got a probe trigger storing the trigger position to user/persist vars, and those counts being read/displayed into text boxes in my app.
Ultimately I need to convert those counts into units, allow for offsets, then update either fixtures and/or DROs.

Is there any chance of a general overview, or at least what classes/functions I need to look at to acheive this?

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Position counts to user units?

Post by TomKerekes » Fri Sep 21, 2018 11:25 pm

Hi Moray,

Hmmm. I can't think of a simple way to do this. Functions in the GCodeInterpreter and Coordinated Motion Classes have functions to transform motor/actuator positions to CAD positions to do the conversion. But the problem is that if you created these objects in your App they could be configured differently and have a different state than the objects that KMotionCNC created and are in use. There is currently no means of having another Windows App have access to KMotionCNC's internal objects.

A different approach might be to extend the "Automation" that is built into KMotionCNC whereby other Windows Applications like the Screen Editor and Measure Fiducial programs use. Custom Windows Messages are sent from one Windows Application to another to request the other Application to please do something for me. Below is a partial list of things that KMotionCNC can currently be requested to do.

ON_COMMAND(ID_ReloadGeoCorrection, OnReloadGeoCorrection)
ON_COMMAND(ID_ReloadGCodeFile, OnReloadGCodeFile)
ON_COMMAND(ID_OpenGCodeFile, OnOpenGCodeFile)
ON_COMMAND_EX(ID_ScreenScript, OnScreenScript)
ON_COMMAND_EX(ID_DoJog, OnDoJog)
ON_COMMAND_EX(ID_DoMoveExp, OnDoMoveExp)
ON_COMMAND_EX(ID_DoMove, OnDoMove)
ON_COMMAND_EX(ID_GetPositions, OnGetPositions)
ON_COMMAND_EX(ID_GetPositionsNoGeo, OnGetPositionsNoGeo)
ON_COMMAND_EX(ID_GetControlInfo, OnGetControlInfo)
ON_COMMAND_EX(ID_MainDlgInfo, OnMainDlgInfo)

The GetPositions request is similar to what we would need. It reads all the KFLOP actuator destinations, transforms the Position to CAD Space, and sends the result back to the caller. This is why I mentioned before if you were to physically move back to where the probe triggered then this functionality could be used to get the current CAD position.

So if we think this approach makes sense we could add in a new command where we could send the actuator positions (of the probe trigger positions uploaded from KFLOP) to KMotionCNC, have KMotionCNC convert to CAD positions, then send the CAD position back to your App.

Do you think this makes sense?

I think the above could be added pretty quickly. An alternate approach of exposing the internal KMotionCNC objects may take more research time. It might be relatively easy. For example instead of Creating a new KM_Controller object (which currently creates an underlying CKMotionDLL C++ object) somehow obtain a reference to KMotionCNC's CKMotionDLL object and set that to be used.

Regards
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Position counts to user units?

Post by Moray » Fri Sep 21, 2018 11:36 pm

That could work.

I still need to sit down and work out a more detailed workflow, as I've only been working on the basics so far, while familiarising myself with KMotion_dotNet. Once I've got a more detailed workflow, along with some examples, I'll post it up and see what you think would be the best option.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Position counts to user units?

Post by Moray » Sat Sep 22, 2018 10:19 pm

Tom, having re-read your post after some sleep, I'd say having the ability to get the CAD positions from axis positions would be the ideal solution, but moving back to the trigger point is doable.

My concerns with that option however are, the probe input bouncing when stopped at the trigger point, the extra stop required while positions get bounced between programs, and the machine not returning precisely to the trigger point (closed loop may dither).
The first can be handled in the C program (I'd want to add some de-bounce anyway, but de-bounce is easier to handle than a continually bouncing input), the second I'm sure won't be a major problem in the grand scheme of a probing move, but the third could affect accuracy.


For now, I'm happy to just do the additional move back, as it'll let me get things functioning without any additional changes.

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Position counts to user units?

Post by TomKerekes » Sat Sep 22, 2018 11:00 pm

Hi Moray,

Ok I will commit to adding the Axis to CAD capability at some point if this works out.

I’m not sure I really understand the concerns. I was thinking to just move back to where the probe tripped. KMotionCNC will then read the exact commanded position regardless of what the probe happens to be doing and or any Servo Dither.
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Position counts to user units?

Post by Moray » Sun Sep 23, 2018 10:05 am

So does KMotionCNC return the commanded position?

I was assuming it would return whatever was shown in the DROs, which I normally have set to show encoder position where possible, hence the dither.

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Position counts to user units?

Post by TomKerekes » Sun Sep 23, 2018 4:55 pm

Hi Moray,
So does KMotionCNC return the commanded position?
Yes. The KMotionCNC code that returns the position is shown below. It takes the recent Destinations, transforms to CAD space, packs into a string, sends it back to the Client App that requested it as a COPYDATA Windows message. This will be the current CAD position in inches in Machine Coordinates (no Interpreter Offsets) of where the axis was last commanded.

I now see a possible issue. This returns the position at the time of the last Status/DRO Update that KMotionCNC did to its screen. That's nice because it can be performed quickly without any additional communication to/from KFLOP. But the position can be stale. Normally no more than 100ms but on occasion longer. Later when we pass the position to transform this problem should go away. For now maybe put a 500ms delay and be aware of the issue.


Code: Select all

int CKMotionCNCDlg::OnGetPositionsNoGeo(UINT nID)
{
	return OnGetPositions2(nID, true);
}

int CKMotionCNCDlg::OnGetPositions(UINT nID)
{
	return OnGetPositions2(nID, false);
}

int CKMotionCNCDlg::OnGetPositions2(UINT nID, bool NoGeo)
{
	double ActsDest[MAX_ACTUATORS], x, y, z, a, b, c;
	CCoordMotion *CM = Interpreter->CoordMotion;

	for (int i = 0; i<MAX_ACTUATORS; i++) ActsDest[i] = 0.0;

	if (CM->x_axis >= 0)	ActsDest[0] = MainStatus.Dest[CM->x_axis];
	if (CM->y_axis >= 0)	ActsDest[1] = MainStatus.Dest[CM->y_axis];
	if (CM->z_axis >= 0)	ActsDest[2] = MainStatus.Dest[CM->z_axis];
	if (CM->a_axis >= 0)	ActsDest[3] = MainStatus.Dest[CM->a_axis];
	if (CM->b_axis >= 0)	ActsDest[4] = MainStatus.Dest[CM->b_axis];
	if (CM->c_axis >= 0)	ActsDest[5] = MainStatus.Dest[CM->c_axis];

	CM->Kinematics->TransformActuatorstoCAD(ActsDest, &x, &y, &z, &a, &b, &c, NoGeo);

	CString s;

	sprintf(s.GetBufferSetLength(150), "%f %f %f %f %f %f", x, y, z, a, b, c);
	s.ReleaseBuffer();

	CStringW strDataToSend = s;

	COPYDATASTRUCT cpd;
	cpd.dwData = 0;
	cpd.cbData = (strDataToSend.GetLength()+1)*2;
	cpd.lpData = (PVOID)strDataToSend.GetBuffer(cpd.cbData);
	::SendMessage(HWndClient, WM_COPYDATA, (WPARAM)::GetDesktopWindow(), (LPARAM)&cpd);

	return 0;
}
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Position counts to user units?

Post by Moray » Mon Sep 24, 2018 10:06 pm

Tom, using the DoMove() functionality, is there anyway to control the move speed, other than changing the channel velocity settings in the KFlop?

Also, I've hit a bit of a problem, using DoMove().
If I command a relative move, once the probe triggers, and enters it's returning routine, KMotionCNC locks up (and my app if I try issuing anymore job/move commands) until I reboot the KFlop. The returning routine also fails.
The returning routine works fine with any moves commanded within KMotionCNC.

I'm guessing it has to do with the Move not completing, but the C Program trying to reverse the axis, and everything ends up deadlocked.

This is the C program code I'm currently using -

Code: Select all

#include "KMotionDef.h"

service_probe()
{
	double *d = (double *)&persist.UserData[TRIGGER_POS_VAR];
	double trigx;
	
	if ((ReadBit(PROBE_BIT)==PROBE_ACTIVE_STATE) && !ReadBit(PROBE_TRIGGERED)  && !ReadBit(PROBE_STOPPING) && !ReadBit(PROBE_RETURNING))
		{
			
			if (CS0_axis_x>=0) d[0]=chan[CS0_axis_x].Position;
			if (CS0_axis_y>=0) d[1]=chan[CS0_axis_y].Position;
			if (CS0_axis_z>=0) d[2]=chan[CS0_axis_z].Dest;
			
			SetBit(PROBE_STOPPING);
			//printf("Stopping state (pre-StopCoord):%d\n", CS0_StoppingState);
			
			StopCoordinatedMotion();
			DoPC(PC_COMM_HALT); // this stops KMotionCNC generating a buffer underrun error
			//printf("Stopping state (post-StopCoord):%d\n", CS0_StoppingState);
			
			printf("Probe triggered\n");
			printf("X trigger:%f\n",d[0]);
			//printf("Stopping state (post):%d\n", CS0_StoppingState);
		}
	if (ReadBit(PROBE_STOPPING) && (CS0_StoppingState >= 3)){
		printf("X stopped:%f\n",chan[CS0_axis_x].Position);
		//Delay_sec(1);
		ClearStopImmediately();
		//printf("X trigger (pre move):%f\n",d[0]);
		Move(0,d[0]);
		Move(1,d[1]);
		Move(2,d[2]);
		SetBit(PROBE_RETURNING);
		ClearBit(PROBE_STOPPING);
	}
	
	if (ReadBit(PROBE_RETURNING) && CheckDone(0)){
		SetBit(PROBE_TRIGGERED);
		ClearBit(PROBE_RETURNING);
		printf("X at trigger position:%f\n",chan[CS0_axis_x].Position);
		//printf("X trigger (returned):%f\n",d[0]);
		//printf("X trigger:%f\n",trigx);
	}
}

User avatar
TomKerekes
Posts: 2540
Joined: Mon Dec 04, 2017 1:49 am

Re: Position counts to user units?

Post by TomKerekes » Tue Sep 25, 2018 2:29 am

Hi Moray,

Hmmm. Nothing is ever easy :)

I suspect the issue is because the current DoMove in KMotionCNC blocks until the move has completed. Which means KMotionCNC is basically frozen until the move completes. So KMotionCNC can not handle a Halt Request to discard the motion.

I suppose one solution would be to create a Windows worker Thread to perform the Move so as to not Block KMotionCNC.

We also might add an Initiate Move command that doesn't wait for the motion to complete.

Below is the code in KMotionCNC. Are you able to modify and recompile it? If so, try removing the WaitForSegmentsFinished call and see if it works for you.

Code: Select all

int CKMotionCNCDlg::OnDoMove(UINT nID)
{
	double x, y, z, a, b, c;
	CCoordMotion *CM = Interpreter->CoordMotion;

	CString s;
	
	s = InterprocessString;
	sscanf(s, "%lf%lf%lf%lf%lf%lf", &x, &y, &z, &a, &b, &c);

	if (CM->ReadCurAbsPosition(&CM->current_x, &CM->current_y, &CM->current_z, &CM->current_a, &CM->current_b, &CM->current_c)) return 1;

	CM->ClearAbort();
	CM->SetTPParams();
	if (CM->StraightTraverse(x, y, z, a, b, c, true)) return 1;
	if (CM->FlushSegments()) return 1;
	if (CM->WaitForSegmentsFinished()) return 1;

	return 0;
}
We might also add a new function to do a feed rather than a Rapid where a Feedrate can be specified.
Regards,

Tom Kerekes
Dynomotion, Inc.

Moray
Posts: 282
Joined: Thu Apr 26, 2018 10:16 pm

Re: Position counts to user units?

Post by Moray » Tue Sep 25, 2018 9:31 am

If it was easy, everybody would do! :D
I did look at that code yesterday to try and see why it was blocking, but missed the blindingly obvious block.

VS2017 is currently downloading the required MFC components, so I'll see what happens.

Would it be possible to add the ability to send a G-code/MDI command to KMotionCNC?

Post Reply