Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update forest firefighters to R2023b #19

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion projects/forest_firefighters/README.md
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ This simulation features a small forest wildfire and a few firefighter robots: a
Users can run the wildfire simulation and program the behavior of the robots to fight the fire.
They can also improve the models of the robot and even design new ones.

**Warning**: This project works only with Webots R2021b.
**Updates**: - 01/02/2024 updated for version R2023b.


![fire](https://user-images.githubusercontent.com/12995815/131650395-876f5ce5-ecdc-4eb7-83bc-a86f94709e32.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 41 additions & 13 deletions projects/forest_firefighters/controllers/fire/fire.py
Original file line number Diff line number Diff line change
@@ -41,22 +41,22 @@ def __init__(self, node):
self.smoke = None
self.fire_count = 0
self.translation = node.getField('translation').getSFVec3f()
self.scale = node.getField('size').getSFFloat() / 10
self.scale = node.getField('scale').getSFFloat()
self.robustness = random.uniform(self.ROBUSTNESS_VARIATION, self.ROBUSTNESS_VARIATION)
node.getField('burnt').setSFBool(False) # Ensure normal tree as initial state

def stopFire(self):
if self.fire:
fire_translation_field = self.fire.getField('translation')
fire_translation = fire_translation_field.getSFVec3f()
t = [fire_translation[0], fire_translation[1], fire_translation[2]]
t[1] = 10000000
fire_translation_field.setSFVec3f(t)
self.fire = None
if self.smoke:
smoke_translation_field = self.smoke.getField('translation')
smoke_translation = smoke_translation_field.getSFVec3f()
t = [smoke_translation[0], smoke_translation[1], smoke_translation[2]]
t[1] = 10000000
t[2] = 1000000
smoke_translation_field.setSFVec3f(t)
self.smoke = None

@@ -100,6 +100,7 @@ def cleanWater(self):
if altitude < 0:
self.waterBalls.remove(waterBall)
waterBall.remove()

def altitude(self):
return self.node.getField('translation').getSFVec3f()[2]

@@ -111,6 +112,8 @@ class Wind():
def __init__(self):
self.intensity = random.random()
self.angle = random.uniform(0, 2 * math.pi)
print('Wind angle:', self.angle)
print('Wind intensity:', self.intensity)

def evolve(self):
if self.RANDOM_EVOLUTION:
@@ -131,10 +134,17 @@ def correctedDistance(self, tree1, tree2, propagation_radius): # distance betwe
x_wind = self.intensity * math.cos(self.angle)
y_wind = self.intensity * math.sin(self.angle)
dx = tree1.translation[0] + propagation_radius * x_wind - tree2.translation[0]
dy = tree1.translation[1] + propagation_radius * y_wind - tree2.translation[1]
dz = tree1.translation[2] - tree2.translation[2]
dy = tree1.translation[1] - tree2.translation[1]
dz = tree1.translation[2] + propagation_radius * y_wind - tree2.translation[2]
return math.sqrt(dx * dx + dy * dy + dz * dz)

def fire_shape_url(shape_node):
if shape_node.getBaseTypeName() == 'Shape':
appr_node = shape_node.getField('appearance').getSFNode()
return appr_node.getField('url').getMFString(0)
else:
print('Node is not an instance of Shape, nothing to return')
return None

class Fire(Supervisor):
FLAME_CYCLE = 13 # there are 13 images in the flame animation
@@ -157,6 +167,7 @@ def __init__(self):
self.trees = []

self.robots = []
self.fire_sprites = []

n = self.children.getCount()
for i in range(n):
@@ -189,6 +200,7 @@ def __init__(self):
def ignite(self, tree):
if tree.fire_count > 1: # already burnt
return
print('Starting fire in:', tree.translation)
tree.fire_scale = tree.scale
fire = f'Fire {{ translation {tree.translation[0]} {tree.translation[1]} {tree.translation[2]} ' \
f'scale {tree.fire_scale} {tree.fire_scale} {tree.fire_scale} }}'
@@ -198,6 +210,19 @@ def ignite(self, tree):
tree.fire_scale_field = tree.fire.getField('scale')
tree.fire_translation = tree.fire_translation_field.getSFVec3f()

node_child = tree.fire.getProtoField('children').getMFNode(0)
if node_child.getBaseTypeName() == 'Shape':
appr_node = node_child.getField('appearance').getSFNode()
tree.fire_shape_field = appr_node.getField('url')

if len(self.fire_sprites) == 0:
self.fire_sprites.append(fire_shape_url(node_child))
for i in range(self.FLAME_CYCLE):
node_child = tree.fire.getProtoField('children').getMFNode(i)
if node_child.getBaseTypeName() == 'Pose':
txr_node = node_child.getField('children').getMFNode(0)
self.fire_sprites.append(fire_shape_url(txr_node))

def burn(self, tree):
if self.update_fire:
tree.fire_count += 1
@@ -206,11 +231,14 @@ def burn(self, tree):
if tree.fire_count == self.FLAME_PEAK * self.FLAME_CYCLE:
tree.node.getField('burnt').setSFBool(True)
tree.fire_scale_field.setSFVec3f([tree.fire_scale, tree.fire_scale, tree.fire_scale])

if tree.fire_scale < tree.scale:
tree.stopFire()
t = [tree.fire_translation[0], tree.fire_translation[1], tree.fire_translation[2]]
t[1] -= 100000 * tree.fire_scale * (tree.fire_count % 13)
tree.fire_translation_field.setSFVec3f(t)
if tree.fire:
sprite_field = tree.fire.getField('spriteBase')
sprite_field.setMFString(0, '../protos/' + self.fire_sprites[tree.fire_count % self.FLAME_CYCLE])
self.propagate(tree)
if tree.fire_count == 1:
smoke = f'Smoke {{ translation {tree.translation[0]} {tree.translation[1]} {tree.translation[2]} ' \
@@ -246,7 +274,7 @@ def checkExtinction(self, tree): # check and extinct the fire if there is water
if water_radius / robot.MAX_WATER_RADIUS > fire_size:
tree.stopFire()
return True
return False
return False

def run(self):
start_fire_now = False
@@ -257,9 +285,10 @@ def run(self):

message = self.wwiReceiveText()
if message:
print('Message:', message)
self.wind.update(message)
self.wind.evolve()

self.wwiSendText('{"angle":%f, "intensity":%f}' % (self.wind.angle, self.wind.intensity))

for robot in self.robots:
@@ -279,18 +308,17 @@ def run(self):
self.update_fire = False
self.fire_clock += 1

extinction = []
extinction = []
for tree in self.trees:
if tree.fire:
self.burn(tree)
extinction.append(self.checkExtinction(tree))

if True in extinction:
self.ignite(random.choice(self.trees))
self.ignite(random.choice(self.trees))
else:
for robot in self.robots: # the simulation starts when the mavic got an altitude > 40
if not start_fire_now and robot.name == "Mavic 2 PRO" and robot.altitude() > 40:
start_fire_now = True

start_fire_now = True
controller = Fire()
controller.run()
Binary file removed projects/forest_firefighters/forest_fire.png
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ function drawDial() {

// x and y axis
drawAxis('red', Math.PI / 2, 'x')
drawAxis('green', 0, 'y')
drawAxis('blue', 0, 'z')
}

function drawAxis(color, angle, letter) {
55 changes: 29 additions & 26 deletions projects/forest_firefighters/protos/Fire.proto
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#VRML_SIM R2021b utf8
#VRML_SIM R2023b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A fire with flame animation

EXTERNPROTO "Fire/FlameAppearance.proto"

PROTO Fire [
field SFVec3f translation 0 0 0
field SFRotation rotation 0 0 1 0
field SFVec3f scale 1 1 1
field MFString spriteBase "Fire/textures/fire_00.png"
]
{
Transform {
@@ -15,7 +18,7 @@ PROTO Fire [
scale IS scale
children [
DEF FLAME Shape {
appearance FlameAppearance {}
appearance FlameAppearance { url IS spriteBase }
geometry DEF FLAME_GEOMETRY IndexedFaceSet {
coord Coordinate {
point [
@@ -52,86 +55,86 @@ PROTO Fire [
}
}
Transform {
translation 0 100000 0
translation 0 0 100000.0
children Shape {
appearance FlameAppearance { url "textures/fire_01.png" }
appearance FlameAppearance { url "Fire/textures/fire_01.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 200000 0
translation 0 0 200000.0
children Shape {
appearance FlameAppearance { url "textures/fire_02.png" }
appearance FlameAppearance { url "Fire/textures/fire_02.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 300000 0
translation 0 0 300000.0
children Shape {
appearance FlameAppearance { url "textures/fire_03.png" }
appearance FlameAppearance { url "Fire/textures/fire_03.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 400000 0
translation 0 0 400000.0
children Shape {
appearance FlameAppearance { url "textures/fire_04.png" }
appearance FlameAppearance { url "Fire/textures/fire_04.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 500000 0
translation 0 0 500000.0
children Shape {
appearance FlameAppearance { url "textures/fire_05.png" }
appearance FlameAppearance { url "Fire/textures/fire_05.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 600000 0
translation 0 0 600000.0
children Shape {
appearance FlameAppearance { url "textures/fire_06.png" }
appearance FlameAppearance { url "Fire/textures/fire_06.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 700000 0
translation 0 0 700000.0
children Shape {
appearance FlameAppearance { url "textures/fire_07.png" }
appearance FlameAppearance { url "Fire/textures/fire_07.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 800000 0
translation 0 0 800000.0
children Shape {
appearance FlameAppearance { url "textures/fire_08.png" }
appearance FlameAppearance { url "Fire/textures/fire_08.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 900000 0
translation 0 0 900000.0
children Shape {
appearance FlameAppearance { url "textures/fire_09.png" }
appearance FlameAppearance { url "Fire/textures/fire_09.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 1000000 0
translation 0 0 1000000.0
children Shape {
appearance FlameAppearance { url "textures/fire_10.png" }
appearance FlameAppearance { url "Fire/textures/fire_10.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 1100000 0
translation 0 0 1100000.0
children Shape {
appearance FlameAppearance { url "textures/fire_11.png" }
appearance FlameAppearance { url "Fire/textures/fire_11.png" }
geometry USE FLAME_GEOMETRY
}
}
Transform {
translation 0 1200000 0
translation 0 0 1200000.0
children Shape {
appearance FlameAppearance { url "textures/fire_12.png" }
appearance FlameAppearance { url "Fire/textures/fire_12.png" }
geometry USE FLAME_GEOMETRY
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#VRML_SIM R2021b utf8
#VRML_SIM R2023b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A flame appearance
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#VRML_SIM R2021b utf8
#VRML_SIM R2022a utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A flame appearance
218 changes: 108 additions & 110 deletions projects/forest_firefighters/protos/Sassafras.proto

Large diffs are not rendered by default.

94 changes: 48 additions & 46 deletions projects/forest_firefighters/protos/Smoke.proto
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
#VRML_SIM R2021b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A smoke of a fire from the top

PROTO Smoke [
field SFVec3f translation 0 0 0
field SFRotation rotation 0 0 1 0
field SFVec3f scale 1 1 1
]
{
Transform {
translation IS translation
rotation IS rotation
scale IS scale
children [
DEF SMOKE Shape {
appearance SmokeAppearance {}
geometry DEF SMOKE_GEOMETRY IndexedFaceSet {
coord Coordinate {
point [
-1 -1 15
1 -1 15
-1 1 15
1 1 15
]
}
texCoord TextureCoordinate {
point [
0 0
1 0
0 1
1 1
]
}
coordIndex [
2 0 1 3 -1
]
texCoordIndex [
2 0 1 3 -1
]
}
}
]
}
}
#VRML_SIM R2023b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A smoke of a fire from the top

EXTERNPROTO "Fire/SmokeAppearance.proto"

PROTO Smoke [
field SFVec3f translation 0 0 0
field SFRotation rotation 0 0 1 0
field SFVec3f scale 1 1 1
]
{
Transform {
translation IS translation
rotation IS rotation
scale IS scale
children [
DEF SMOKE Shape {
appearance SmokeAppearance {}
geometry DEF SMOKE_GEOMETRY IndexedFaceSet {
coord Coordinate {
point [
-1 -1 15
1 -1 15
-1 1 15
1 1 15
]
}
texCoord TextureCoordinate {
point [
0 0
1 0
0 1
1 1
]
}
coordIndex [
2 0 1 3 -1
]
texCoordIndex [
2 0 1 3 -1
]
}
}
]
}
}
434 changes: 215 additions & 219 deletions projects/forest_firefighters/protos/UnevenForest.proto

Large diffs are not rendered by default.

80 changes: 40 additions & 40 deletions projects/forest_firefighters/protos/Water.proto
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
#VRML_SIM R2021b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A fire with flame animation

PROTO Water [
field SFVec3f translation 0 0 0
field SFFloat radius 0.1
field SFString name "water"
]
{
Solid {
translation IS translation
name IS name
children [
Shape {
appearance PBRAppearance {
baseColor 0.447059 0.623529 0.811765
transparency 0.5
metalness 0
}
geometry Sphere {
radius IS radius
}
}
]
physics Physics {
density -1
mass 1
centerOfMass [
0 0 0
]
inertiaMatrix [
1 1 1
0 0 0
]
}
}
}

#VRML_SIM R2023b utf8
# license: Creative Commons Attribution 4.0 International License.
# license url: https://creativecommons.org/licenses/by/4.0/legalcode
# A fire with flame animation

PROTO Water [
field SFVec3f translation 0 0 0
field SFFloat radius 0.1
field SFString name "water"
]
{
Solid {
translation IS translation
name IS name
children [
Shape {
appearance PBRAppearance {
baseColor 0.447059 0.623529 0.811765
transparency 0.5
metalness 0
}
geometry Sphere {
radius IS radius
}
}
]
physics Physics {
density -1
mass 1
centerOfMass [
0 0 0
]
inertiaMatrix [
1 1 1
0 0 0
]
}
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 12 additions & 11 deletions projects/forest_firefighters/worlds/.forest_firefighters.wbproj
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
Webots Project File version R2021b
perspectives: 000000ff00000000fd000000030000000000000188000003ccfc0100000003fb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f00770100000000000001880000006900fffffffb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f007700000001a0000000830000000000000000fb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f007700000001ba000000690000000000000000000000010000011c000002f1fc0200000001fb0000001400540065007800740045006400690074006f00720100000016000002f10000003f00ffffff00000003000005ae000000d9fc0100000001fb0000001a0043006f006e0073006f006c00650041006c006c0041006c006c010000018a000005ae0000006900ffffff00000490000002f100000001000000020000000100000008fc00000000
simulationViewPerspectives: 000000ff0000000100000002000001000000051a0100000002010000000100
sceneTreePerspectives: 000000ff0000000100000002000000c0000000fa0100000002010000000200
Webots Project File version R2023b
perspectives: 000000ff00000000fd000000030000000000000188000003ccfc0100000003fb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f00770100000000000001880000000000000000fb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f007700000001a0000000830000000000000000fb0000001e00480074006d006c0052006f0062006f007400570069006e0064006f007700000001ba00000069000000000000000000000001000001df0000017bfc0200000001fb0000001400540065007800740045006400690074006f007200000000170000017b0000003f00ffffff00000003000002ca00000154fc0100000001fb0000001a0043006f006e0073006f006c00650041006c006c0041006c006c0100000000000002ca0000006900ffffff000002ca0000022900000001000000020000000100000008fc00000000
simulationViewPerspectives: 000000ff0000000100000002000000fc000002c20100000002010000000100
sceneTreePerspectives: 000000ff00000001000000030000001f000000c0000000fa0100000002010000000200
maximizedDockId: -1
centralWidgetVisible: 1
orthographicViewHeight: 1
textFiles: -1
robotWindow: robot
globalOptionalRendering: CoordinateSystem
consoles: Console:All:All
renderingDevicePerspectives: Mavic 2 PRO(2):camera;1;1.245;0;0
renderingDevicePerspectives: Mavic 2 PRO:camera;1;1.235;5.67493e-10;0.402092
renderingDevicePerspectives: Spot:left flank camera;0;0.141667;0;0.633802
renderingDevicePerspectives: Spot:left head camera;0;0.12963;0;0
renderingDevicePerspectives: Spot:rear camera;0;0.141667;0;0.633802
renderingDevicePerspectives: Spot:right flank camera;0;0.125926;0.0734597;0.673709
renderingDevicePerspectives: Spot:right head camera;0;0.141667;0;0.00496278
renderingDevicePerspectives: Mavic 2 PRO(2):camera;0;1;0;0
renderingDevicePerspectives: Mavic 2 PRO:camera;0;1;0.0217391;0.498986
renderingDevicePerspectives: Spot:left flank camera;0;0.24537;0;0
renderingDevicePerspectives: Spot:left head camera;0;0.24537;0;0
renderingDevicePerspectives: Spot:rear camera;0;0.24537;0;0
renderingDevicePerspectives: Spot:right flank camera;0;0.24537;0;0
renderingDevicePerspectives: Spot:right head camera;0;0.24537;0;0
141 changes: 73 additions & 68 deletions projects/forest_firefighters/worlds/forest_firefighters.wbt

Large diffs are not rendered by default.