Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Navigation
- Tecnomatix
- Forums
- Blogs
- Knowledge Bases
- Groups

- Siemens PLM Community
- Tecnomatix
- Plant Simulation
- Sensor Graphics

Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-27-2016 03:02 PM

I've been asked to add some visuals for the sensors on a line. We are setting up a Virtual Commission or Emulation where we will be interfacing with a PLC.

I've been asked to have a graphic next to the line sensor that will change color whether the sensor is sending an ON or OFF bit to the PLC (true or false). I can concieve doing this the long way by creating an icon or 3D graphic and referencing that object by each and every sensor... that seems like a lot of work. However, I was thinking that PS might have the tools to automate this.

I'm thinking that I could write a SimTalk method that could build this graphic and place it based on the position of the sensor. This is what I've come up with so far:

param SensorID: integer, Front: boolean ?._3D.addGraphicsGroup("PRS1_"+SensorID,true, true) ?._3D.createSphere(makeArray(?.sensorID(SensorID).Position,.5,?._3D.BaseHeight), 0.25, "PRS1_"+SensorID)

Here I am creating a new 3D graphics group named by the type of sensor (PRS1_) + the Sensor ID number, then I am creating a Sphere that will be placed next to the sensor. My thought is then I will just change the color of the sphere depending on whether the value is true or false. The problem I'm having here is that "?.sensorID(SensorID).Position" doesn't appear to return the Position of the sensor. I'm guessing that it only allows you to set the Position of the sensor. I tested it by doing a hardcoded test: "print PF_Line1.sensorID(1).Position", but I just get the error: "Error in method '.Models.ClassObjects.PF_Line.PRS1_Method' in line 4: Unknown identifier PF_Line1." PF_Line1 does exist.

Does anyone have any incite on how I could get this to work... or any better ideas of how I could have a more graphical representation on what is going on at the sensor?

Thank you in advance!

Solved! Go to Solution.

28 REPLIES

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-27-2016 03:40 PM - edited 09-27-2016 04:01 PM

Well I got the Sphere to show up in the correct position... atleast with this first sensor. I have a feeling that it will fail when the line travels down the Y axis... Any ideas on how to get better placement? I also need to figure out how to change the color still.

Anyway, here is my code. I had some typos before:

var lineGrphcsNames := ?._3D.GraphicGroupNames

if lineGrphcsNames.find("PRS1_"+SensorID) = 0

?._3D.addGraphicGroup("PRS1_"+SensorID,true, true)

?._3D.createSphere(makeArray(-?.sensorID(SensorID).Position,0.25,?._3D.BaseHeight), 0.1, "PRS1_"+SensorID)

end

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-27-2016 08:46 PM

Change the colour by:

?._3D.setGraphicMaterial(makeArray("GraphicName"), 255, 255, 255, 255, 0, 0.1, "GraphicGroup") -- this would paint the Graphic RED, see details in the help file

To calculate the number for a colour from the RGB values use:

var i : integer := makergbvalue(255,0,0)

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 07:13 AM

Your code works on the assumption that the line has only one segment (which is probably true in all your cases) and that the line was *inserted* from left to right. If you insert it from left to right and turn the whole object afterwards, the code should still work. Additionally, your segment probably doesn't rise or fall in Z direction. (That could all be taken into account but the more general your code should be, the more complex it will get so I't like to keep the matter restricted but simple)

To take care of the insertion direction, you can use the tangential angle of the polycurve segment:

<*obj*>._3D.getExtSegments(t) fills the table <*t*> with the segments of the conveyor <*obj*>.

After the call, t[1,2] will give you the tangential angle of the segment.

The tridimensional sensor position can no be modified as follows:

Say, your *left-to-right* values are makeArray(x, y, z). The rotated values then are makeArray(cos(t[1,2]) * x, -sin(t[1,2]) * y, z). That way, your tridimensional sensor position should always be correct in this limited case.

On the topic of applying the color to your graphic:

_3D.createSphere(...) returns an integer index that you then can use for your call to _3D.setGraphicMaterial(...) - set the first parameter to makeArray(<*return value of createSphere*>) to reference it.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 08:17 AM

Thank you Peter for this insite. Actually this line has many segments and has many curves and does change in Z. I've only been testing this code on the first couple of sensors. It does seem to work correctly on these... except the 3rd sensor is on a segment that has a up Z slope, so the Z is incorrect when the graphic is built.

I've been nervous to test it on segments further down, because I was pretty sure that it would fail and I wasn't sure how I would handle it.

Thank you for your suggestion on using the getExtSegments method. I'll give it a shot and see if I can get something that will work down the rest of the line.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 08:30 AM - edited 09-28-2016 08:57 AM

On a multiple segment line, how would I know what segment the current sensor is on?

My guess is that I would have to use a loop and add up the length of each segment until I landed on the one that contained the ?.sensorID(SensorID).Position? Or would there be an easier way to do this?

--note--

t[1,2] will return the Tangential angle in degrees, but cos(), and sin() need the value in radians. To convert:

cos((t[1,2]*(pi/180)))

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 10:35 AM

Sorry, you're absolutely correct with the degrees/radian conversion - I did this in my example but forgot to mention that.

I'm not entirely sure whether there is an easier way than looping through the segments. At least I know of none.

To calculate the absolute tangential angle, you'll have to sum up the tangential angles and curve angles up to the segment in which the sensor is located. Additionally, to locate the sensor, you'll also need to sum up the segment lengths and check in every loop whether the sensor position is between the last summed up length and the current one.

At least, you can use is the position of the last segment before the sensor - that can be found in columns 7 to 9 of the segments table. You'll need to add these values to the x/y/z values of your graphic position (but you can remove the addition of the base height in that case).

To calculate the segment lenghts then, you can use the value in column 6 ("length") for straight segments and *radius* (column 4) * *curveAngle* (column 3) * pi / 180 for curve segments. If you also have height offsets (column 6 - delta Z), you'll have to adjust the length by *length* := sqrt(*length***length* + *dZ***dZ*).

Short of vertical curve segments (column 5 is *true*), this should cover all cases.

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 01:39 PM - edited 09-28-2016 01:43 PM

Thank you Peter! I was surprized when I read your post, because I was in the process of coding about half of what you suggested... It's great to have that confirmation that I'm on the right path!! Thank you for the formula to account for the curves... I still need to implement that. I hadn't even begun to try to work through that. I had enough trouble cleaning out the cobwebs in the geometry part of my brain... fortunately my teachers in HS repeated themselves enough that I heard them inbetween naps. The old y = mx + b and c2 = a2 + b2 came in handy :-)

Here's what I have so far:

param SensorID: integer, Front: boolean var lineGrphcsNames := ?._3D.GraphicGroupNames if lineGrphcsNames.find("PRS1_"+SensorID) = 0 --if not exist var t : table ?._3D.getExtSegments(t) --local vars-- var len : length := 0.0 var seg : integer := 0 var tga : real := 0 var hgt : length := ?._3D.BaseHeight var SphrHgt : length := 0 var SphrX : length := 0 var m : real := 0 var senSegPos : length := 0 --parse through segments before sensor-- repeat seg += 1 --index++-- len += t[2,seg] --add up lengths-- tga += t[1,seg] --add up tangential angles-- hgt += t[6,seg] --add up height changes-- until len >= ?.sensorID(SensorID).Position --repeat until accum length is >= Sensor Position-- tga := tga*(pi/180) --convert deg to radians-- --calculations for x,y,z placement-- m := (t[6,seg] / sqrt( pow(t[2,seg],2) - pow(t[6,seg],2)) ) --find slope ΔZ/ΔX on current segment-- senSegPos := ?.sensorID(SensorID).Position-(len-t[2,seg]) --length position of Sensor on it's segment-- SphrX := senSegPos / sqrt( pow(m,2) + 1 ) --find x length ; formula ref: http://tinyurl.com/h98acjw-- SphrHgt := (m*SphrX) + ?._3D.BaseHeight --z = mx + b to find Sphere Height-- SphrX += t[7,1] - t[7,seg-1] --add previous segment X, minus first seg (our 0 ref)-- --build graphic; set init color-- ?._3D.addGraphicGroup("PRS1_"+SensorID,true, true) ?._3D.createSphere(makeArray(cos(tga)*SphrX,sin(tga)+0.25,SphrHgt), 0.1, "PRS1_"+SensorID) ?._3D.setGraphicMaterial(makeArray(1), makeRGBValue(160,160,164), makeRGBValue(0,0,0), makeRGBValue(0,0,0), makeRGBValue(0,0,0), 0.0, 0.2, "PRS1_"+SensorID) --white; off end

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 01:50 PM

- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

09-28-2016 03:45 PM

Not sure what the etiquette is on here regarding updates... as far as deleting my outdated code, but here is another update.

This is now working on a straight line with Z changes, still need to work on the curves.

param SensorID: integer, Front: boolean var lineGrphcsNames := ?._3D.GraphicGroupNames if lineGrphcsNames.find("PRS1_"+SensorID) = 0 --if not exist var t : table ?._3D.getExtSegments(t) --local vars-- var len : length := 0.0 var seg : integer := 0 var tga : real := 0 var hgt : length := ?._3D.BaseHeight var SphrHgt : length := 0 var SphrX : length := 0 var m : real := 0 var senSegPos : length := 0 var xCor : length := 0 --parse through segments before sensor-- repeat seg += 1 --index++-- if seg > t.MaxYDim --if beyond scope of table-- seg -= 1 exitloop end len += t[2,seg] --add up lengths-- tga += t[1,seg] --add up tangential angles-- hgt += t[6,seg] --add up height changes-- if seg > 1 --need two points to make a segment-- xCor += t[2,seg-1] / sqrt( pow(m,2) + 1 ) --add up xCordinates at End point of last segment-- --find x length ; formula ref: http://tinyurl.com/h98acjw-- if t[6,seg] < 0 --cant calc m with neg num-- m := (-t[6,seg] / sqrt( abs(pow(t[2,seg],2) - pow(-t[6,seg],2)) ) ) --find slope ΔZ/ΔX on current segment-- m := m*-1 else m := (t[6,seg] / sqrt( abs(pow(t[2,seg],2) - pow(t[6,seg],2)) ) ) --find slope ΔZ/ΔX on current segment-- end end until len >= ?.sensorID(SensorID).Position --repeat until accum length is >= Sensor Position-- tga := tga*(pi/180) --convert deg to radians-- --calculations for x,y,z placement-- if t[6,seg] < 0 --cant calc m with neg num-- m := (-t[6,seg] / sqrt( abs(pow(t[2,seg],2) - pow(-t[6,seg],2)) ) ) --find slope ΔZ/ΔX on current segment-- m := m*-1 else m := (t[6,seg] / sqrt( abs(pow(t[2,seg],2) - pow(t[6,seg],2)) ) ) --find slope ΔZ/ΔX on current segment-- end senSegPos := ?.sensorID(SensorID).Position-(len-t[2,seg]) --length position of Sensor on it's segment-- SphrX := senSegPos / sqrt( pow(m,2) + 1 ) --reletive x length on segment; formula ref: http://tinyurl.com/h98acjw-- SphrHgt := (m*SphrX) + t[9,seg-1] // ?._3D.BaseHeight --z = mx + b to find Sphere Height-- SphrX += xCor --absolute x length-- --build graphic; set init color-- ?._3D.addGraphicGroup("PRS1_"+SensorID,true, true) ?._3D.createSphere(makeArray(cos(tga)*SphrX,sin(tga)+0.25,SphrHgt), 0.1, "PRS1_"+SensorID) ?._3D.setGraphicMaterial(makeArray(1), makeRGBValue(160,160,164), makeRGBValue(0,0,0), makeRGBValue(0,0,0), makeRGBValue(0,0,0), 0.0, 0.2, "PRS1_"+SensorID) --white; off end ?._3D.setGraphicMaterial(makeArray(1), makeRGBValue(160,160,164), makeRGBValue(255,0,0), makeRGBValue(255,0,0), makeRGBValue(255,0,0), 0.0, 0.2, "PRS1_"+SensorID) --red; on wait PRS_Timeout ?._3D.setGraphicMaterial(makeArray(1), makeRGBValue(160,160,164), makeRGBValue(0,0,0), makeRGBValue(0,0,0), makeRGBValue(0,0,0), 0.0, 0.2, "PRS1_"+SensorID) --white; off

Follow Siemens PLM Software

© 2018 Siemens Product Lifecycle Management Software Inc