Skip to content

Commit

Permalink
Merge pull request #127 from mhhwang1/126-tower-class-and-tests
Browse files Browse the repository at this point in the history
Adding Tower Class and Tests
  • Loading branch information
e10harvey authored Jul 25, 2024
2 parents e0a9512 + 1e79f8b commit 19cfad1
Show file tree
Hide file tree
Showing 7 changed files with 467 additions and 0 deletions.
176 changes: 176 additions & 0 deletions opencsp/common/lib/csp/Tower.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
"""
Tower Class
"""

import matplotlib.pyplot as plt
import numpy as np

from opencsp.common.lib.geometry.Pxyz import Pxyz
import opencsp.common.lib.render_control.RenderControlTower as rct
from opencsp.common.lib.csp.RayTraceable import RayTraceable
from opencsp.common.lib.render_control.RenderControlPointSeq import RenderControlPointSeq
from opencsp.common.lib.render_control.RenderControlTower import RenderControlTower
from opencsp.common.lib.render.View3d import View3d


class Tower(RayTraceable):
"""
Tower representation.
All parameter values are in meters using ENU (East, North, Up)
coordinate system. Values are relative to the field coordinates.
Parameters:
-----------
name : str
The name of this Tower. Used for special styles given in the draw method.
origin : Pxyz
The center of Tower. All other points in the tower are relative to this value.
parts : list[str]
The parts that build the Tower. Includes walls (top, northface, southface, bottom), and optionl target.
height : float
The height of Tower. Currently set for NSTTF Tower height of 61 m.
east : float
The East wall of the Tower. Currently set for 8.8 m. TODO, MHH find dimensions of tower (in particular width)
west : float
The West wall of the Tower. Currently set for 8.8 m.
south : float
The South wall of the Tower. Currently set for 8.8 m.
north : float
The North wall of the Tower. Currently set for 8.8 m.
x_aim : float
The x component of the target in relation to the Tower origin.
y_aim : float
The y component of the target in relation to the Tower origin.
z_aim : float
The z component of the target in relation to the Tower origin.
"""

def __init__(
self,
name: str,
origin: Pxyz,
parts: list[str] = ["whole tower"],
height: float = 100,
east: float = 8.8,
west: float = -8.8,
south: float = -8.8,
north: float = 8.8,
x_aim: float = 0,
y_aim: float = 8.8,
z_aim: float = 100,
):

# parameters used for control tower at NSTTF
# tower_control= Tower(name='Sandia NSTTF Control Tower',
# origin = np.array([0,0,0]),
# height=25,
# east = 8.8,
# west = -8.8,
# south = 284,
# north = 300)
"""Create a new Tower instance.
Parameters:
-----------
name The name of this Tower. Used for special styles given in the draw method.
origin The center of Tower, as a three vector xyz coordinate.
all measurements in meters using ENU coordinate system.
"""
super(Tower, self).__init__()
self.name = name
self.origin = origin
self.parts = parts
self.height = height
self.east = east
self.west = west
self.south = south
self.north = north
self.x_aim = x_aim
self.y_aim = y_aim
self.z_aim = z_aim
self.target_loc = Pxyz([x_aim, y_aim, z_aim])

# Tower faces, top, and bottom
self.top = [
[self.east, self.north, self.height],
[self.west, self.north, self.height],
[self.west, self.south, self.height],
[self.east, self.south, self.height],
]

self.northface = [
[self.east, self.north, self.height],
[self.west, self.north, self.height],
[self.west, self.north, 0],
[self.east, self.north, 0],
]
"""
The top-left, top-right, bottom-right, bottom-left corners of the Tower,
as viewed when standing north of the tower and facing south.
"""

self.southface = [
[self.east, self.south, self.height],
[self.west, self.south, self.height],
[self.west, self.south, 0],
[self.east, self.south, 0],
]
"""
The top-left, top-right, bottom-right, bottom-left corners of the Tower,
as viewed when standing south of the tower and facing north.
"""

self.bottom = [
[self.east, self.north, 0],
[self.west, self.north, 0],
[self.west, self.south, 0],
[self.east, self.south, 0],
]

self.point = [self.x_aim, self.y_aim, self.z_aim]
"""
The target location given the x, y, and z components.
"""

def walls(self):
"""Returns the list of walls as top, north, south, and bottom."""
# Assumes that Tower coordinates have been set, and the walls have been set.
# # Later we can add a more meaningful check for this.
return [self.top, self.northface, self.southface, self.bottom]

# RENDERING

def draw(self, view: View3d, tower_style: RenderControlTower) -> None:
# Assumes that heliostat configuration has already been set.

tower_style = tower_style.style(self.name)

# Whole tower
if 'whole tower' in self.parts:
self.parts += ['top', 'northface', 'southface', 'bottom', 'northface']

# Top of tower
if "top" in self.parts:
view.draw_xyz_list(self.top, close=True, style=tower_style.wire_frame)

# Northface of tower
if "northface" in self.parts:
view.draw_xyz_list(self.northface, close=True, style=tower_style.wire_frame)

# Southface of tower
if "southface" in self.parts:
view.draw_xyz_list(self.southface, close=True, style=tower_style.wire_frame)

# Bottom of tower
if "bottom" in self.parts:
view.draw_xyz_list(self.bottom, close=True, style=tower_style.wire_frame)

# target on northface of tower
if "target" in self.parts:
view.draw_xyz(self.point, style=tower_style.target)

return
77 changes: 77 additions & 0 deletions opencsp/common/lib/render_control/RenderControlTower.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import opencsp.common.lib.render_control.RenderControlPointSeq as rcps
import opencsp.common.lib.render_control.RenderControlText as rctxt
from opencsp.common.lib.render_control.RenderControlPointSeq import RenderControlPointSeq


class RenderControlTower:
"""
Render control for towers.
"""

def __init__(
self,
centroid=False,
draw_name=False,
name_style=None,
draw_outline=True,
point_styles: RenderControlPointSeq = None,
wire_frame: RenderControlPointSeq = None,
target: RenderControlPointSeq = None,
) -> None:
"""
Controls for rendering a tower.
Parameters
----------
centroid : bool, optional
If True, centroid will be drawn on graph as origin of tower. Default is False.
draw_name : bool, optional
If True then the name will be drawn on graph. Default is False.
name_style : None | str
If draw_name = True, then styles name using RenderControlText. By default from RenderControlText, color 'black'.
draw_outline : bool
Draws outline of Tower using wire_frame style. Default is True.
point_styles : RenderControlPointSeq
Draws target as a point on the Tower.
wire_frame : RenderControlPointSeq
Outline style of Tower, that draws walls edges. Default is RenderControlSeq outline, color 'black', linewidth '1'.
target : RenderControlPointSeq
If target, draws a point on Tower. Default color is 'red', with shape 'x', markersize '6'.
"""

# default values
if name_style is None:
namestyle = rctxt.default(color='k')
if point_styles is None:
point_styles = rcps.marker()
if wire_frame is None:
wire_frame = rcps.outline()
if target is None:
target = rcps.marker(marker='x', color='r', markersize=6)

super(RenderControlTower, self).__init__()

self.centroid = centroid
self.draw_name = draw_name
self.name_style = name_style
self.draw_outline = draw_outline
self.point_styles = point_styles
self.wire_frame = wire_frame
self.target = target

def style(self, any):
""" "style" is a method commonly used by RenderControlEnsemble.
We add this method here so that RenderControlHeliostat can be used similarly to RenderControlEnsemble."""
return self

# Common Configurations


def normal_tower():
# Overall tower outline only.
return RenderControlTower()


def no_target():
# tower outline with no target.
return RenderControlTower(wire_frame=rcps.outline(color='g'), target=False)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Metadata:
Figure number: 1
Name: tto001_Single Tower
Title: Single Tower
Code tag: TestTowerOutput.test_single_tower()
View spec: 3d

Title:
Single Tower

Caption:
A single Sandia NSTTF tower.

Comments:
Demonstration of single 3d tower drawing.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Metadata:
Figure number: 1
Name: tto002_Multiple Towers
Title: Multiple Towers
Code tag: TestTowerOutput.test_multiple_towers()
View spec: 3d

Title:
Multiple Towers

Caption:
Sandia NSTTF reciever and control tower.

Comments:
Demonstration of single 3d tower drawing.
Black tower is NSTTF receiver tower.
Green tower is NSTTF control tower.

Loading

0 comments on commit 19cfad1

Please sign in to comment.