Best way to pass initialized constants - python

I'm going to make an easy example on an application case of mine.
I am developing a gui with tkinter, my work is divided in 3 files:
constants:
CostoMedioEnergia = float(0.2) #
IncentivoAutFisico_Prop_Impianti = float(0.2)#
IncentivoAutFisico_DirittoSup = float(0.06)#
IncentivoAutFisico_Finanziatore = float(0.140)#
CostoFotovoltaico = float(1000)
ProduzioneFotovoltaico = float(1300) ##########
IncentivoRitDedicato = float(0.045)#
IncentivoMise = float(0.110)#
IncentivoArera = float(0.009)#
another file where I have the prototypes of the classes of users (here an example):
class ProprietarioImpianti(Parametri):
def __init__(self, ConsumiPrevisti, PotenzaContatore, PotenzaFotovoltaicoInstallato, PercEnerAutoconsumo, PercIncentivoAutconsumo, PercEnerCondivisa, PercMise, PercArera, PercIncentivoRitDedicato, IndiceUtente):
self.ConsumiPrevisti = ConsumiPrevisti
self.PotenzaContatore = PotenzaContatore
self.PotenzaFotovoltaicoInstallato = PotenzaFotovoltaicoInstallato
self.PercEnerCondivisa = PercEnerCondivisa #Energia in autoconsumo condiviso (percentuale sull'energia totale disponibile alla condivisione)
self.PercMise = PercMise #Percentuale incentivo Mise attributita all'utente
self.PercArera = PercArera # Percentuale incentivo Arera attribuita all'utente
self.PercEnerAutoconsumo = PercEnerAutoconsumo #Percentuale dell'energia prodotta che viene autoconsumata fisicamente
self.PercIncentivoAutoconsumo = PercIncentivoAutconsumo #Percentuale dell'incentivo autoconsumo attribuito all'utente
self.PercIncentivoRitDedicato = PercIncentivoRitDedicato
self.IndiceUtente = IndiceUtente
#property
def CostoMedioBolletta(self):
return self.ConsumiPrevisti * self.PotenzaContatore * CostoMedioEnergia
As you can see in the last line I'm using "CostoMedioEnergia" which is a constant imported from the previous file. The third and last file is my tkinter gui, you don't necessary need that, where I input some data and instantiate classes accordingly.
My question is: I want to input those constant data from the first file (such as CostoMedioEnergia) form the GUI in tkinter. What would be the best way to update my code so that I can use parameters form input? I thought to create a new class in the second file I mentioned (where all my other classes are) and to use inheritance. But this way I'd add a lot of attributes to my classes when I only need to store that information once and make it accessible to all classes without creating "copies" of the information in my "subclasses".

Related

Linearization of External System Dynamics in VectorSystem DoCalcVectorOutput Method

I am attempting to implement a custom linear MPC controller class in Drake, which inherits from the VectorSystem base class. This controller is supposed to linearize the dynamics of a given plant at its current operating point, and then perform a trajectory optimization.
I have defined the MPC controller class here.
class MpcController(VectorSystem):
def __init__(self, quadrotor_plant, init_state, target_state, time_horizon, max_time_samples, thrust_limit, obstacle_list):
# define this system as having 12 inputs and 4 outputs
VectorSystem.__init__(self, 12, 4)
self.quadrotor_plant = quadrotor_plant
self.init_state = init_state
self.target_state = target_state
self.time_horizon = time_horizon
self.max_time_samples = max_time_samples
self.thrust_limit = thrust_limit
self.obstacle_list = obstacle_list
self.current_step = 0
def DoCalcVectorOutput(self, context, inp, state, output):
quadrotor_context = self.quadrotor_plant.CreateDefaultContext()
# print("DoCalcVectorOutput quad input value", quad_input_port.HasValue(quadrotor_context))
# input into the controller is the state of the quadrotor
# set the context equal to the current state
quadrotor_context.SetContinuousState(inp)
current_state = inp
print(f"cur_quad_state = {current_state}")
print(f"quadrotor current input = {output}")
##################
# Linearize system dynamics - Take first order taylor series expansions of system
# around the operating point defined by quadrotor context
##################
eq_check_tolerance = 10e6 # we do not need to be at an equilibrium point
linear_quadrotor = Linearize(self.quadrotor_plant, quadrotor_context, \
equilibrium_check_tolerance = eq_check_tolerance )
I have setup my simulation like so:
# define the quadrotor plant using drake built in quadrotor plant class
# this is a System, not a MultiBodyPlant
quadrotor_plant = QuadrotorPlant()
# quadrotor_context = quadrotor_plant.CreateDefaultContext()
quadrotor_plant = builder.AddSystem(quadrotor_plant)
mpc_controller = MpcController(quadrotor_plant, initial_state, final_state, time_horizon, num_time_samples, thrust_limit, obstacles)
mpc_controller = builder.AddSystem(mpc_controller)
# connect the MPC controller to the quadrotor
builder.Connect(mpc_controller.get_output_port(0), quadrotor_plant.get_input_port(0))
builder.Connect(quadrotor_plant.get_output_port(0), mpc_controller.get_input_port(0))
# quad_context = quadrotor_plant.CreateDefaultContext()
# print(quadrotor_plant.get_input_port(0).HasValue(quad_context))
# Set up visualization in MeshCat
QuadrotorGeometry.AddToBuilder(builder, quadrotor_plant.get_output_port(0), scene_graph)
meshcat.Delete()
meshcat.ResetRenderMode()
meshcat.SetProperty('/Background','visible',False)
visualizer = MeshcatVisualizerCpp.AddToBuilder(builder, scene_graph, meshcat)
# end setup for visualization
################# Run Simulation ####################
#Set up a simulator to run this diagram
diagram = builder.Build()
quad_context = quadrotor_plant.CreateDefaultContext()
print(quadrotor_plant.get_input_port(0).HasValue(quad_context))
simulator = Simulator(diagram)
sim_context = simulator.get_mutable_context()
sim_context.SetContinuousState(initial_state)
# pass sim context into MpC controller to be used for linearization of dynamics
mpc_controller.set_sim_context(sim_context)
quadrotor_context = quadrotor_plant.GetMyMutableContextFromRoot(sim_context)
# quadrotor_plant.get_input_port(0).FixValue(quadrotor_context, [10.,10.,10.,10.])
end_time = 10.0
simulator.set_target_realtime_rate(1.0)
meshcat.AddButton('Stop Simulation')
while simulator.get_context().get_time() < end_time:
simulator.AdvanceTo(sim_context.get_time() + 0.1)
meshcat.DeleteAddedControls()
When I run this code I get the following runtime error:
RuntimeError: InputPort::Eval(): required InputPort[0] (propellor_force) of System ::_::drake/examples/quadrotor/QuadrotorPlant#00000000058fa1e0 (QuadrotorPlant) is not connected
However, I have clearly connected it.
To get around this, I have also tried passing the mutable context to the Linearize() method using:
quadrotor_context = quadrotor_plant.GetMyMutableContextFromRoot(sim_context)
However, when I do this I run into a different error:
SystemExit: Failure at bazel-out/k8-opt/bin/tools/install/libdrake/_virtual_includes/drake_shared_library/drake/systems/framework/vector_system.h:290 in DoCalcVectorOutput(): condition 'output->size() == 0' failed.
I believe this error is due to the fact that using the mutable context creates a scenario of infinite recursion, because Linearize() calls DoCalcVectorOutput for the MpcController, which in turn calls Linearize()...
It seems like neither of these approaches is correct. What is the best approach to linearizing the dynamics of an external plant inside of the DoCalcVectorOutput() method of a controller in Drake?
Your analysis of the error is correct. The quadrotor_context that you have in the MpcController does not have the input port connected, which is why you get the error when you call Linearize. You need to set or connect the input port inside that method in order to specify which input you are linearizing around.
One solution would be to use something like self.quadrotor_plant.get_input_port().FixValue(quadrotor_context, u0) in your MpcController DoCalcVectorOutput method.

Pydrake: Creating a Trajectory Source for RigidTransformations

I've been trying to create a TrajectorySource for RigidTransforms to pass into a DifferentialInverseKinematicsIntegrator which only takes in RigidTransforms in its input port.
def createTraj(time, pose):
times = []
poses = []
for step in time:
times.append(time[step])
poses.append(pose[step])
return PiecewisePose.MakeLinear(times, poses)
Initially, I tried to directly pass in the output from createTraj above into TrajectorySource but ran into the issue of my trajectory having more than one columns: Failure at systems/primitives/trajectory_source.cc:21 in TrajectorySource(): condition 'trajectory.cols() == 1' failed.
import matplotlib.pyplot as plt, mpld3
class DexterTest():
# Output from createTraj is passed as parameter: traj into constructor
def __init__(self, traj):
builder = DiagramBuilder()
self.station = DexterPPStation(1e-4, "/opt/drake/share/drake/manipulation/models/final_dexter_description/urdf/dexter.urdf")
self.station.CreateBins("/opt/drake/share/drake/examples/manipulation_station/models/bin.sdf", RigidTransform(np.array([0.5,0,0])), RigidTransform(np.array([0,0.5,0])))
self.station.CreateRandomPickingObjects(3)
self.station.AddDexter()
builder.AddSystem(self.station)
self.station.Finalize()
self.diff_ik = DifferentialInverseKinematicsIntegrator(self.station.controller_plant, self.station.plant.GetFrameByName("link6", self.station.dexter["instance"]), self.station.time_step, DifferentialInverseKinematicsParameters(7,7))
builder.AddSystem(self.diff_ik)
#=========================================== Likely Source of Error ===========================================
pose = builder.AddSystem(PoseSystem())
p_G_source = builder.AddSystem(TrajectorySource(traj.get_position_trajectory()))
w_G_source = builder.AddSystem(TrajectorySource(traj.get_orientation_trajectory()))
builder.Connect(p_G_source.get_output_port(), pose.GetInputPort("p_G"))
builder.Connect(w_G_source.get_output_port(), pose.GetInputPort("r_G"))
builder.Connect(pose.get_output_port(), self.diff_ik.get_input_port())
#======================================================================================
MeshcatVisualizerCpp.AddToBuilder(builder, self.station.GetOutputPort("query_object"), meshcat)
self.diagram = builder.Build()
self.simulator = Simulator(self.diagram)
self.diagram_context = self.simulator.get_mutable_context()
self.station_context = self.station.GetMyMutableContextFromRoot(self.diagram_context)
self.plant_context = self.station.GetSubsystemContext(self.station.plant, self.station_context)
self.station.SetRandomPoses(self.plant_context)
builder.Connect(self.diff_ik.get_output_port(), self.station.GetInputPort("dexter_position"))
def run(self):
self.simulator.set_target_realtime_rate(2.0)
self.simulator.AdvanceTo(1)
class PoseSystem(LeafSystem):
def __init__(self):
LeafSystem.__init__(self)
self.p_G = self.DeclareVectorInputPort("p_G", BasicVector(3))
self.r_G = self.DeclareVectorInputPort("r_G", BasicVector(4))
self.DeclareAbstractOutputPort("X_G", Value[RigidTransform], self.CalcOutput)
def CalcOutput(self, context, output):
pose = RigidTransform(Quaternion(self.r_G.Eval(context)), self.p_G.Eval(context))
output.set_value(pose)
Instead, I tried to break up my trajectory into its orientation and position parts, add them to the input ports of a custom system, and then reconstruct them together in the output port. However, this gives me the following RuntimeError once the run method is called: RuntimeError: This multibody element does not belong to the supplied MultibodyTree.
Any help would be greatly appreciated!
I think you are very close. The PoseSystem looks like it should be a solution to the problem you've articulated in your post. (The error about MultibodyTree must be coming from the other part of your code.
You don't actually need to break the RigidTransform up into orientation / translation to create your PoseSystem, your CalcOutput could just call output.set_value(poses.Eval(t)) if poses is a PiecewisePose trajectory.
I have an example of doing this in the PickAndPlaceTrajectory class in this notebook: https://github.com/RussTedrake/manipulation/blob/008cec6343dd39063705287e6664a3fee71a43b8/pose.ipynb

.set in function is not being found in other function so it's creating an error tkinter python

I'm trying to create a GUI, in the nav menu you can click a cascade option to open another window where you can click roll to generate a set of numbers. It comes up with error. I think it's because the function is called from another function I just don't know how to get that function to call it/ if there is any other ways to fix this. I've tried global functions and looking it up but haven't found anything other than using classes so far, which I don't know how to do.
line 147, in totalRolls
txtresultsOut.set(totalRollResults)
NameError: name 'txtresultsOut' is not defined
Here is the code that is relevant to it. I've called the function to skip having to input all the other code for the main gui window.
def rollSix():
s = 0
numbers = [0,0,0,0]
for i in range(1,5):
numbers[s] = randrange(1,7)
s += 1
numbers.remove(min(numbers))
Result = sum(numbers)
totalRollResults.append(Result)
def totalRolls():
rollOne()
rollTwo()
rollThree()
rollFour()
rollFive()
rollSix()
txtresultsOut.set(totalRollResults)
def rollw():
rollWindow = tix.Tk()
rollWindow.title("Dice Rolls")
diceLabel = Label(rollWindow, text = "Click Roll for your Stats")
diceLabel.grid(row = 0, column = 0)
rollBtn = Button(rollWindow, text = "Roll Stats", command = totalRolls)
rollBtn.grid(row = 1, column = 0)
txtresultsOut = StringVar()
resultsOut = Entry(rollWindow, state = "readonly", textvariable = txtresultsOut)
resultsOut.grid(row = 2, column = 0)
rollw()
first of all I would NOT recommend using StringVar(). You can use the .get() method of Entry to obtain the value inside the same. Try this way and make a global declaration of the Entry whose values you want to get in other functions.
EDIT------------
#you can use the following code to make your entry active to be edited.
entry.configure(state='normal')
# insert new values after deleting old ones (down below)
entry.delete(0,END)
entry.insert(0, text_should_be_here)
# and finally make its state readonly to not let the user mess with the entry
entry.configure(state='readonly')

VTK changes for "GetImage" and "Update"

I'm trying to get into Extension programming in 3DSlicer using Python.
There is a tutorial online. Unfortunately there is a problem with the third example script "HelloSharpen". I did the exact same thing they did but I get this error:
Traceback (most recent call last):
File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 105, in onApply
laplacian.SetInput(inputVolume.GetImageData())
AttributeError: 'vtkImagingGeneralPython.vtkImageLaplacian' object has no attribute 'SetInput'
I solved this by changing laplacian.SetInput(inputVolume.GetImageData()) to laplacian.SetInputData(inputVolume.GetImageData()) because I read that they changed this in the newer versions of VTK.
However when I try to run this a new error comes up:
Traceback (most recent call last):
File "C:/Users/johan/Desktop/HelloPythonSlicer4/helloPython/code/HelloSharpen.py", line 107, in onApply
laplacian.GetOutput().Update()
AttributeError: 'vtkCommonDataModelPython.vtkImageData' object has no attribute 'Update'
It seems that laplacian.GetOutput().Update() is causing problems so
I tried to find something on the Internet if they also changed this in the newer versions of VTK but I couldn't find anything. I tried to change this into "UpdateData" but this doesn't work.
Do you know if they also changed this and if yes, do you know what I should replace this with?
Here is the full code for "HelloSharpen":
from __main__ import vtk, qt, ctk, slicer
#
# HelloSharpen
#
class HelloSharpen:
def __init__(self, parent):
parent.title = "Hello Python Part D - Sharpen"
parent.categories = ["Examples"]
parent.dependencies = []
parent.contributors = ["Jean-Christophe Fillion-Robin (Kitware)",
"Steve Pieper (Isomics)",
"Sonia Pujol (BWH)"] # replace with "Firstname Lastname (Org)"
parent.helpText = """
Example of scripted loadable extension for the HelloSharpen tutorial.
"""
parent.acknowledgementText = """
This file was originally developed by Jean-Christophe Fillion-Robin, Kitware Inc.,
Steve Pieper, Isomics, Inc., and Sonia Pujol, Brigham and Women's Hospital and was
partially funded by NIH grant 3P41RR013218-12S1 (NAC) and is part of the National Alliance
for Medical Image Computing (NA-MIC), funded by the National Institutes of Health through the
NIH Roadmap for Medical Research, Grant U54 EB005149.""" # replace with organization, grant and thanks.
self.parent = parent
#
# qHelloPythonWidget
#
class HelloSharpenWidget:
def __init__(self, parent = None):
if not parent:
self.parent = slicer.qMRMLWidget()
self.parent.setLayout(qt.QVBoxLayout())
self.parent.setMRMLScene(slicer.mrmlScene)
else:
self.parent = parent
self.layout = self.parent.layout()
if not parent:
self.setup()
self.parent.show()
def setup(self):
# Collapsible button
self.laplaceCollapsibleButton = ctk.ctkCollapsibleButton()
self.laplaceCollapsibleButton.text = "Sharpen Operator"
self.layout.addWidget(self.laplaceCollapsibleButton)
# Layout within the laplace collapsible button
self.laplaceFormLayout = qt.QFormLayout(self.laplaceCollapsibleButton)
#
# the volume selectors
#
self.inputFrame = qt.QFrame(self.laplaceCollapsibleButton)
self.inputFrame.setLayout(qt.QHBoxLayout())
self.laplaceFormLayout.addWidget(self.inputFrame)
self.inputSelector = qt.QLabel("Input Volume: ", self.inputFrame)
self.inputFrame.layout().addWidget(self.inputSelector)
self.inputSelector = slicer.qMRMLNodeComboBox(self.inputFrame)
self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
self.inputSelector.addEnabled = False
self.inputSelector.removeEnabled = False
self.inputSelector.setMRMLScene( slicer.mrmlScene )
self.inputFrame.layout().addWidget(self.inputSelector)
self.outputFrame = qt.QFrame(self.laplaceCollapsibleButton)
self.outputFrame.setLayout(qt.QHBoxLayout())
self.laplaceFormLayout.addWidget(self.outputFrame)
self.outputSelector = qt.QLabel("Output Volume: ", self.outputFrame)
self.outputFrame.layout().addWidget(self.outputSelector)
self.outputSelector = slicer.qMRMLNodeComboBox(self.outputFrame)
self.outputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
self.outputSelector.setMRMLScene( slicer.mrmlScene )
self.outputFrame.layout().addWidget(self.outputSelector)
self.sharpen = qt.QCheckBox("Sharpen", self.laplaceCollapsibleButton)
self.sharpen.toolTip = "When checked, subtract laplacian from input volume"
self.sharpen.checked = True
self.laplaceFormLayout.addWidget(self.sharpen)
# Apply button
laplaceButton = qt.QPushButton("Apply")
laplaceButton.toolTip = "Run the Laplace or Sharpen Operator."
self.laplaceFormLayout.addWidget(laplaceButton)
laplaceButton.connect('clicked(bool)', self.onApply)
# Add vertical spacer
self.layout.addStretch(1)
# Set local var as instance attribute
self.laplaceButton = laplaceButton
def onApply(self):
inputVolume = self.inputSelector.currentNode()
outputVolume = self.outputSelector.currentNode()
if not (inputVolume and outputVolume):
qt.QMessageBox.critical(
slicer.util.mainWindow(),
'Sharpen', 'Input and output volumes are required for Laplacian')
return
# run the filter
laplacian = vtk.vtkImageLaplacian()
laplacian.SetInputData(inputVolume.GetImageData())
laplacian.SetDimensionality(3)
laplacian.GetOutput().Update()
ijkToRAS = vtk.vtkMatrix4x4()
inputVolume.GetIJKToRASMatrix(ijkToRAS)
outputVolume.SetIJKToRASMatrix(ijkToRAS)
outputVolume.SetAndObserveImageData(laplacian.GetOutput())
# optionally subtract laplacian from original image
if self.sharpen.checked:
parameters = {}
parameters['inputVolume1'] = inputVolume.GetID()
parameters['inputVolume2'] = outputVolume.GetID()
parameters['outputVolume'] = outputVolume.GetID()
slicer.cli.run( slicer.modules.subtractscalarvolumes, None, parameters, wait_for_completion=True )
selectionNode = slicer.app.applicationLogic().GetSelectionNode()
selectionNode.SetReferenceActiveVolumeID(outputVolume.GetID())
slicer.app.applicationLogic().PropagateVolumeSelection(0)
TL;DR Change laplacian.GetOutput().Update() to laplacian.Update().
Explanation:
As per this link, there was a major change introduced in VTK 6. In summary, newer versions of VTK have separated algorithms and the data in two different class hierarchies. In newer versions of VTK, the Update() function can be called only on objects which have been derived from the vtkAlgorithm class. You can look at the inheritance diagram of vtkImageLaplacian here and it is indeed derived from vtkAlgorithm class. So laplacian.Update() will work.
As the name suggests vtkImageData is a data object. laplacian.GetOutput() returns a vtkImageData object and that's why you cannot call Update() function on it and therefore you get the error.

Maya Python read and set optionMenu value via variable

I have a module that creates a savedSettings.py file after the user used my tool this file is filled with variables to load into the gui next time the tool is used.
I have some checkboxes and a optionMenu. Reading and setting the variables for the checkboxes is as simple as:
# loadsettings into gui
if os.path.exists(userSettings):
sys.path.append(toolFolder)
import savedSettings
viewCBvalue = savedSettings.viewCheck
ornamentCBvalue = savedSettings.ornamentCheck
renderCBvalue = savedSettings.renderCheck
I thought the optionMenu would be the same and wrote:
encodingOMvalue = savedSettings.encodingCheck
When I now tell the GUI to use the variables:
cmds.checkBoxGrp( 'viewCB', label = 'View: ', value1 = viewCBvalue)
cmds.checkBoxGrp( 'ornamentCB', label = 'Show Ornaments: ', value1 = ornamentCBvalue)
cmds.checkBoxGrp( 'renderCB', label = 'Render offscreen: ', value1 = renderCBvalue)
cmds.optionMenuGrp( 'encodingOM', label = 'Encoding ', value = encodingOMvalue )
cmds.menuItem( 'tif', label = 'tif')
cmds.menuItem( 'jpg', label = 'jpg')
cmds.menuItem( 'png', label = 'png')
I get the follwing error:
RuntimeError: Item not found: tif #
My savedSettings.py looks like this:
# User Settings Savefile:
viewCheck = False
ornamentCheck = False
renderCheck = False
encodingCheck = "tif"
Would be great if someone explains me what I am doing wrong and how to set variables for the optionMenu.
Thanks for taking the time in advance and have a nice day coding!
Don't do this. instead use mayas internal mechanism, optionVar, for this.
But if you must do this then know that when you do:
import savedSettings
whatever is defined in savedSettings is stored inside savedSettings so if you have the var viewCBvalue then you call it with savedSettings.viewCBvalue. You could load this into main by calling import savedSettings as *, but you really, really do not want to do this!
Python import is not a normal function, results get cached.
Various other problems. Dont use import for this purpose
If you do not want to use optionVar, consider using pickle

Categories