Hope someone can help me.
I'm using VB to extract peak member forces from Robot for a given set of load cases. Unfortunately in the case where a given bar position has 2 member forces, Robot will pass the lower of the 2 values to Excel. The result is that my code and spreadsheet and therefore my structural design is not capturing the peak moment.
I don't think this is a problem with my code, its working at every other position of the structure. I have a work around in mind, but forcing a peak moment extraction would be first prize.
Private Sub GetBarForces() Dim rbForceServer As RobotBarForceServer Dim rbCase_Col As RobotCaseCollection Dim lBarNum As Long Dim lCaseNum As Long Dim rbForceData As RobotBarForceData Dim ResultFx As Double, ResultFz As Double, ResultMy As Double Dim rbCase As IRobotCase Dim rbCase_Sel As RobotSelection Dim i, j As Integer Dim iNumPositions As Integer Dim iMinFx, iMaxFx As Single Dim iMinFz, iMaxFz As Single Dim iMinMy, iMaxMy As Single Dim iBarPosition, iBarLength As Single Dim rRange As Range 'set collection of load cases Set rbCase_Sel = Robot.Project.Structure.Selections.Create(I_OT_CASE) rbCase_Sel.AddText (sCaseNums) Set rbCase_Col = Robot.Project.Structure.Cases.GetMany(rbCase_Sel) 'set Robot forceserver Set rbForceServer = Robot.Project.Structure.Results.Bars.Forces With Worksheets("Case 2&3- " & vWallResults(1, iWallNum)) .Unprotect iBarLength = vWallResults(3, iWallNum) - vWallResults(4, iWallNum) Set rRange = .Range("A:A") iNumPositions = Application.WorksheetFunction.Count(rRange) For i = 1 To iNumPositions 'update status window With frmStatusWindow .txtStatusWindow = .txtStatusWindow.Text _ & ". " End With 'set position on bar for force extraction iBarPosition = (vWallResults(3, iWallNum) - .Cells(6 + i, 1)) / iBarLength For j = 1 To rbCase_Col.Count 'get jth load case Set rbCase = rbCase_Col.Get(j) lCaseNum = rbCase.Number 'set bar number for force extraction lBarNum = vWallResults(2, iWallNum) 'extract forces/moments Set rbForceData = rbForceServer.Value(lBarNum, lCaseNum, iBarPosition) ResultFx = rbForceData.FX ResultFz = rbForceData.FZ ResultMy = rbForceData.MY 'initialise envelope variables If j = 1 Then iMinFx = ResultFx iMaxFx = ResultFx iMinFz = ResultFz iMaxFz = ResultFz iMinMy = ResultMy iMaxMy = ResultMy End If 'compare forces/moments to determine envelope If ResultFx < iMinFx Then iMinFx = ResultFx End If If ResultFx > iMaxFx Then iMaxFx = ResultFx End If If ResultFz < iMinFz Then iMinFz = ResultFz End If If ResultFz > iMaxFz Then iMaxFz = ResultFz End If If ResultMy < iMinMy Then iMinMy = ResultMy End If If ResultMy > iMaxMy Then iMaxMy = ResultMy End If Set rbForceData = Nothing Next j 'record force/moment envelope to spreadsheet With rCase .Cells(6 + i, 1) = iMinFx / 1000 .Cells(6 + i, 2) = iMaxFx / 1000 .Cells(6 + i, 3) = iMinFz / 1000 .Cells(6 + i, 4) = iMaxFz / 1000 .Cells(6 + i, 5) = iMinMy / 1000 .Cells(6 + i, 6) = iMaxMy / 1000 End With Next i
Thanks in Advance for your help.
Solved! Go to Solution.
Solved by RoboExploiter. Go to Solution.
My assumption is that you have this bar divided into number of calculation elements (intermediate nodes along the bar).
There are several possibilities:
1. Change model to avoid bar division (e.g. split bar into two smaller at node 100)
2. Read value from dx from both sides of this point
3. Use extreme server to find min and max value
Dim r As New RobotOM.RobotApplication
Dim ep As RobotOM.RobotExtremeParams
Dim selCas As RobotOM.RobotSelection
Dim selBar As RobotOM.RobotSelection
selBar = r.Project.Structure.Selections.Create(RobotOM.IRobotObjectType.I_OT_BAR)
selCas = r.Project.Structure.Selections.Create(RobotOM.IRobotObjectType.I_OT_CASE)
selBar.FromText("1")
selCas.FromText("1")
ep = r.CmpntFactory.Create(RobotOM.IRobotComponentType.I_CT_EXTREME_PARAMS)
ep.ValueType = RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_MY
ep.Selection.Set(RobotOM.IRobotObjectType.I_OT_CASE, selCas)
ep.Selection.Set(RobotOM.IRobotObjectType.I_OT_BAR, selBar)
ep.BarDivision = 11
Dim ev As RobotOM.RobotExtremeValue
ev = r.Project.Structure.Results.Extremes.MaxValue(ep)
MsgBox(ev.Value)
ev = r.Project.Structure.Results.Extremes.MinValue(ep)
MsgBox(ev.Value)
Most likely the 4th solution below will be the best:
4. Use the query mechanism able to working on elements (since RSA 2012). Example:
Dim RobApp As New RobotOM.RobotApplication
Dim Res As RobotOM.IRobotResultQueryReturnType
Dim RobResQueryParams As RobotOM.RobotResultQueryParams
Dim RobResRowSet As New RobotOM.RobotResultRowSet
Dim SelBar As RobotOM.RobotSelection
Dim SelCas As RobotOM.RobotSelection
SelBar = RobApp.Project.Structure.Selections.Create(RobotOM.IRobotObjectType.I_OT_BAR)
SelCas = RobApp.Project.Structure.Selections.Create(RobotOM.IRobotObjectType.I_OT_CASE)
SelBar.AddText("1")
SelCas.AddText("1")
RobResQueryParams = RobApp.CmpntFactory.Create(RobotOM.IRobotComponentType.I_CT_RESULT_QUERY_PARAMS)
RobResQueryParams.Selection.Set(RobotOM.IRobotObjectType.I_OT_BAR, SelBar)
RobResQueryParams.Selection.Set(RobotOM.IRobotObjectType.I_OT_CASE, SelCas)
RobResQueryParams.SetParam(RobotOM.IRobotResultParamType.I_RPT_BAR_ELEMENT_DIV_COUNT, 11)
RobResQueryParams.ResultIds.SetSize(6)
RobResQueryParams.ResultIds.Set(1, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_FX)
RobResQueryParams.ResultIds.Set(2, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_FY)
RobResQueryParams.ResultIds.Set(3, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_FZ)
RobResQueryParams.ResultIds.Set(4, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_MX)
RobResQueryParams.ResultIds.Set(5, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_MY)
RobResQueryParams.ResultIds.Set(6, RobotOM.IRobotExtremeValueType.I_EVT_FORCE_BAR_MZ)
Res = RobApp.Project.Structure.Results.Query(RobResQueryParams, RobResRowSet)
Dim q As New Object
Dim v As Double
Dim max As Double
Dim min As Double
max = 0
min = 0
Do
Res = RobApp.Project.Structure.Results.Query(RobResQueryParams, RobResRowSet)
Dim ok As Boolean
ok = RobResRowSet.MoveFirst()
While ok
v = RobResRowSet.CurrentRow.GetValue(RobResRowSet.ResultIds.Get(5))
If (min > v) Then min = v
If (max < v) Then max = v
ok = RobResRowSet.MoveNext()
End While
Loop While Res = RobotOM.IRobotResultQueryReturnType.I_RQRT_MORE_AVAILABLE
MsgBox("min = " & min & " max = " & max)
If you find your post answered press the Accept as Solution button please. This will help other users to find solutions much faster. Thank you.
Hi Artur,
1) Not possible. The bar is continuous, but there are nodes along the length where i've placed spring supports.
2) This is my potential workaround, I was hoping for another quicker/neater solution.
3) On what version of RSA is this available? I have RSA Pro 2010.
4) Thanks, however I don't have RSA 2012.
Thanks.
Hi,
API for methods 3 and 4 should be available in ARSA 2010.
Hi Gents,
Thanks for your help so far. I think i'm almost there. I've tried to adapt your piece of code to work properly, but I'm having some difficulty.
When I'm running this query mechanism I am given this error at the
ResultFx= RobResRowSet.CurrentRow.GetValue(RobResRowSet.ResultIds.Get(1)) : "Run Time Error '-2147467259 (80004005)': Method 'GetValue of object 'IRobotResultRow' failed".
I think the error occurs because I haven't defined RobResRowSet properly. Can you help me?
Sub Extreme_Bar_Forces() ''Using the query mechanism Dim Res As RobotOM.IRobotResultQueryReturnType Dim RobResQueryParams As RobotResultQueryParams Dim RobResRowSet As New RobotResultRowSet Dim SelBar As RobotSelection Dim SelCase As RobotSelection Dim v As Double Dim max As Double Dim min As Double Dim ok As Boolean Dim iBarPosition, iNumpositions, iBarLength, i, j As Single Dim rRange As Range Dim ResultFx, ResultFz, ResultMy, iMinFx, iMaxFx, iMinFz, iMaxFz, iMinMy, iMaxMy As Double 'set collection of load cases Set SelCase = Robot.Project.Structure.Selections.Create(I_OT_CASE) SelCase.FromText (sCaseNums) MsgBox sCaseNums Set SelBar = Robot.Project.Structure.Selections.Create(I_OT_BAR) Set RobResQueryParams = Robot.CmpntFactory.Create(I_CT_RESULT_QUERY_PARAMS) RobResQueryParams.Selection.Set I_OT_BAR, SelCase RobResQueryParams.Selection.Set I_OT_BAR, SelBar RobResQueryParams.ResultIds.SetSize 6 RobResQueryParams.ResultIds.Set 1, IRobotExtremeValueType.I_EVT_FORCE_BAR_FX RobResQueryParams.ResultIds.Set 2, IRobotExtremeValueType.I_EVT_FORCE_BAR_FY RobResQueryParams.ResultIds.Set 3, IRobotExtremeValueType.I_EVT_FORCE_BAR_FZ RobResQueryParams.ResultIds.Set 4, IRobotExtremeValueType.I_EVT_FORCE_BAR_MX RobResQueryParams.ResultIds.Set 5, IRobotExtremeValueType.I_EVT_FORCE_BAR_MY RobResQueryParams.ResultIds.Set 6, IRobotExtremeValueType.I_EVT_FORCE_BAR_MZ 'Set RobResRowSet = Robot.CmpntFactory.Create(??_??_??) With Worksheets("Forces " & vWallResults(1, iWallNum)) .Unprotect iBarLength = vWallResults(3, iWallNum) - vWallResults(4, iWallNum) Set rRange = .Range("A:A") iNumpositions = Application.WorksheetFunction.Count(rRange) Res = Robot.Project.Structure.Results.Query(RobResQueryParams, RobResRowSet) ok = RobResRowSet.MoveNext() For i = 1 To iNumpositions 'update status window With frmStatusWindow .txtStatusWindow = .txtStatusWindow.Text _ & ". " End With 'set position on bar for force extraction 'iBarPosition = (vWallResults(3, iWallNum) - .Cells(6 + i, 1)) / iBarLength RobResQueryParams.SetParam I_RPT_BAR_DIV_COUNT, iNumpositions For j = 1 To SelCase.Count 'get jth load case 'Set jCase = SelCase.Get(j) 'lCaseNum = SelCase.Number 'set bar number for force extraction 'lBarNum = vWallResults(2, iWallNum) 'extract forces/moments 'Set rbForceData = rbForceServer.Value(lBarNum, lCaseNum, iBarPosition) ResultFx = RobResRowSet.CurrentRow.GetValue(RobResRowSet.ResultIds.Get(1)) ResultFz = RobResRowSet.CurrentRow.GetValue(RobResRowSet.ResultIds.Get(3)) ResultMy = RobResRowSet.CurrentRow.GetValue(RobResRowSet.ResultIds.Get(5)) 'initialise envelope variables If j = 1 Then iMinFx = ResultFx iMaxFx = ResultFx iMinFz = ResultFz iMaxFz = ResultFz iMinMy = ResultMy iMaxMy = ResultMy End If 'compare forces/moments to determine envelope If ResultFx < iMinFx Then iMinFx = ResultFx End If If ResultFx > iMaxFx Then iMaxFx = ResultFx End If If ResultFz < iMinFz Then iMinFz = ResultFz End If If ResultFz > iMaxFz Then iMaxFz = ResultFz End If If ResultMy < iMinMy Then iMinMy = ResultMy End If If ResultMy > iMaxMy Then iMaxMy = ResultMy End If ok = RobResRowSet.MoveNext() Next j 'record force/moment envelope to spreadsheet With rCase .Cells(6 + i, 1) = iMinFx / 1000 .Cells(6 + i, 2) = iMaxFx / 1000 .Cells(6 + i, 3) = iMinFz / 1000 .Cells(6 + i, 4) = iMaxFz / 1000 .Cells(6 + i, 5) = iMinMy / 1000 .Cells(6 + i, 6) = iMaxMy / 1000 End With Next i '.protect End With 'update status window With frmStatusWindow .txtStatusWindow = .txtStatusWindow.Text & _ "." & vbNewLine End With End Sub
Some bug in your code:
- wrong selection : bars mixed with cases
RobResQueryParams.Selection.Set I_OT_BAR, SelCase
- bar selection not set
SelBar.FromText()
- wrong querry
parameter RobResQueryParams.SetParam I_RPT_BAR_DIV_COUNT, iNumpositions should be set before
querry: Res = Robot.Project.Structure.Results.Query(RobResQueryParams, RobResRowSet)
Correct your code and check.
Thanks Rafal.
RoboExploiter has enlisted me to help out, and with your hints the query is working now. Just need to confirm it's doing the right thing.
Hi Guys, some feedback on your suggestions.
The query mechanism suggested was also unable to capture the peak member force, given 2 member forces at the same position.
I didn't try the extreme server method, as i couldn't risk losing more time to do anymore abortive work.
My final solution (albeit flawed) was to read the member forces 1mm above and 1mm below the position in question.
Thanks.