Pull PR from Scan data

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Pull PR from Scan data

    I have a product that requires me to perform several evaluations using a minimum of 180 points per plane/diameter. Within this request is a percentage that must be maintained in a secondary set of boundary for diameter. We would like to output Min/Max and Percentage within boundary.

    When I attempt to 'pierce' the scan with a line at specific angle PC-DMIS errors and tells me the features do not converge. If I select 'construct circle' and select the scan, the pierce will work, but returns the PR as half the reported measured diameter(Pre-averaged). This removes the form error and generates a 100% conformance or non-conformance to the percentage requirement as well as showing no diameter variation.

    Is there a way to access the scan data at specified ANGULAR locations so no matter how many points the CMM collects so that I can always get my 90x required cross sections?

  • #2
    You should be able to do it in a loop, but the way to do it depends on the accuracy that you want.
    If you have a high density of points, there's probably a hit close to the perfect angle.
    Then calculate the polar angle of each hit :
    ASSIGN/V1=RAD2DEG(ATAN(SCN1.HIT[1..SCN1.NUMHITS].Y/SCN1.HIT[1..SCN1.NUMHITS].X))..........................array of values between -90 and + 90
    ASSIGN/V2=((SCN1.HIT[1..SCN1.NUMHITS].X/ABS(SCN1.HIT[1..SCN1.NUMHITS].X))-1)*(-90)...............................should be an array of 0 and 180
    ASSIGN/V3=V1+V2 .................................................. .................................................. .................................................. ...should be an array of values between 0 and 360

    V4 =LOOP/START,ID=YES,NUMBER=90,START=1,SKIP=,
    OFFSET:XAXIS=0.01,YAXIS=0,ZAXIS=0,ANGLE=0
    ASSIGN/V5=MININDEX(ABS(V3-(2*(V4-1))))
    ASSIGN/V6=MININDEX(ABS(V3-(2*(V4-1)+180)))
    ASSIGN/DIST1[V4]=SQRT(DOT(SCN1.HIT[V5].XYZ*MPOINT(1,1,0),SCN1.HIT[V5].XYZ*MPOINT(1,1,0)))+SQRT(DOT(SCN1.HIT[V6].XYZ*MPOINT(1,1,0),SCN1.HIT[V6].XYZ*MPOINT(1,1,0)))
    LOOP/END
    ASSIGN/DMIN=MIN(DIST1)
    ASSIGN/DMAX=MAX(DIST1)
    ASSIGN/BND_MAX=here enter the diameter max of the boundary
    ASSIGN/BND_MIN=here enter the diameter min of the boundary
    ASSIGN/V8=SUM(((BND_MAX-DIST1)/ABS(BND_MAX-DIST1)-1)/2)...................number of values bigger than BND_MAX
    ASSIGN/V9=SUM(((DIST1-BND_MIN)/ABS(DIST1-BND_MIN)-1)/2)...................number of values smaller than BND_MIN
    ASSIGN/PERCENTAGE=(90-V8-V9)/90

    I'm not at the cmm to check, but it should work (only if the origin is at the center of the circle !)

    DIST1 is the sum of two opposite polar radius.

    Maybe the local distances in the FCF 2018 or 2019 could do it directly ?

    ​​​​​​​Hope this help...

    Comment


    • R2ah1ze1l
      R2ah1ze1l commented
      Editing a comment
      Code:
      $$ NO,
      
                  ASSIGN/V1=RAD2DEG(ATAN(SCN_B_U.HIT[1..SCN_B_U.NUMHITS].Y/SCN_B_U.HIT[1..SCN_B_U.NUMHITS].X))
                  ASSIGN/V2=((SCN_B_U.HIT[1..SCN_B_U.NUMHITS].X/ABS(SCN_B_U.HIT[1..SCN_B_U.NUMHITS].Y))-1)*(-90)
                  ASSIGN/V3=V1+V2
      $$ NO,
      
      V4         =LOOP/START,ID=YES,NUMBER=90,START=1,SKIP=,
                    OFFSET:XAXIS=0.01,YAXIS=0,ZAXIS=0,ANGLE=0
        $$ NO,
      
                    ASSIGN/V5=MININDEX(ABS(V3-(2*(V4-1))))
                    ASSIGN/V6=MININDEX(ABS(V3-(2*(V4-1)+180)))
                    ASSIGN/DIST1[V4]=SQRT(DOT(SCN_B_U.HIT[V5].XYZ*MPOINT(1,1,0),SCN_B_U.HIT[V5].XYZ*MPOINT(1,1,0)))+SQRT(DOT(SCN_B_U.HIT[V6].XYZ*MPOINT(1,1,0),SCN_B_U.HIT[V6].XYZ*MPOINT(1,1,0)))
        $$ NO,
      
                  LOOP/END
      $$ NO,
      
                  ASSIGN/B_MIN=MIN(DIST1)
                  ASSIGN/B_MAX=MAX(DIST1)
      $$ NO,
      
                  COMMENT/OPER,NO,FULL SCREEN=NO,AUTO-CONTINUE=NO,
      
                  "min found: 13.7124    "+B_MIN
                  "max found: 26.6124    "+B_MAX
      I input the values this code spit out for me. (13.7124 and 26.6124, feature nominal is 26.608) This is from an offline run. I did have to edit the X/Y in V2, felt more accurate, but not positive it was the right swap. Otherwise I copied the code identically, it's a matter of understanding what/how these statements are functioning.

      Still a work in progress, but way farther ahead than I was when I asked!

  • #3
    V2 is only a way to know if the angle is between -90 and + 90 or between + 90 and -90.
    So if you divide X/ABS(X), you obtain +1 or -1.
    Then, you retract 1, so you have 0 or -2.
    *(-90) and you have 0 or +180.
    Then, when you add it to V1, you should have values between 0 and 360.

    Comment


    • #4
      Ok, now that I've updated that part and reviewed V3, I notice that there are only about 13 instances of values depicted below a value of 80, all the other outputs are in 4 decimal display from 80.#### to 88.#### then it switches to -80.#### to -88.####. I do not see many values outside of 80's.
      I am starting to see some of this and reading what the functions do. I will carry on, just not sure if you may know why it is acting like this.

      PS. With the update, the 13.#### is still being displayed for smallest dia currently. (ODD)

      Comment


      • #5
        Some checks to do :
        1 : Did you origin on the circle ?
        2 : The values of V1 should be between 90 and + 90
        3 : V2 should contain only 0 and 180.


        ASSIGN/V5=MININDEX(ABS(V3-(2*(V4-1)))) : V3 is an angle in degrees, 2*(V4-1) gives angles from 0 to 88 with a step of 2°.... So the loop should go to 91 !!!!!

        ASSIGN/V6=MININDEX(ABS(V3-(2*(V4-1))+180)) : the bracket has to be placed before 180, so that when V4=1, you search the min difference of angle between V3 and 180 !!!! (sorry for this error !)

        SQRT(DOT(SCN_B_U.HIT[V5].XYZ*MPOINT(1,1,0),SCN_B_U.HIT[V5].XYZ*MPOINT(1,1,0))) : SQRT(DOT(PT1.XYZ,PT1.XYZ) gives the 3D distance between PT1 and the origin.
        If you want the PR of PT1, you have to avoid the z value, so multiplying by MPOINT(1,1,0) alows to do that.

        Then, it should work... I will give it a try on tomorrow...
        Good night (here, it's time to sleep...)

        Comment


        • R2ah1ze1l
          R2ah1ze1l commented
          Editing a comment
          1: Yes, that scan is constructed to a circle which is the origin of alignment during this evaluation.
          2: This appears not to be the case when I hover my cursor over the assignment.
          3: V2 seems to solidly consist of 0, I don't see any spots where 180 appears.

          Corrected/Updated V6 - No further modification to the information I posted as comment to your original post. (IE results remain the same)

          Thank you for your help and explanations!

      • #6
        My code would look like this (assuming the hits are in CIR2, with a nominal Ø of 44.0):

        Code:
        $$ NO,
                    Compute (X1-X0) ^ 2
                    ASSIGN/V1=(CIR2.HIT[1..CIR2.NUMHITS/2].X-CIR2.HIT[CIR2.NUMHITS/2+1..CIR2.NUMHITS].X)^2
        $$ NO,
                    Compute (Y1-Y0) ^ 2
                    ASSIGN/V2=(CIR2.HIT[1..CIR2.NUMHITS/2].Y-CIR2.HIT[CIR2.NUMHITS/2+1..CIR2.NUMHITS].Y)^2
        $$ NO,
                    Compute all two point diameters
                    ASSIGN/V3=SQRT(V1+V2)
        $$ NO,
                    Extract results
                    .
                    ASSIGN/MX=MAX(V3)
                    ASSIGN/MXI=MAXINDEX(V3)
                    ASSIGN/MN=MIN(V3)
                    ASSIGN/MNI=MININDEX(V3)
        $$ NO,
                    Percent within boundary
        
                    ASSIGN/VLOW=43.9
                    ASSIGN/VHIGH=44.1
                    ASSIGN/VIN=0
        VLOOP      =LOOP/START,ID=YES,NUMBER=CIR2.NUMHITS/2,START=1,SKIP=,
                      OFFSET:XAXIS=0,YAXIS=0,ZAXIS=0,ANGLE=0
                      IF/(V3[VLOOP] >= VLOW) AND (V3[VLOOP] <= VHIGH)
                        ASSIGN/VIN=VIN+1
                      END_IF/
                    LOOP/END
                    ASSIGN/VPCNT=(VIN/CIR2.NUMHITS)*100
        $$ NO,
                    Present result
                    .
                    COMMENT/REPT,
                    Two point measure (local MAX, MIN)
                    COMMENT/REPT,
                    "Maxindex: "+MXI 
                    "Max     : "+MX
                    "Minindex: "+MNI
                    "Min     : "+MN
                    "Percent : "+VPCNT
        AndersI
        SW support - Hexagon Metrology Nordic AB

        Comment


        • R2ah1ze1l
          R2ah1ze1l commented
          Editing a comment
          Thank you, finding my high/low/percent are easy(IMO), but I like this alternate style...it's obtaining reliable cross sections from the scan that is most difficult.

      • #7
        AndersI : nice idea to use Pythagoras.
        As i understand the problem, R2ah1ze1l would like to calulate diameters each 2°...
        After a little work this morning, I can purpose this first solution, which calculate the diameter closer to the perfect angle :
        Code:
        ASSIGN/COS_ANG=(((CE1.HIT[1..CE1.NUMHITS].X-CE1.X)/CE1.R))
                    ASSIGN/SIN_ANG=((CE1.HIT[1..CE1.NUMHITS].Y/CE1.R))
                    ASSIGN/TAN_ANG=((CE1.HIT[1..CE1.NUMHITS].Y/CE1.HIT[1..CE1.NUMHITS].X))
                    ASSIGN/SIGN_COS=(COS_ANG/ABS(COS_ANG))
                    ASSIGN/SIGN_SIN=(SIN_ANG/ABS(SIN_ANG))
                    ASSIGN/SIGN_TG=(TAN_ANG/ABS(TAN_ANG))
                    ASSIGN/COMPL=((SIGN_COS*SIGN_SIN)+(SIGN_TG*SIGN_COS)-2)*(-90)
                    ASSIGN/REAL_ANG=RAD2DEG(ATAN(TAN_ANG))+COMPL
        V8         =LOOP/START,ID=YES,NUMBER=91,START=1,SKIP=,
                      OFFSET:XAXIS=0,YAXIS=0,ZAXIS=0,ANGLE=0
                      ASSIGN/ANGLE_1=2*(V8-1)
                      ASSIGN/MIN_DIF_ANGLE_1=MININDEX(ABS(REAL_ANG-ANGLE_1))
                      ASSIGN/MIN_DIF_ANGLE_2=MININDEX(ABS(REAL_ANG-(ANGLE_1+180)))
                      ASSIGN/DIST1[V8]=SQRT(DOT((CE1.HIT[MIN_DIF_ANGLE_1].XYZ-CE1.HIT[MIN_DIF_ANGLE_2].XYZ),(CE1.HIT[MIN_DIF_ANGLE_1].XYZ-CE1.HIT[MIN_DIF_ANGLE_2].XYZ)))
                    LOOP/END
                    COMMENT/OPER,NO,FULL SCREEN=NO,AUTO-CONTINUE=NO,
                    MIN(DIST1)
                    MAX(DIST1)
        To go further, I believe it's necessary to create a circle from some hits around the perfect angle, then intersect with a line at the perfect angle.
        I'll give it a try ASAP, I'm interesting on this method

        Comment


        • #8
          Originally posted by JEFMAN View Post
          AndersI
          As i understand the problem, R2ah1ze1l would like to calulate diameters each 2°...
          I ignored that, and assumed there were exactly 180 points - makes the solution easier :-) but I realize it's difficult to get an exact number of points when scanning.

          With less points, it is impossible to calculate 90 cross sections, so we can forget that (ok, you could calculate local splines etc. but that isn't worth the effort)..

          With more points, we want to loop in exactly 90 steps, so divide the number of points with 90, and use the following code to select which cross sections to include in the calculation(s):

          Code:
                      ASSIGN/VSTEP=CIR2.NUMHITS/90
           VLOOP      =LOOP/START,ID=YES,NUMBER=90,START=1,SKIP=,OFFSET:XAXIS=0,YAXIS=0,ZAXIS=0,ANGLE=0
                         ASSIGN/VIDX=INT(VLOOP*VSTEP)
                         IF/(V3[VIDX] >= VLOW) AND (V3[VIDX] <= VHIGH)
                           ASSIGN/VIN=VIN+1
                         END_IF/
                       LOOP/END
          If max and min should only look at these selected cross sections, you would have to add IF-statements for that innermost in this loop.
          Last edited by AndersI; 11-28-2019, 07:53 AM.
          AndersI
          SW support - Hexagon Metrology Nordic AB

          Comment


          • R2ah1ze1l
            R2ah1ze1l commented
            Editing a comment
            Trouble is when the scn.numhits/90= 2.33 or 2.68 and oddities like that. Because that would mean I'm starting calculations late or ending them early before having 100% of the diameter evaluated.

            IE: 2.33 would result in 309º of 360º being accounted for.
            This could enable the CMM to not calculate the true min/max and percentage as governing specification requires.

          • AndersI
            AndersI commented
            Editing a comment
            No, the code I suggested will use the full 360, but skip points here and there in the middle:

            2.33 -> point 2
            4.66 -> point 4
            6.99 -> point 6
            9.32 -> point 9
            etc.

        • #9
          FWIW I'd measure once to get the centre, then again with defined 180 points and simply get 2d distance from pnt1 to pnt 91, pnt2 to pnt 92 etc.
          Automettech - Automated Metrology Technology

          Comment


          • R2ah1ze1l
            R2ah1ze1l commented
            Editing a comment
            This was my initial effort, but the program took nearly 2hrs to run. 4 surfaces with 180 points, not to mention any alignment touches required. And that was reducing as much movement/wrist changes as I could.

        • #10
          Another way could be creating 2 curves on half number of points, then create pierce points betwen both curves and a plane turning arond the axis...
          It would use much less assignments, it's much less funny !

          Comment


          • neil.challinor
            neil.challinor commented
            Editing a comment
            +1 This is the method I usually use - construct a curve through the scan and then pierce / intersect with a plane.

          • NinjaBadger
            NinjaBadger commented
            Editing a comment
            I tried this but with one curve, but you end up with repeated points (only does 180° of the circle)

            Is this why you suggested 2 curves Jefman?

          • JEFMAN
            JEFMAN commented
            Editing a comment
            NinjaBadger : Yes that's the reason.
            I tried ASSIGN/V1=2*ROUND(SCN1.NUMHITS/2) to be sure to have an even number.
            Then I constrcted to feature sets with SCN1.HIT[1..V1/2+1] and SCN1.HIT[V1/2-1..V1], but the curves have SCN1.NUMHITS - 2 points, so the planes doesn't intersect when alpha=0...

        • #11
          neil.challinor : I tried it, but the problem here of the curve (even if I selected 100% of hits) is that the curve misses the first and last point, so I obtain 0 for the first distance... (tried on an optical scan, with a lot of hits).

          Comment


          • #12
            There is so much content here to find useful! Thank you to everyone adding in.

            Believe me, if I could JUST do point to point distance I would be THRILLED - 1 long easy full setup and cycles for each unit, however that practice takes up too much time. Scanning will complete this cycle in nearly 1/3 the time if I can perfect the 90+ cross sections of evaluation to follow. I have 2 diameters in this 1 program that need to be evaluated simultaneously. I just got a fixture to put it on its side as wrist rotations were adding a problem in my first eval attempt.

            Comment


            • #13
              So, here was the solution I am attempting after trying some of the offered information. Maybe this benefits someone, maybe it does not...
              Instead of using a loop, I patterned the 90 cross sections and built a 'factor' within the counting to spread the points equally.

              Code:
                          ASSIGN/BH_SET=(ROUND(SCN_B_U.NUMHITS/2))-1
                          ASSIGN/FCTR=SCN_B_U.NUMHITS/180
                          ASSIGN/INDX=""
                          ASSIGN/B_PNTA=""
                          ASSIGN/B_PNTB=""
                          ASSIGN/PT1_B=""
                          ASSIGN/PT2_B=""
                          ASSIGN/INDX=0
                          ASSIGN/PT1_B=0
                          ASSIGN/PT2_B=BH_SET
                          ASSIGN/B_OUT=0
              $$ NO,
              
                          ASSIGN/INDX=INDX+1
                          ASSIGN/B_PNTA="B_PNT1_"+INDX
                          ASSIGN/B_PNTB="B_PNT2_"+INDX
                          ASSIGN/PT1_B=INDX+1
                          ASSIGN/PT2_B=BH_SET+PT1_B
              $$ NO,
              
              B_PNTA     =GENERIC/POINT,DEPENDENT,CARTESIAN,$
                          NOM/XYZ,<(SCN_B_U.HIT[PT1_B].TX),(SCN_B_U.HIT[PT1_B].TY),(SCN_B_U.HIT[PT1_B].TZ)>,$
                          MEAS/XYZ,<(SCN_B_U.HIT[PT1_B].X),(SCN_B_U.HIT[PT1_B].Y),(SCN_B_U.HIT[PT1_B].Z)>,$
                          NOM/IJK,<(SCN_B_U.HIT[PT1_B].TI),(SCN_B_U.HIT[PT1_B].TJ),(SCN_B_U.HIT[PT1_B].TK)>,$
                          MEAS/IJK,<(SCN_B_U.HIT[PT1_B].I),(SCN_B_U.HIT[PT1_B].J),(SCN_B_U.HIT[PT1_B].K)>
              B_PNTB     =GENERIC/POINT,DEPENDENT,CARTESIAN,$
                          NOM/XYZ,<(SCN_B_U.HIT[PT2_B].TX),(SCN_B_U.HIT[PT2_B].TY),(SCN_B_U.HIT[PT2_B].TZ)>,$
                          MEAS/XYZ,<(SCN_B_U.HIT[PT2_B].X),(SCN_B_U.HIT[PT2_B].Y),(SCN_B_U.HIT[PT2_B].Z)>,$
                          NOM/IJK,<(SCN_B_U.HIT[PT2_B].TI),(SCN_B_U.HIT[PT2_B].TJ),(SCN_B_U.HIT[PT2_B].TK)>,$
                          MEAS/IJK,<(SCN_B_U.HIT[PT2_B].I),(SCN_B_U.HIT[PT2_B].J),(SCN_B_U.HIT[PT2_B].K)>
              $$ NO,
              
                          ASSIGN/B1_PR=("B_PT1_"+INDX)
                          ASSIGN/PTB1_PR=B1_PR.PR
                          ASSIGN/B2_PR=("B_PT2_"+INDX)
                          ASSIGN/PTB2_PR=B2_PR.PR
              $$ NO,
              
              DIM BCROSS_1= 3D DISTANCE FROM POINT B_PNTA TO POINT B_PNTB,SHORTEST=OFF,NO_RADIUS  UNITS=IN,$
              GRAPH=OFF  TEXT=OFF  MULT=1000.00  OUTPUT=BOTH
              AX       MEAS    NOMINAL        DEV       +TOL       -TOL     OUTTOL
              M      26.6080    26.6080     0.0000     0.0050     0.0020     0.0000 --#------
              $$ NO,
              
                          ASSIGN/INDX=INDX+1
                          ASSIGN/B_PNTA="B_PNT1_"+INDX
                          ASSIGN/B_PNTB="B_PNT2_"+INDX
                          ASSIGN/PT1_B=ROUND(INDX*FCTR)
                          ASSIGN/PT2_B=BH_SET+PT1_B
              $$ NO,
              
              B_PNTA     =GENERIC/POINT,DEPENDENT,CARTESIAN,$
                          NOM/XYZ,<(SCN_B_U.HIT[PT1_B].TX),(SCN_B_U.HIT[PT1_B].TY),(SCN_B_U.HIT[PT1_B].TZ)>,$
                          MEAS/XYZ,<(SCN_B_U.HIT[PT1_B].X),(SCN_B_U.HIT[PT1_B].Y),(SCN_B_U.HIT[PT1_B].Z)>,$
                          NOM/IJK,<(SCN_B_U.HIT[PT1_B].TI),(SCN_B_U.HIT[PT1_B].TJ),(SCN_B_U.HIT[PT1_B].TK)>,$
                          MEAS/IJK,<(SCN_B_U.HIT[PT1_B].I),(SCN_B_U.HIT[PT1_B].J),(SCN_B_U.HIT[PT1_B].K)>
              B_PNTB     =GENERIC/POINT,DEPENDENT,CARTESIAN,$
                          NOM/XYZ,<(SCN_B_U.HIT[PT2_B].TX),(SCN_B_U.HIT[PT2_B].TY),(SCN_B_U.HIT[PT2_B].TZ)>,$
                          MEAS/XYZ,<(SCN_B_U.HIT[PT2_B].X),(SCN_B_U.HIT[PT2_B].Y),(SCN_B_U.HIT[PT2_B].Z)>,$
                          NOM/IJK,<(SCN_B_U.HIT[PT2_B].TI),(SCN_B_U.HIT[PT2_B].TJ),(SCN_B_U.HIT[PT2_B].TK)>,$
                          MEAS/IJK,<(SCN_B_U.HIT[PT2_B].I),(SCN_B_U.HIT[PT2_B].J),(SCN_B_U.HIT[PT2_B].K)>
              $$ NO,
              
                          ASSIGN/B1_PR=("B_PT1_"+INDX)
                          ASSIGN/PTB1_PR=B1_PR.PR
                          ASSIGN/B2_PR=("B_PT2_"+INDX)
                          ASSIGN/PTB2_PR=B2_PR.PR
              $$ NO,
              
              DIM BCROSS_2= 3D DISTANCE FROM POINT B_PNTA TO POINT B_PNTB,SHORTEST=OFF,NO_RADIUS  UNITS=IN,$
              GRAPH=OFF  TEXT=OFF  MULT=1000.00  OUTPUT=BOTH
              AX       MEAS    NOMINAL        DEV       +TOL       -TOL     OUTTOL
              M      26.6080    26.6080     0.0000     0.0050     0.0020     0.0000 --#------
              $$ NO,
              From 2 - 90 the assignments are the same for the pattern, only #1 is unique to prevent point overlap. Then I come back to clean up the information I was looking for with:

              Code:
                          ASSIGN/B_OUT=0
                          ASSIGN/CNTR_B=0
                          ASSIGN/DIB_ID="BCROSS_"
                          DO/
                          ASSIGN/CNTR_B=CNTR_B+1
                          ASSIGN/F_GRP=DIB_ID+CNTR_B
                          ASSIGN/DISTB[CNTR_B]=F_GRP.M.MEAS
                          IF/F_GRP.M.MEAS>26.613 OR F_GRP.M.MEAS<26.606
                            ASSIGN/B_OUT=B_OUT+1
                          END_IF/
                          UNTIL/CNTR_B==90
              $$ NO,
              
                          ASSIGN/MAX_B=MAX(DISTB)
                          ASSIGN/MIN_B=MIN(DISTB)
                          ASSIGN/AVG_B=((INDX-B_OUT)/INDX)*100
              $$ NO,
              
                          COMMENT/OPER,NO,FULL SCREEN=NO,AUTO-CONTINUE=NO,
                          "Max:             "+MAX_B
                          "Min:             "+MIN_B
                          "Avg:             "+AVG_B
                          "Cross Sections:  "+INDX
                          "Factor:          "+FCTR
                          "HALF:            "+BH_SET
                          "Out Tol:         "+B_OUT
              This is only reported in a text box to stop the offline cycle for testing. I will convert these values as needed into a generic feature (point) to report with tolerancing for my save-file.

              Thank you to everyone who attempted to assist! I got the chance to learn some new options!

              Comment

              Related Topics

              Collapse

              Working...
              X