redshift 1.3.17 → 1.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/.bnsignore +23 -0
  2. data/.gitignore +7 -6
  3. data/README +22 -4
  4. data/RELEASE-NOTES +16 -0
  5. data/examples/lotka-volterra.rb +1 -1
  6. data/examples/modular-component-def.rb +49 -0
  7. data/examples/robots/README +49 -0
  8. data/examples/robots/lib/base.rb +38 -0
  9. data/examples/robots/lib/explosion.rb +48 -0
  10. data/examples/robots/lib/missile.rb +75 -0
  11. data/examples/robots/lib/radar.rb +56 -0
  12. data/examples/robots/lib/robot.rb +105 -0
  13. data/examples/robots/lib/shell-world.rb +167 -0
  14. data/examples/robots/lib/tracker.rb +16 -0
  15. data/examples/robots/robots.rb +53 -0
  16. data/examples/shell.rb +1 -2
  17. data/ext/redshift/buffer/buffer.c +102 -0
  18. data/ext/redshift/buffer/buffer.h +17 -0
  19. data/ext/redshift/buffer/dir.rb +1 -0
  20. data/ext/redshift/buffer/extconf.rb +2 -0
  21. data/ext/redshift/util/isaac/extconf.rb +2 -0
  22. data/ext/redshift/util/isaac/isaac.c +129 -0
  23. data/ext/redshift/util/isaac/rand.c +140 -0
  24. data/ext/redshift/util/isaac/rand.h +61 -0
  25. data/lib/redshift/mixins/shell.rb +72 -0
  26. data/lib/redshift/redshift.rb +1 -1
  27. data/lib/redshift/syntax.rb +12 -5
  28. data/lib/redshift/target/c/component-gen.rb +11 -8
  29. data/lib/redshift/target/c/flow/buffer.rb +17 -126
  30. data/lib/redshift/target/c/flow/delay.rb +5 -5
  31. data/lib/redshift/target/c/library.rb +12 -1
  32. data/lib/redshift/util/histogram.rb +1 -1
  33. data/lib/redshift/util/irb-shell.rb +81 -0
  34. data/lib/redshift/util/isaac.rb +22 -0
  35. data/lib/redshift/util/modular.rb +48 -0
  36. data/lib/redshift/util/tkar-driver.rb +1 -2
  37. data/lib/redshift/util/tracer/var.rb +1 -1
  38. data/lib/redshift/world.rb +9 -3
  39. data/rakefile +9 -1
  40. data/test/test.rb +23 -9
  41. data/test/test_buffer.rb +1 -1
  42. data/test/test_flow_trans.rb +3 -20
  43. metadata +50 -46
  44. data/lib/redshift/mixins/irb-shell.rb +0 -151
data/.bnsignore ADDED
@@ -0,0 +1,23 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # PROJ.ignore_file = '.gitignore'
8
+ #
9
+ # For a project with a C extension, the following would be a good set of
10
+ # exclude patterns (uncomment them if you want to use them):
11
+ # *.[oa]
12
+ # *~
13
+ announcement.txt
14
+ coverage
15
+ doc
16
+ pkg
17
+ *.bck
18
+ misc
19
+ junk
20
+ tmp
21
+ */tmp
22
+ */*/tmp
23
+ */junk
data/.gitignore CHANGED
@@ -1,8 +1,9 @@
1
1
  *.bck
2
- pkg
3
- doc
4
- junk/*
5
- tmp/*
2
+ /pkg
3
+ junk
6
4
  tmp
7
- */tmp
8
- */junk
5
+ *.o
6
+ *.so
7
+ /ext/*/*/Makefile
8
+ /ext/*/*/*/Makefile
9
+ /rdoc/*
data/README CHANGED
@@ -1,5 +1,23 @@
1
- To install:
1
+ = RedShift
2
+
3
+ A framework for simulation of networks of hybrid automata, similar to SHIFT and Lambda-SHIFT. Includes ruby-based DSL for defining simulation components, and ruby/C code generation and runtime.
4
+
5
+ There's no documentation yet. Start with the examples.
6
+
7
+ == Requirements
8
+
9
+ RedShift needs ruby 1.8.x and a compatible C compiler. If you can build native gems, you're all set.
10
+
11
+ == Env vars
12
+
13
+ If you have a multicore system and are using the gnu toolchain, set
14
+
15
+ REDSHIFT_MAKE_ARGS='-j -l2'
16
+
17
+ or some variation. You'll find that rebuilds of your simulation code go faster.
18
+
19
+ ----
20
+
21
+ Copyright (C) 2001-2010, Joel VanderWerf, vjoel@users.sourceforge.net
22
+ Distributed under the Ruby license. See www.ruby-lang.org.
2
23
 
3
- ruby install.rb config
4
- ruby install.rb setup
5
- ruby install.rb install
data/RELEASE-NOTES CHANGED
@@ -1,3 +1,19 @@
1
+ redshift 1.3.18
2
+
3
+ - added robots example
4
+
5
+ - redshift builds isaac and buffer code at install time, rather than run time
6
+
7
+ - added isaac extension and reverted tests to use it again
8
+
9
+ - use REDSHIFT_MAKE_ARGS
10
+
11
+ - added -j2 switch to test
12
+
13
+ - added modular.rb for modular use of redshift DSL, and an example
14
+
15
+ - some rdoc improvements
16
+
1
17
  redshift 1.3.17
2
18
 
3
19
  - added shell example with plotting and tk animation
@@ -24,7 +24,7 @@ require 'redshift/util/plot'
24
24
  include Plot::PlotUtils
25
25
 
26
26
  gnuplot do |plot|
27
- plot.command %{set title "Lotla-Volterra"}
27
+ plot.command %{set title "Lotka-Volterra"}
28
28
  plot.command %{set xlabel "time"}
29
29
  plot.add data, %{using 1:2 title "foxes" with lines}
30
30
  plot.add data, %{using 1:3 title "rabbits" with lines}
@@ -0,0 +1,49 @@
1
+ # This example shows how to define things in a module and include that in a
2
+ # Component or World class.
3
+
4
+ require 'redshift'
5
+ require 'redshift/util/modular'
6
+
7
+ module ThermoStuff
8
+ extend Modular
9
+
10
+ continuous :temp
11
+
12
+ state :Heat, :Off
13
+
14
+ flow :Heat do # Must quote constants, since they are defined later
15
+ diff "temp' = (68 - temp)/3"
16
+ end
17
+
18
+ flow :Off do
19
+ diff "temp' = (45 - temp)/10"
20
+ end
21
+
22
+ transition :Heat => :Off do
23
+ guard "temp > 68 - 0.1"
24
+ end
25
+
26
+ transition :Off => :Heat do
27
+ guard "temp < 66"
28
+ end
29
+
30
+ setup do
31
+ start :Off
32
+ end
33
+ end
34
+
35
+ class Thermostat < RedShift::Component
36
+ include ThermoStuff
37
+
38
+ default do
39
+ self.temp = 35
40
+ end
41
+ end
42
+
43
+ world = RedShift::World.new
44
+ thermostat = world.create Thermostat
45
+
46
+ world.evolve 30 do |w|
47
+ printf "%6.2f: %7.3f %s\n", w.clock, thermostat.temp, thermostat.state
48
+ end
49
+
@@ -0,0 +1,49 @@
1
+ = Robots
2
+
3
+ An example covering some of the basic language features plus some techniques for interactive simulation and for animating simulation output.
4
+
5
+ To run the example:
6
+
7
+ ruby robots.rb
8
+
9
+ Press ^C to break into a command shell, and then ^D to continue the simulation run. The "help" command in the shell shows you the commands beyond the basic irb.
10
+
11
+ Use -h from the command line to see the switches.
12
+
13
+ To change the setup of the world, edit robots.rb. You can add and move robots and missles.
14
+
15
+ You can also move the objects interactively in the Tk visualization.
16
+
17
+ Currently, the robots move around and the missles track and hit them.
18
+
19
+ = To do
20
+
21
+ == robots physics
22
+
23
+ - collision detection and effect on robot health
24
+
25
+ - walls and obstacles
26
+
27
+ == robot control
28
+
29
+ - command language to evade attackers and launch missiles based on radar
30
+
31
+ - maybe similar to RoboTalk (from RoboWar)
32
+
33
+ - multirobot coordination using comm channels
34
+
35
+ == game mechanics
36
+
37
+ - robot shop
38
+
39
+ - tournaments
40
+
41
+ == dev tools
42
+
43
+ - debugger
44
+
45
+ - plotter
46
+
47
+ == visualization
48
+
49
+ - for each sensor, show nearest robot by drawing arrow
@@ -0,0 +1,38 @@
1
+ # This file encapsulates some relatively uninteresting tweaks and additions
2
+ # to make the demo go smoothly.
3
+
4
+ require 'redshift'
5
+
6
+ class RobotComponent < RedShift::Component
7
+ attr_accessor :name # for display; can be anything
8
+ attr_reader :id # for keeping track of tk objects; must be uniq int
9
+
10
+ default do
11
+ @id = world.next_id
12
+ @name = id
13
+ end
14
+
15
+ def tk_delete
16
+ "delete #{id}"
17
+ end
18
+
19
+ state :Done
20
+
21
+ transition Done => Exit do
22
+ action do
23
+ world.exited << self
24
+ end
25
+ end
26
+ end
27
+
28
+ require 'shell-world'
29
+ require 'robot'
30
+
31
+ class RobotWorld < RedShift::World
32
+ include ShellWorld
33
+
34
+ def show_status
35
+ grep(Robot) {|r| r.show_status}
36
+ nil
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ class Explosion < RobotComponent
2
+ continuous :size, :max_size, :x, :y, :vx, :vy
3
+ continuous :t, :prev_t
4
+
5
+ setup do
6
+ self.t = self.prev_t = 0
7
+ end
8
+
9
+ state :Expanding
10
+ start Expanding
11
+
12
+ flow Expanding do
13
+ diff " x' = vx "
14
+ diff " y' = vy "
15
+ diff " size' = 10 * sqrt(size) "
16
+ diff " t' = 1 "
17
+ end
18
+
19
+ transition Expanding => Done do
20
+ guard " size > max_size "
21
+ end
22
+
23
+ transition Expanding => Expanding do
24
+ guard " t > prev_t "
25
+ action do
26
+ world.grep(Robot) do |r|
27
+ if (x - r.x)**2 + (y - r.y)**2 < size**2
28
+ r.messages <<
29
+ Robot::InflictDamage.new(10*(max_size - size)*(t - prev_t))
30
+ end
31
+ end
32
+ end
33
+ reset :prev_t => "t"
34
+ end
35
+
36
+ def tk_add
37
+ "add explosion #{id} - 0 #{x} #{y} 0 #{size} #{-size}"
38
+ end
39
+
40
+ # emit string representing current state
41
+ def tk_update
42
+ fade = ("%x" % ((size / max_size) * 256)) * 2
43
+ "moveto #{id} #{x} #{y}\n" +
44
+ "param #{id} 0 #{size}\n" +
45
+ "param #{id} 1 #{-size}\n" +
46
+ "param #{id} 2 0xFF#{fade}"
47
+ end
48
+ end
@@ -0,0 +1,75 @@
1
+ class Missile < RobotComponent
2
+ require 'explosion'
3
+
4
+ link :target => Robot
5
+
6
+ continuous :x, :y, :vx, :vy, :v, :heading, :power
7
+ constant :turn_rate
8
+
9
+ state :Seeking
10
+ start Seeking
11
+
12
+ default do
13
+ self.power = 40
14
+ self.v = 20
15
+ self.turn_rate = 60 * Math::PI / 180 # convert from degrees per sec
16
+ end
17
+
18
+ flow Seeking do
19
+ alg " vx = v * cos(heading) "
20
+ alg " vy = v * sin(heading) "
21
+
22
+ diff " x' = vx "
23
+ diff " y' = vy "
24
+
25
+ diff "power' = -1"
26
+
27
+ alg " distance =
28
+ sqrt(
29
+ pow(x - target.x, 2) +
30
+ pow(y - target.y, 2) ) "
31
+
32
+ alg " angle =
33
+ atan2(target.y - y,
34
+ target.x - x) "
35
+
36
+ alg " error = fmod(heading - angle, 2*#{Math::PI}) "
37
+ diff " heading' = turn_rate * (
38
+ error < #{-Math::PI/2} ?
39
+ #{-Math::PI/2} :
40
+ (error > #{Math::PI/2} ?
41
+ #{Math::PI/2} : -error)) "
42
+ end
43
+
44
+ transition Seeking => Done do
45
+ guard "power < 0"
46
+ end
47
+
48
+ transition Seeking => Done do
49
+ guard "distance < 1"
50
+ action do
51
+ unless target.state == Exit
52
+ create Explosion do |e|
53
+ e.size = 1
54
+ e.max_size = power
55
+ e.x = x
56
+ e.y = y
57
+ e.vx = vx
58
+ e.vy = vy
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # return string that adds an instance of the shape with label t.name,
65
+ # position based on (x, y), and rotation based on heading
66
+ def tk_add
67
+ "add missile #{id} - 11 #{x} #{y} #{heading}"
68
+ end
69
+
70
+ # emit string representing current state
71
+ def tk_update
72
+ "moveto #{id} #{x} #{y}\n" +
73
+ "rot #{id} #{heading}"
74
+ end
75
+ end
@@ -0,0 +1,56 @@
1
+ require 'tracker'
2
+
3
+ class Radar < RobotComponent
4
+ constant :period => 0.200
5
+ continuous :t
6
+ continuous :distance
7
+ continuous :angle
8
+ attr_accessor :host_robot, :nearest_robot
9
+ link :nearest_tracker => Tracker
10
+
11
+ attr_accessor :trackers
12
+ default do
13
+ self.trackers = []
14
+ end
15
+
16
+ # add +robots+ to the list of objects tracked by this radar
17
+ def track_robots *robots
18
+ robots.flatten.each do |robot|
19
+ tracker = create Tracker
20
+ tracker.host = host_robot
21
+ tracker.target = robot
22
+ trackers << tracker
23
+ end
24
+ end
25
+
26
+ state :Sleep, :Measure
27
+ start Sleep
28
+
29
+ flow Sleep do
30
+ diff " t' = -1 "
31
+ end
32
+
33
+ flow Sleep, Measure do
34
+ alg " angle_deg = fmod(angle * #{180/Math::PI}, 360)"
35
+ end
36
+
37
+ transition Sleep => Measure do
38
+ guard " t <= 0 "
39
+ action do
40
+ scan_for_nearest_robot
41
+ end
42
+ end
43
+
44
+ transition Measure => Sleep do
45
+ reset :t => "period"
46
+ end
47
+
48
+ def scan_for_nearest_robot
49
+ self.nearest_tracker = trackers.min_by {|tracker| tracker.distance}
50
+ if nearest_tracker
51
+ self.nearest_robot = nearest_tracker.target ## how to delay this?
52
+ self.distance = nearest_tracker.distance
53
+ self.angle = nearest_tracker.angle
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,105 @@
1
+ class Robot < RobotComponent
2
+ require 'radar'
3
+ require 'explosion'
4
+ require 'missile'
5
+
6
+ continuous :x, :y, :vx, :vy, :v, :heading, :power, :health
7
+ link :radar => :Radar
8
+
9
+ InflictDamage = Struct.new(:value)
10
+ queue :messages
11
+
12
+ default do
13
+ self.radar = create Radar
14
+ radar.host_robot = self
15
+
16
+ self.power = 100
17
+ self.health = 100
18
+ end
19
+
20
+ state :Stopped, :Rolling, :Exploding
21
+ start :Rolling
22
+
23
+ flow Stopped, Rolling do
24
+ alg " vx = v * cos(heading) "
25
+ alg " vy = v * sin(heading) "
26
+
27
+ alg " heading_deg = fmod(heading * #{180/Math::PI}, 360)"
28
+
29
+ diff " x' = vx "
30
+ diff " y' = vy "
31
+
32
+ # a bit of friction, i.e. deceleration proportional to velocity
33
+ diff " v' = -0.01 * v"
34
+ end
35
+
36
+ flow Rolling do
37
+ # it takes power to maintain speed
38
+ diff " power' = -1 "
39
+ end
40
+
41
+ transition Rolling => Stopped do
42
+ guard " power <= 0 "
43
+ end
44
+
45
+ transition Rolling => Exploding, Stopped => Exploding do
46
+ guard " health <= 0 "
47
+ action do
48
+ create Explosion do |e|
49
+ e.size = 1
50
+ e.max_size = 60
51
+ e.x = x
52
+ e.y = y
53
+ e.vx = vx
54
+ e.vy = vy
55
+ end
56
+ end
57
+ end
58
+
59
+ transition Exploding => Done
60
+
61
+ transition Rolling => Rolling, Stopped => Stopped do
62
+ wait :messages => InflictDamage
63
+ action do
64
+ m = messages.pop
65
+ case m
66
+ when RedShift::SimultaneousQueueEntries
67
+ dmg_msgs, other = m.partition {|n| InflictDamage === n}
68
+ messages.unpop other
69
+ dmg_msgs.each do |n|
70
+ self.health -= n.value
71
+ end
72
+ else
73
+ self.health -= m.value
74
+ end
75
+ end
76
+ end
77
+
78
+ # return string that adds an instance of the shape with label t.name,
79
+ # position based on (x, y), and rotation based on heading
80
+ def tk_add
81
+ "add robot #{id} - 10 #{x} #{y} #{heading}\n" +
82
+ "param #{id} 0 #{name}\n" +
83
+ "param #{id} 1 359\n" +
84
+ "param #{id} 2 359"
85
+ end
86
+
87
+ # emit string representing current state
88
+ def tk_update
89
+ e = (power / 100.0) * 359.9
90
+ h = (health / 100.0) * 359.9
91
+ "moveto #{id} #{x} #{y}\n" +
92
+ "rot #{id} #{heading}\n" +
93
+ "param #{id} 1 #{e}\n" +
94
+ "param #{id} 2 #{h}"
95
+ end
96
+
97
+ def show_status
98
+ printf \
99
+ "%5.3f sec: closest blip is %s, at %8.3f meters, bearing %3d degrees\n",
100
+ world.clock,
101
+ radar.nearest_robot ? radar.nearest_robot.name : "none",
102
+ radar.distance,
103
+ (radar.angle * 180/Math::PI).round.abs
104
+ end
105
+ end