question

Mischa Spelt avatar image
2 Likes"
Mischa Spelt asked Che-Wei Chou commented

Creating a specific curved AGV path

I'm trying to create a curved one-way AGV path in FlexScript, given:

  • The starting point
  • The start angle
  • The sweep angle
  • The radius


TL;DR: Please help me write a function that works for all reasonable (0 <= ... < 360) angles.

I found that applyDragStart and applyDragEnd don't respect the angles so my best bet was to create a path with the given angles and radius, then find its starting point, and shift it to the position I want it.

In the screenshot below, the straight path has a 'direction' of -135 (where 0 is the model x-axis). The two selected arcs have a start angle of 45 (apparently for the AGV network, 0 is the y-axis) and sweep angles of 90 and -90 respectively. As you see, one of them (the positive sweep angle) is correct but the other one is rotated or mirrored relative to what I want.

In addition, when trying to calculate the shift needed I tried to find the starting point using

Vec3 startOfPath = path.location + Vec3( -radius * Math.sin( sweepAngle ), radius * Math.cos( sweepAngle ), 0 );

but sometimes that gives me the starting point, and sometimes the end point (that is, I get one endpoint of the path but not necessarily the correct one according to the path direction).

Here is what I tried, but that only seems to work correctly in some arbitrary cases.

// Note: AGV directions are rotated 90 degrees (0 = positive y)
setvarnum( path, "startAngle", -Math.degrees( pathDirection ) - 90 );
setvarnum( path, "sweepAngle", angle );
setvarnum( path, "radius", radius );
function_s( path, "setZ", point.z, /* isStart: */ 1 );
function_s( path, "finalizeSpatialChanges" );

double secSweepRad = Math.radians( angle ) - pathDirection;
Vec3 startOfPath = path.location + Vec3( -radius * Math.sin( secSweepRad ), radius * Math.cos( secSweepRad ), 0 );
path.location += point - startOfPath;
function_s( path, "finalizeSpatialChanges" );

Please help me write this function or at least understand how the AGV paths work without having to reverse engineer it :-)

FlexSim 20.0.0
flexscriptagv networkcurved path
createagvpath.png (3.3 KiB)
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

1 Answer

Phil BoBo avatar image
4 Likes"
Phil BoBo answered Che-Wei Chou commented

A curved path's definition is based on a position (of the center of its circle), a start angle, a sweep angle, and a radius.

If you define it in terms of a start position instead of a position that is based on the center of its circle, then what does "start angle" mean? What does "sweep angle" mean?

For the AGV network, the start and sweep angles are relative to a unit circle where the FlexSim x axis is the x axis and the FlexSim y axis is the y axis. I don't know what you mean by "apparently for the AGV network, 0 is the y-axis." 0 represents the positive x axis, not the y axis.

The following code creates and positions a curved agv path based on the inputs that it expects:

Object path = createinstance(node("/AGV/CurvedPath",library()),model());
Vec3 pos = [0, 0, 0];
double startAngle = 10;
double sweepAngle = 45;
double radius = 2;
setvarnum(path, "startAngle", startAngle);
setvarnum(path, "sweepAngle", sweepAngle);
setvarnum(path, "radius", radius);
path.location = pos;
function_s(path, "finalizeSpatialChanges");

The following code shifts the curve so that its location is adjusted based on a specified starting point:

Model.find("AGVNetwork").subnodes.clear();
Object path = createinstance(node("/AGV/CurvedPath",library()),model());
double startAngle = 0;
double sweepAngle = 45;
double radius = 2;
setvarnum(path, "startAngle", startAngle);
setvarnum(path, "sweepAngle", sweepAngle);
setvarnum(path, "radius", radius);

Vec3 startPoint = [2, 1, 0];
double x = startPoint.x - radius * Math.cos(startAngle * (pi/180));
double y = startPoint.y - radius * Math.sin(startAngle * (pi/180));
double z = startPoint.z;
path.location = Vec3(x, y, z);
function_s(path, "finalizeSpatialChanges");

I don't understand your explanation of what you want from your image of selected paths. If one of them has a sweep angle of 90 and the other has a sweep angle of -90, then of course they are going to appear to be mirrored; their angles are sweeping in opposite directions.

If you are trying to define the curves in your picture that aren't selected, this is how they are defined by FlexSim:

If you want to define your curves another way, then you need to convert from how you want to define them into that format. That's the input format that FlexSim's curved paths are defined by.


curved-path.png (53.9 KiB)
curves.png (52.9 KiB)
· 5
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Mischa Spelt avatar image Mischa Spelt commented ·

Thanks, your explanation really helped me understand how it works.

I did have to fiddle a bit with some minus signs, but my final solution is pretty close to yours (pathDirection is the direction we were travelling in on the straight path)

double startAngle = Math.pi / 2 - (Math.fabs(pathDirection) > Math.pi ? -1 : 1) * pathDirection;
if( sweepAngle < 0 ) { startAngle *= -1; }
setvarnum( path, "startAngle", -Math.degrees( startAngle ) );
setvarnum( path, "sweepAngle", sweepAngle );
setvarnum( path, "radius", radius );
			
path.location = point + Vec3( -radius * Math.cos( startAngle ), radius * Math.sin( startAngle ), 0 );

0 Likes 0 ·
Che-Wei Chou avatar image Che-Wei Chou Mischa Spelt commented ·

@Mischa Spelt



Hi Miscah,

Could you specifty clearly about pathDirection?

It will be helpful to understand the path generated rules, thanks.

Wade

0 Likes 0 ·
Jason Lightfoot avatar image Jason Lightfoot ♦♦ Che-Wei Chou commented ·

From Mischa's description it sounds like he's using the negative of the heading angle (not sure why).

For example:

Object path=Model.find("AGVNetwork/StraightPath1");
Vec3 start=path.getProperty("StartLocation");
Vec3 end=path.getProperty("EndLocation");
Vec3 heading=end-start;
double pathAngle=Math.degrees(Math.atan2(heading.y,heading.x));
double pathdirection= -1*pathAngle;
0 Likes 0 ·
Show more comments