Keeping track of an objects local coordinate space - c++

Ok, so - this is heavily related to my previous question Transforming an object between two coordinate spaces, but a lot more direct and it should have an obvious answer.
An objects local coordinate space, how do I "get a hold of it"? Say that I load an Orc into my game, how do I know programatically where it's head, left arm, right arm and origin (belly button?) is? And when I know where it is do I need to save it manually or is it something that magically exists in the DirectX API? In my other question one person said something about storing a vertice for X,Y,Z directions and and origin? How do I find these vertices? Do I pick them arbitrarily, assign them in the model before loading it into my game? etc.
This is not about transforming between coordinate spaces

Actually, it is about transforming between coordinate spaces.
Ok, you understand that you can have a Matrix that does Translation or Rotation. (Or scaling. Or skew. Etc.) That you can multiply such a Matrix by a point (V) to get the new (translated/rotated/etc) point. E.g.:
Mtranlate = [ 1 0 0 Tx ] * V = [ Vx ] = [ Vx + Tx ]
[ 0 1 0 Ty ] [ Vy ] [ Vy + Ty ]
[ 0 0 1 Tz ] [ Vz ] [ Vz + Tz ]
[ 0 0 0 1 ] [ 1 ] [ 1 ]
Or rotation about the X/Y/Z axis:
Mrotate_x = [ 1 0 0 0 ] * V = [ Vx ] = [ Vx ]
[ 0 cos -sin 0 ] [ Vy ] [ Vy*cos - Vz*sin ]
[ 0 sin cos 0 ] [ Vz ] [ Vy*sin + Vz*cos ]
[ 0 0 0 1 ] [ 1 ] [ 1 ]
That you can combine multiple operations by multiplying the matrices together. For example: Mnew = Mtranslate * Mrotate_x.
(And yes, the order does matter!)
So given a real-world base origin, you could translate to your (known/supplied) orc's xy location, deduce from the terrain at that point what your orc's feet's z location is and translate to that. Now you have your orc's "feet" in global coordinates. From there, you might want to rotate your orc so he faces a particular direction.
Then translate upwards (based on your orc's model) to find it's neck. From the neck, we can translate upwards (and perhaps rotate) to find its head or over to find its shoulder. From the shoulder, we can rotate and translate to find the elbow. From the elbow we can rotate and translate to find the hand.
Each component of your orc model has a local reference frame. Each is related to the reference frame where it is attached by one or more transforms (matrices). By multiplying through all the local matrices (transforms), we can eventually see how to go from the orc's feet to his hand.
(Mind you, I'd animate the orc and just use his feet x,y,z location. Otherwise it's too much work.)
You see a lot of this sort of thing in robotics which can provide a nice elementary introduction to forward kinematics. In robotics, at least with the simpler robots, you have a motor which rotates, and a limb-length to translate by. And then there's another motor. (In contrast, the human shoulder-joint can rotate about all three axis at once.)
You might look over the course HANDOUTS for CMU's Robotic Manipulation class (15-384).
Perhaps something like their Forward Kinematics Intro.

Related

Netlogo Lists: detecting the patch in a list with max distance to one specific patch - for each turtle

I want to solve a problem in Netlogo that so far exceeds my programming skills. I want to built a list for each turtle which contains the furthest patch the turtle went on this "day". So far I tried to built a list were all patches are stored for each turtle. Now I want to calculate - for each turtle - the patch from this list that has maximum distance from its home (hide). I want to empty the list every night (thats not mandatory) Thats my code so far:
let temp-visited-patch-list lput patch-here temp-visited-patch-list
if period = night
[
[foreach [temp-visited-patch-list] [x -> set visited-patch-list lput (max x [distance hide]) visited-patch-list]]
let temp-visited-patch-list []
]
So I am not that far to extract the values for each turtle seperatly - and even the part I posted does not work. I get an "expected command" error. I would be very thankful for any suggestions to solve this problem.
Best regards
Olivia
This code has the turtles move, remember their furthest patch and turns those patches red and calculates average distance. It should help orient you how to use patches and turtle attributes to solve your question.
globals [home-patch]
turtles-own
[ farpatch
maxdistance
]
to setup
clear-all
set home-patch one-of patches
ask home-patch
[ set pcolor blue
sprout 20
]
reset-ticks
end
to go
repeat 20 [movement]
ask (patch-set [farpatch] of turtles) [set pcolor red]
type "Average max distance:" print mean [maxdistance] of turtles
tick
end
to movement
ask turtles
[ set heading random 360
forward 1
if distance home-patch > maxdistance
[ set maxdistance distance home-patch
set farpatch patch-here
]
]
end

Chemotaxis in NetLogo

I have made a gradient, and I am quite unsure as to how I can make my turtle(s) attracted to one end and also behave a different way. For instance, from light blue to dark blue. Dark blue would be where the food is (chemoattractant), and in this zone, the bacterias would prefer to run randomly or be more energetic. While, in the light blue area, there would be fewer turtles and their movements would be slow or "tumbling."
Overall, how do I make the turtles sense the chemoattractant or the gradient in the patch?
If pcolors were floating point you could just search the immediate neighbors and use
ask turtles [ uphill pcolor ]
but that won't work if the gradient is subtle. The turtles might just sit there.
If you store a floating-point patch variable "exact_color" , say, the next code will work but the angle of motion is always some multiple of 45 degrees.
ask turtles [ uphill exact_color]
So if you generalize the search to a larger radius to determine the local gradient,
this would work:
let neighborhood patches with [ distance myself <= search_radius]
let p max-one-of neighborhood [exact_color]
if [exact_color] of p > exact_color [ face p move-to p]
Here's a working implementation that assigns the color gradient then tracks it.
globals [ scentXC scentYC search_radius ] ;; location of center of maximum scent
patches-own [ exact_color ];
to setup
clear-all
print ("This assumes the world does not wrap");
;; decide to put center of attraction at ( 14, 7 )
set scentXC 14;
set scentYC 7;
;; search a larger radius for gradient since it may be low
set search_radius 5;
color_code_patches
;; next line can visually check work so far
;; ask N-of 20 patches [ set plabel pcolor]
create-turtles 10 [ setxy random-pxcor random-pycor set size 2 set shape "arrow" pen-down];
reset-ticks
end
to go
;; ask turtles [ uphill pcolor ] ;; fails because the gradient is too low
;; following works but the angle of motion is always a multiple of 45 degrees
;; ask turtles [ pen-down uphill exact_color] ;; move one step uphill
;; the following searches a larger neighborhood for the uphill direction
ask turtles
[
;; set search_radius 1.45 to simply search neighbors, ie "uphill exact_color"
let neighborhood patches with [ distance myself <= search_radius]
let p max-one-of neighborhood [exact_color] ;; or neighbors4
if [exact_color] of p > exact_color [ face p move-to p]
]
end
to color_code_patches
no-display
ask patches [
let blueness 0 ;; initialize to make the interpreter happy
let dist distancexy scentXC scentYC
ifelse (dist <= 1) [ set blueness 250 ]
[ set blueness (250 / dist ) ]
set exact_color blueness;
set blueness round blueness;
;;set pcolor [ 0 0 blueness] ;; for unknown reason this doesn't work so more complex
let color_assign ( word "set pcolor [ 0 0 " blueness " ] ")
run color_assign
]
display
end

Netlogo: How to transfer lists belonging to neighbours to a matrix?

A list called ownList2 consists of two parameters. Flockmates are all the neighbours in a given radius of the neighbour. I tried this code in version 6.0. But it doesn't work.
Basically, I want to put a list of equal dimension into a matrix. Is there something wrong I am doing? Or someone could improve the code piece?
ask turtles[set ownList2 (list who sensed)]
;sensed is sensor value of a turtle with respect to the patch.
;ownList2 is like a message of two bytes,
;first byte mentioning the identity of the itself
;second byte mentioning the value of the sensor.
ask turtles[
foreach (list flockmates)
[
i -> set m45 matrix:to-column-list ( list [ownList2] of i )
]
]
Result:
For turtle-0 with neighbours 1, 2, 3:
ownList2 ~ [1 200]
[2 400]
[3 900]
The m43 for turtle-0 should look like
[[1 200][2 400][3 900]]
Thanks for adding that information. Here is a toy example that might do what you need:
extensions [ matrix ]
turtles-own [ ownlist2 sensed m45 ]
to setup
ca
; Setup example turtles as per question
foreach [ 100 200 400 900 ] [
n ->
crt 1 [
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
set sensed n
set ownlist2 ( list who sensed )
]
]
; Get the turtles to create matrices from the ownlists of
; sorted other turtles
ask turtles [
set m45 matrix:from-column-list map [ i -> [ ownlist2] of i ] sort other turtles
]
; Example output:
ask turtle 0 [
print "Turtle 0's m45:"
print matrix:pretty-print-text m45
]
reset-ticks
end
Output example:
Turtle 0's m45:
[[ 1 2 3 ]
[ 200 400 900 ]]

NetLogo sort list of agents by a specific value

I have a model with 5000+ farmers and several factories. Sometimes a new factory is built, at which point I want the factory to do the following:
Create a list with all farmers and then sort that list according to distance of farmer to the factory (from low to high).
I have tried doing this with a table,
ask factory 1 [ask farmers [set distance-to-factory distance myself]]
ask factory 1 [set a table:group-agents farmers [distance-to-factory]]
but then the resulting agentsets are not ordered from low to high or vice versa. Moreover, I want the factory to be able afterwards to ask single agents from the ordered table (or list) to do something:
After ordering the farmers by their distance-to-factory, I want the factory to be able to ask farmers from that list to deliver their goods (i.e. the closest farmer is asked first, but when it has no goods, the second closest farmer is asked and so on).
Your help is much appreciated!
You need to create an agent variable for the factory that stores the list of farmers in distance order. Here is a full example, run it and inspect a factory to convince yourself that it works.
breed [factories factory]
breed [farmers farmer]
factories-own [my-farmers]
to setup
clear-all
create-farmers 100
[ setxy random-xcor random-ycor
set color yellow
set shape "circle"
set size 0.5
]
create-factories 3
[ setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
]
reset-ticks
end
to initialise-factory
set my-farmers sort-on [distance myself] farmers
end
Look at the initialise-factory procedure. The sort-on primitive operating on an agentset returns a list. And the [distance myself] of ... is calculating the distance back to the factory (because the factory is doing the asking and is therefore myself). So the list is sorted by distance to the factory.
Once you have created the list, you use list procedures (eg the item primitive) to do the asking specific farmers.
There are indeed multiple factories and the distance-to-factory is to the most recently created factory, but the my-farmers list that each factory has doesn't change.
I already used the profiler extension on a previous version of the model and that one was very slow because of every factory asking each farmer every time (once a year) if they had goods:
let closest-farmer (min-one-of farmers with [status = 0] [distance myself])
That is why I thought of every factory creating a list of farmers from closest to furthest, so that factories can run through that list. Below you find a more elaborate piece of code, I hope this helps you to get a better image.
breed [factories factory]
breed [farmers farmer]
globals [
count-down
total-capacity-factories
price-goods
]
farmers-own [
area
goods-per-area
goods
distance-to-factory
status
]
factories-own [
my-farmers
goods-delivered
capacity
revenues-this-year
total-revenues
]
to setup
clear-all
create-farmers 1000 [
setxy random-xcor random-ycor
set area one-of [10 50 100]
set goods-per-area one-of [5 10 15]
set color yellow
set shape "circle"
set size 0.5
]
create-factories 20 [
setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
]
set market-demand-goods 250000
set total-capacity-factories sum [capacity] of factories
set count-down 11
reset-ticks
end
to go
if count-down = 11 [
change-market-demand
ask farmers [
set status 0
set goods 0
]
]
if count-down = 10 [
ask farmers [
sow-seeds
]
]
if count-down = 5 [
if market-demand-goods - [capacity] of one-of factories > total-capacity-factories [
build-factory
]
]
if count-down = 2 [
ask farmers [
harvest-goods
]
ask factories [
receive-harvested-goods
sell-goods
]
]
set count-down count-down - 1
if count-down = 0 [
set count-down 11
]
end
to initialise-factory
set capacity 10000
ask farmers [
set distance-to-factory distance myself
]
set my-farmers (sort-on [distance-to-factory] farmers)
end
to change-market-demand
let chance random 100
if chance < 33 [
set market-demand-goods market-demand-goods - 50000
]
if chance >= 33 and chance < 66 [
set market-demand-goods market-demand-goods + 10000
]
if chance >= 66 [
set market-demand-goods market-demand-goods + 50000
]
let chance2 random 100
if chance2 < 50 [
set price-goods price-goods + 1
]
if chance2 >= 50 [
set price-goods price-goods - 1
]
end
to sow-seeds
set color brown
end
to build-factory
loop [
if total-capacity-factories >= market-demand-goods [stop]
create-factory 1 [
setxy random-xcor random-ycor
set color red
set shape "house"
set size 2
initialise-factory
set total-capacity-factories (total-capacity-factories + [capacity] of myself
]
end
to harvest-goods
set goods area * goods-per-area
end
to receive-harvested-goods
let i 0
loop [
if goods-delivered >= capacity [stop]
let closest-farmer-with-goods (item i my-farmers)
ifelse [status] of closest-farmer-with-goods = 0 [
set goods-delivered + [goods] of closest-farmer-with-goods
ask closest-farmer-with-goods [
set status "goods-delivered"
]
]
[set i i + 1]
]
end
to sell-goods
set revenues-this-year goods-delivered * price-goods
set total-revenues total-revenues + revenues-this-year
end
#JenB, thanks for the help! I also found out that it can be done as follows:
hatch factory 1 [
ask farmers [set distance-to-factory distance myself]
set my-farmers (sort-on [distance-to-factory] farmers)
]
Then I designed the following code for asking from the my-farmers list:
let i 0
loop [
if goods-delivered > capacity [stop]
let closest-farmer-with-goods (item i my-farmers)
ifelse [status] of closest-farmer-with-goods = 0 [ (; aka goods are not delivered yet to another factory)
set goods-delivered + [goods] of closest-farmer-with-goods
]
[set i i + 1] ; *else*
]
But this makes the model quite slow. Do you know how to make this simpler?

Netlogo : inequality doesn't work properly under foreach

It supposes to be a simple code, but I don't know why it doesn't work properly.
I want to change a color of non-white turtle back into white if a condition is fulfilled. I put inequality as the condition.
for example, if the amount of red turtle > = 5, then [ do something ].
No error message for the code, but I found that [ do something ] codes are executed before the condition is fulfilled. For example, it is executed when the amount of turtle is 1 or 4. And I also found that there are moments when it reach > = 5, [ do something] code is not executed.
Below is the code
to seize-value
ask consumers [set type-of-value ( list blue red green) ]
foreach type-of-value [
if count consumers with [color = ?] > = 5 [
let z consumers with [color = ?]
ask z [ set color white ]
ask consumers with [color = white] [set value? false]
ask one-of cocreation-patches [ sprout 1 [gen-prevalue]]
]]
end
I've tried using a single color, instead of a list of color (without - foreach) it doesn't work either.
Can anyone help with this?
Thank you
You have something like the following at the top of your code to set up type-of-value as an agent variable:
breed [ consumers consumer ]
consumers-own [ type-of-value ]
However, you are treating it as a global variable in your code. First you say ask consumers [set type-of-value ( list blue red green) ] to set the AGENT variable called type-of-value to the list of colours. But you end that ask [] statement before starting the foreach.
Unless the consumers have different lists of colours, what you really want is something more like this (untested). Note that I have also removed your multiple creations of the same agentset (for efficiency):
globals [ type-of-value ]
to setup
clear-all
...
set type-of-value ( list blue red green)
...
reset-ticks
end
to seize-value
*type "seize-value on tick " print ticks
foreach type-of-value
[ let changers consumers with [color = ?]
*print ?
*print count changers
if count changers >= 5
[ ask changers
[ set color white
set value? false
]
ask one-of cocreation-patches [ sprout 1 [gen-prevalue] ]
]
]
end
UPDATE for debugging I have added three lines that will output key information for debugging. They are marked with an asterisk (*). Add those lines (without the *) and look at the output.