redshift 1.3.17 → 1.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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