[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

LOGO-L> Substitute for "setorientation towardsxyz"



Hi.

After a few hours of pushing vectors around a piece of paper, moving 
protractors around at funny angles in the air and finally actually doing 
some coding, I've come up with this substitute for "setorientation 
towardsxyz".

The reason I think it's necessary is that after doing "setorientation 
towardsxyz [100 100 100]", the turtle ends up pointing towards [100 100 
100], but if you follow this with "rt 90", you can't be sure where it's 
pointing.  So we need some rule which will fix the turtle's final position.

With the new procedure "settowardsxyz" given here, the new orientation of 
the turtle depends on the initial position.  To orientate itself towards a 
point, the turtle turns left or right until it is "above" or "below" the 
point and then pitches its nose up or down accordingly.  I find this rule 
makes visualising the final orientation of the turtle relatively easy.

The other procedures given here are just to test settowardsxyz to see that 
it works.  Totally off-subject: A strange problem I had was that when I was 
flooding the commander with output (uncomment the "print ..." lines) it 
occasionally clicked and output blank lines on one computer I tried it on.

George did say he was going to look at this problem too, so he may well 
have come up with another solution.

Tom

---
Begin "settowardsxyz.lgo"
I don't trust my email program with attachments any more. :(
---
to _test :p :q
; Test that settowardsxyz works between points :p and :q
  pu setposxyz :p pd settowardsxyz :q fd distancexyz :q
; (print "Result: posxyz)
end

to aaa
; Draws some axes (pretty pointless :) and then plots points at random
; directions and checks that the turtle has actually reached the correct
; point.

  cs perspective ht
  ask -1 [setposxyz [1000 1000 1000]]
  drawaxes

  ; Comment out the next line to keep record of maxerror between tests
  localmake "maxerror 0

  repeat 1000 [
    localmake "x 100 * (3 - random 6)
    localmake "y 100 * (3 - random 6)
    localmake "z 100 * (3 - random 6)

    localmake "px 300 - random 600
    localmake "py 300 - random 600
    localmake "pz 300 - random 600

    ; print (combine "From: (list :px :py :pz))
    ; print (combine "To: (list :x :y :z))
    _test (list :px :py :pz) (list :x :y :z)
    
    if :maxerror < abs ((first posxyz) - :x) [
      make "maxerror abs ((first posxyz) - :x)
    ]

    if :maxerror < abs ((first butfirst posxyz) - :y) [
      make "maxerror abs ((first butfirst posxyz) - :y)
    ]

    if :maxerror < abs ((first butfirst butfirst posxyz) - :z) [
      make "maxerror abs ((first butfirst butfirst posxyz) - :z)
    ]
  ]
  print (list "Maximum "error: :maxerror)
end

to dotprod :a :b
; Returns the dot product of vectors :a and :b.
  output apply "sum (map [?1 * ?2] :a :b)
end

to drawaxes
; Draws the positive parts of the grid axes 
  pu home pd settowardsxyz [1000 0 0] fd distancexyz [1000 0 0]
  pu home pd settowardsxyz [0 1000 0] fd distancexyz [0 1000 0]
  pu home pd settowardsxyz [0 0 1000] fd distancexyz [0 0 1000]
end

to settowardsxyz :F
; setorientation towardsxyz does not completely define the new orientation
; of the turtle. settowardsxyz defines the new orientation of the turtle by
; these rules:
; 
; 1. Turns right until the target position is in the same pitch plane (sets
; yaw).
;
; 2. Pitch up or down until headed towards the target (sets pitch).
;
; I haven't found a situation where this gives an inappropriate
; orientation, but there probably is one, seeing as this is a hard problem.
; There are another three complementary functions which could be defined,
; which set pitch then yaw, roll then pitch and roll then yaw.  It might be
; useful to have these as well, but someone else can do them :)

  localmake "InitialPenState pendownp
  localmake "T posxyz
  localmake "fvec vecsub :F :T
  pu fd 1 localmake "cvec vecsub posxyz :T bk 1
  rt 90 fd 1 localmake "rvec vecsub posxyz :T bk 1 lt 90
  down 90 fd 1 localmake "nvec vecsub posxyz :T bk 1 up 90
  localmake "avec vecscale (dotprod :fvec :cvec) :cvec
  localmake "bvec vecscale (dotprod :fvec :rvec) :rvec
  localmake "svec vecadd :avec :bvec

  ifelse (veclen :svec) = 0 [
    ifelse (dotprod :fvec :nvec) < 0 [up 90] [down 90]
  ] [
    localmake "costheta (dotprod :svec :cvec) / veclen :svec
    if (abs :costheta) > 1 [  ; May happen due to numerical errors
      ifelse :costheta < 0 [localmake "costheta -1][localmake "costheta 1]
    ]
    localmake "theta arccos :costheta
    ifelse (dotprod :fvec :rvec) < 0 [lt :theta] [rt :theta]

    if not ((veclen :fvec) = 0) [
      localmake "cosalpha ((dotprod :svec :fvec) / ((veclen :svec) * ~
        (veclen :fvec)))
      if (abs :cosalpha) > 1 [  ; May happen due to numerical errors
        ifelse :cosalpha < 0 [localmake "cosalpha -1][ ~
          localmake "cosalpha 1]
      ]

      localmake "alpha arccos :cosalpha
      ifelse (dotprod :fvec :nvec) < 0 [up :alpha] [down :alpha]
    ]
  ]

  ifelse :InitialPenState [pd][pu]
end

to vecadd :a :b
; Adds vectors :a and :b
  output (map [?1 + ?2] :a :b)
end

to vecdiv :v :s
; Divides vector :v by scalar :s
  output map (list "? "/ :s) :v
end

to veclen :v
; Returns the length of vector :v
  localmake "a first :v
  localmake "b first butfirst :v
  localmake "c first butfirst butfirst :v
  output sqrt(:a*:a + :b*:b + :c*:c)
end

to vecscale :s :v
; Multiplies vector :v by scalar :s
  output map (list "? "* :s) :v
end

to vecsub :a :b
; Subtracts 3d vector :b from 3d vector :a
  output (map [?1 - ?2] :a :b)
end
---------------------------------------------------------------
Please post messages to the Logo forum to logo-l@gsn.org.  Mail
questions about the list administration to logofdn@gsn.org.  To
unsubscribe send    unsubscribe logo-l    to majordomo@gsn.org.



Global SchoolNet Foundation - Linking Kids Around the World!
Copyright GSN - All Rights Reserved - Comments & Questions
Visit GSN's Global Schoolhouse for more exciting learning resources!
Search our Site - Home