Modeling Planar Belt Transmissions

GitHub source

Background

Belt transmissions involve several moving elements and a variety of materials, enabling flexible power transmission but leading to complex and interdependent system design requirements. The basic performance of a candidate belt transmission can be estimated from kinematic analysis, while a dynamic simulation can give a much better idea of actual system performance and limits.

This Julia package assists users in the kinematic analysis, designing belt transmissions using flat or synchronous belts. Primary structures model pulleys and belt segments, these can be analyzed and plotted through recipes for Plots.jl. BeltTransmission was used to determine the basic design of the Moover variants.

See the package readme for release, license, and development information.

Dependencies

And from the standard repository those defined in the Project.toml.

Installation

using Pkg
Pkg.add("https://github.com/mechanomy/BeltTransmission.jl.git")

Use Cases

Designing a planar belt transmission is the primary use case for BeltTransmission, but this design can have several objectives according to what is already known about the system. If the positions, sizes, and belt routing are known, these can be entered to calculate belt length and arrival and departure angles on each pulley. BeltTransmission can also be used to solve systems for other unknowns, say to determine the position of an idler pulley given a known belt length.

Basic belt transmissions

The goal of these examples is to calculate the belt length given pulley sizes and locations.

Two pulleys

using Unitful, Plots
using Geometry2D
using BeltTransmission

#create the pulleys
ctrA = Geometry2D.Point(10u"mm", 10u"mm")
pA = PlainPulley( pitch=Geometry2D.Circle( center=ctrA, radius=10u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="A")
pB = PlainPulley( pitch=Geometry2D.Circle(100u"mm", 100u"mm", 20u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="B")

#create the belt route
route = [pA, pB] #from A to B and back to A

#solve the departure and arrival angles on each PlainPulley
solved = calculateRouteAngles(route)

#create belt Segments between the Pulleys
segments = route2Segments(solved)
beltLength = calculateBeltLength(segments)

plot(segments, title="two pulleys")

By convention, Pulleys having a positive rotation (+uk) have a dot at their center to indicate the vector's tip, while negative rotation is shown with an X for the arrow's fletching. Once solved, the system can be interrogated:

calculateBeltLength(segments)
0.34959229994006674 m

A variety of pulleys

using Unitful, Plots
using Geometry2D
using BeltTransmission

#create the pulleys
ctrA = Geometry2D.Point(10u"mm", 10u"mm")
pA = PlainPulley( pitch=Geometry2D.Circle( center=ctrA, radius=10u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="A")
pB = PlainPulley( pitch=Geometry2D.Circle(100u"mm",  20u"mm", 20u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="B")
pC = PlainPulley( pitch=Geometry2D.Circle( 80u"mm",  40u"mm",  5u"mm"), axis=-Geometry2D.UnitVector(0,0,1), name="C")
pD = PlainPulley( pitch=Geometry2D.Circle(150u"mm",  40u"mm",  5u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="D")
pE = PlainPulley( pitch=Geometry2D.Circle(100u"mm",  80u"mm",  5u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="E")

#create the belt route
route = [pA, pB, pC, pD, pE]

#solve the departure and arrival angles on each PlainPulley
solved = calculateRouteAngles(route)

#create belt Segments between the Pulleys
segments = route2Segments(solved)

plot(segments, title="Various Pulleys" )
julia> calculateBeltLength(segments)0.5507346870088579 m
julia> printSegments(segments)FreeSegment: depart[A] [10.000mm, 0.000mm] --> arrive[B] [100.000mm, 0.000mm] l[90.000mm]@[0.000°]
FreeSegment: depart[B] [94.114mm, 39.114mm] --> arrive[C] [81.471mm, 35.221mm] l[13.229mm]@[-162.886°]
FreeSegment: depart[C] [80.714mm, 44.949mm] --> arrive[D] [149.286mm, 35.051mm] l[69.282mm]@[-8.213°]
FreeSegment: depart[D] [153.123mm, 43.904mm] --> arrive[E] [103.123mm, 83.904mm] l[64.031mm]@[141.340°]
FreeSegment: depart[E] [97.106mm, 84.078mm] --> arrive[A] [4.213mm, 18.155mm] l[113.908mm]@[-144.638°]

Positive rotation of PlainPulley A will cause PlainPulley C to rotate negatively, hence the negative rotation axis on C. In addition to the PlainPulley rotation axis, the point of departure on each PlainPulley is given a slight arrow in the direction of positive belt rotation.

Multiple systems

using Unitful, Plots
using Geometry2D
using BeltTransmission

#create the pulleys
pA = PlainPulley( pitch=Geometry2D.Circle( 10u"mm",  20u"mm", 20u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="B")
pB = PlainPulley( pitch=Geometry2D.Circle(100u"mm",  20u"mm", 30u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="B")

pX = PlainPulley( pitch=Geometry2D.Circle( 10u"mm",  20u"mm", 15u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="X")
pY = PlainPulley( pitch=Geometry2D.Circle( 50u"mm",  80u"mm",  5u"mm"), axis=Geometry2D.UnitVector(0,0,1), name="Y")

#create the belt systems
segAB = route2Segments( calculateRouteAngles( [pA, pB] ))
segXY = route2Segments( calculateRouteAngles( [pX, pY] ))

plot( segAB, title="Parallel Systems", xlabel="[mm]", ylabel="[mm]", xlims=([-50,150]), ylims=([-50,100]), legend=false, dpi=100, size=(1000,500))
plot!(segXY, segmentColor=:cyan)

PlainPulley body colors are assigned by the default colormap, but segmentColor may be used to control the belt segment color. Other Plots.jl attributes may be used as expected.

Development Plan

BeltTransmission.jl is under active development, enhancement requests are welcome.

BeltTransmission.jl API

BeltTransmission.BeltTransmissionModule

Geometric modeling of 2D closed belt transmissions.

This module models closed belt transmissions with either:

  • Plain pulleys with flat belting
  • Timing pulleys and timing belts

With the general concept of a 'belt' entailing a continuous element, flat and timing belts add properties that affect which method may be called. For instance, a flat belt may have an arbitrary length, limited only by fabrication, while toothed belts are defined to have an integer number of teeth. Likewise, calculations involving tooth pitch are nonsensical if applied to flat or V belts. The module uses Julia's type system to differentiate between these belt types.

Timing and plain pulleys are specializaitons of AbstractPulley, permitting functions that need only the pulley location, rotation axis, or pitch diameter to accept any argument that maps to AbstractPulley, while allowing those needing tooth properties to specify arguments of TimingPulley type.

Calculations are perfomed on the pulley or belt pitch line.

Exports methods:

source
BeltTransmission.BeltSystemType

A BeltSystem is an ordered set of pulleys connected by segments of some belt.

  • pulleys::Vector{AbstractPulley}

  • segments::Vector{BeltTransmission.AbstractSegment}

  • belt::BeltTransmission.AbstractBelt

source
BeltTransmission.BeltSystemMethod
BeltSystem(
    pulleys::Vector{AbstractPulley},
    belt::BeltTransmission.AbstractBelt
) -> BeltSystem

Construct a new BeltSystem, creating segments from pulleys and belt.

source
BeltTransmission.PlainPulleyType

Models a cylindrical plain pulley in a BeltTransmission with:

  • pitch

: the pitch Circle

  • axis

: the rotation axis for the pulley with +/- defining the 'positive' rotation direction

  • arrive

: angle of the radial vector of the belt's point of arrival

  • depart

: angle of the radial vector of the belt's point of departure

  • name

: convenience name of the pulley

source
BeltTransmission.PlainPulleyMethod
PlainPulley(pitch::Geometry2D.Circle, axis::Geometry2D.UnitVector, name::String)

Models a PlainPulley in a BeltTransmission, described by a circle, rotation axis, and name.

source
BeltTransmission.SynchronousBeltType

Represents a synchronous belt with parameters: profile::String - tooth profile name pitch::Unitful.Length - distance between belt grooves length::Unitful.Length - belt linear length if cut nTeeth::Int - number of teeth over the length width::Unitful.Length - belt width partNumber::String - reference name supplier::String - reference name url::String - sourcing link id::UUID - unique id

source
BeltTransmission.SynchronousBeltMethod

SynchronousBelt( belt::SynchronousBelt; partNumber="", supplier="", url="" ) :: SynchronousBelt A copy constructor for adding/changing partNumber, supplier, or url.

source
BeltTransmission.SynchronousPulleyType

Models a SynchronousPulley in a BeltTransmission, described by a pitch circle, rotation axis, and beltPitch.

  • pitch

: Circle describing the pulley pitch diameter.

  • axis

: The rotation axis for the pulley with +/- defining the 'positive' rotation direction.

  • beltPitch

: Distance between belt teeth

  • arrive

: Angle of the radial vector of the belt's point of arrival.

  • depart

: Angle of the radial vector of the belt's point of departure.

  • name

: Convenience name of the pulley.

source
BeltTransmission.SynchronousPulleyMethod
SynchronousPulley(center::Geometry2D.Point, axis::Geometry2D.UnitVector, nGrooves::Integer, beltPitch::Unitful.Length, name::String)

Models a SynchronousPulley in a BeltTransmission located at center rotating about axis with nGrooves(=nTeeth) spaced with arc length beltPitch and covenience name.

source
Base.lengthMethod
Base.length(seg::FreeSegment) :: Unitful.Length

Returns the straight-line distance or length of FreeSegment seg via distance.

source
BeltTransmission.calculateBeltLengthMethod
calculateBeltLength(route::Vector{AbstractPulley}) :: Unitful.Length

Calculates the belt length over the given route as the sum of circular sections at the pulley pitch radii between the arrival and departure angles.

source
BeltTransmission.calculateCenterDistanceMethod
calculateCenterDistance(bs::BeltSystem, which::Integer)

Given a belt system, find the pulley position(s) that satisfy the given belt length. It does this through a linear optmization whose objective is to minimze the error between the given belt's length and the calculateBeltLength(). Since pulleys can each move in <x,y>, the

which is an index or array to the pulley(s) that may be moved; by default all pulleys may be moved and the algorithm minimizes the total pulley movement. The pulleys in the belt system need to be placed in approximate locations in order to determine the belt routing. That is even if their positions are not final some position must be given when creating the pulleys to permit the belt length to be accurately calculated. Pulleys are constrained from overlap

In a two-belt system this problem devolves to calculating the center distance between two pulleys: '''@example

'''

In larger systems,

source
BeltTransmission.calculateRatioMethod
calculateRatio(
    driving::AbstractPulley,
    driven::AbstractPulley
) -> Real

Calculate the transmission ratio between pulleys driving and driven, with the ratio defined as driven/driving, being >1 when the driven pulley rotates more than the driving and <1 less. This can be developed from the belt translation or velocity, as:

xBelt = thA*rA = thB * rB; thB = thA * rA/rB
vBelt = wA*rA = wB*rB; wB = wA * rA/rB

Pulleys having a positive transmission ratio rotate in the same direction, negative opposing.

source
BeltTransmission.calculateRatiosMethod
calculateRatios(bs::BeltSystem) -> Matrix{Float64}

Calculate the transmission ratio matrix between all pulleys, returning a matrix of ratios. Pulleys are numbered according to their order in bs, with the ratio as in calculateRatio.

source
BeltTransmission.calculateRatiosMethod
calculateRatios(
    pulleys::Array{T<:AbstractPulley, 1}
) -> Matrix{Float64}

Calculate the transmission ratio matrix between all pulleys, returning a matrix of ratios. Pulleys are numbered according to their order in pulleys, with the ratio as in calculateRatio.

source
BeltTransmission.calculateRouteAnglesMethod
calculateRouteAngles(route::Vector{AbstractPulley}, plotSegments::Bool=false) :: Vector{AbstractPulley}

Given an ordered vector of Pulleys, output a vector of new Pulleys whose arrive and depart angles are set to connect the pulleys with mutually tangent segments. Convention: pulleys are listed in 'positive' belt rotation order, consistent with the direction of each pulley's rotation axis.

source
BeltTransmission.calculateWrappedAngleMethod
calculateWrappedAngle(p::AbstractPulley) :: Geometry2D.Angle

Given p, calculate the wrapped angle from p.arrive to p.depart. Note that the wrapped angle is not restricted to <= 1 revolution, as the pulley may be wrapped multiple times.

source
BeltTransmission.calculateWrappedLengthMethod
calculateWrappedLength(p::AbstractPulley) :: Unitful.Length

Given p, calculate the arclength of the wrapped segment from p.arrive to p.depart Note that the wrapped length is not restricted to <= 1 revolution, as the pulley may be wrapped multiple times.

source
BeltTransmission.findTangentsMethod
findTangents(seg::FreeSegment) :: Vector{FreeSegment}

Find four lines tangent to both pulleys a and b, returns 4 Segments with departure and arrival angles locating the points of tangency on the circles.

source
BeltTransmission.isSegmentMutuallyTangentMethod
isSegmentMutuallyTangent( seg::FreeSegment ) :: Bool

Determines whether the departure and arrival points are tangent to the connecting belt segment.

For a segment a->b between ai&bi; the correct arrival and departure angles will have cross products that match both axes, (ra-a1)x(a1-b1) = ax1 && (rb-b1)x(a1-b1) = bx1, all others should be false.

source
BeltTransmission.pulley2StringMethod
pulley2String(p::PlainPulley) :: String

Returns a descriptive string of the given PlainPulley p of the form: PlainPulley[struct] @ [1.000mm,2.000mm] r[3.000mm] arrive[57.296°] depart[114.592°] aWrap[57.296°] lWrap[3.000mm]"

source
BeltTransmission.pulley2StringMethod
pulley2String(p::SynchronousPulley) :: String

Returns a descriptive string of the given SynchronousPulley p of the form: SynchronousPulley[struct] @ [1.000mm,2.000mm] r[3.000mm] arrive[57.296°] depart[114.592°] aWrap[57.296°] lWrap[3.000mm]"

source
BeltTransmission.radius2NGroovesMethod
radius2NGrooves(p::SynchronousPulley)::Integer
radius2NGrooves(pitch::Unitful.Length, radius::Unitful.Length)::Integer

Convert the pitch and radius to the number of grooves.

source
BeltTransmission.route2SegmentsMethod
route2Segments(route::Vector{AbstractPulley}) :: Vector{FreeSegment}

Given the ordered Pulleys of a belt routing, returns a vector of the free-space Segments connecting the Pulleys.

source
BeltTransmission.toStringPointsMethod
toStringPoints(seg::FreeSegment) :: String

Creates strings like: FreeSegment: depart[E] [-0.013m, 0.012m] –> arrive[A] [0.110m, 0.083m] l[0.142m]@[29.973°]

source
BeltTransmission.toStringShortMethod
toStringShort(seg::FreeSegment) :: String

Returns a short string of the form 'A – B', for a departing pulley named A arriving at a pulley named B.

source
Geometry2D.distanceMethod
distance(seg::FreeSegment) :: Unitful.Length

Returns the straight-line distance or length of FreeSegment seg.

source
KeywordDispatch.kwcallMethod
FreeSegment(; depart::AbstractPulley, arrive::AbstractPulley) :: FreeSegment

Create a belt FreeSegment between depart and arrive Pulleys

source
KeywordDispatch.kwcallMethod
PlainPulley(; pitch::Geometry2D.Circle, axis::Geometry2D.UnitVector, name::String) 
PlainPulley(; pitch::Geometry2D.Circle, axis::Geometry2D.UnitVector, arrive::Geometry2D.Radian, depart::Geometry2D.Radian, name::String)

Models a PlainPulley in a BeltTransmission through keyword arguments.

source
KeywordDispatch.kwcallMethod
SynchronousBelt(; pitch::Unitful.Length, length::Unitful.Length, nTeeth::Int,  width::Unitful.Length, profile::String, partNumber::String, supplier::String, url::String, id::UUID )
SynchronousBelt(; pitch::Unitful.Length, length::Unitful.Length,               width::Unitful.Length, profile::String)
SynchronousBelt(; pitch::Unitful.Length,                         nTeeth::Int,  width::Unitful.Length, profile::String)

Creates a SynchronousBelt with tooth pitch, overall length, nTeeth, belt width and profile name.

source
KeywordDispatch.kwcallMethod
SynchronousPulley(; center::Geometry2D.Point, axis::Geometry2D.UnitVector, nGrooves::Integer, beltPitch::Unitful.Length, arrive::Geometry2D.Radian, depart::Geometry2D.Radian, name::String)
SynchronousPulley(; center::Geometry2D.Point, axis::Geometry2D.UnitVector, nGrooves::Integer, beltPitch::Unitful.Length, name::String)

Models a SynchronousPulley in a BeltTransmission, described by a circle, rotation axis, and name. nGrooves and beltPitch are used to find the pulley pitch diameter. The belt's arrive and depart angles are the polar angles about the pulley axis of the belt's arrival and departure contact points, usually found by calculateRouteAngles()

source
RecipesBase.apply_recipeMethod
plotRecipe(seg::FreeSegment; n=2, lengthUnit=u"mm", segmentColor=:magenta, arrowFactor=0.03)

Plot recipe to plot the free sections of a segment, does not plot the pulleys. using Plots, Unitful, BeltTransmission, Geometry2D a = PlainPulley( Geometry2D.Circle(1u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) b = PlainPulley( Geometry2D.Circle(10u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) seg = FreeSegment(depart=a, arrive=b) plot(seg)

source
RecipesBase.apply_recipeMethod
plotRecipe(p::PlainPulley; n=100, lengthUnit=u"mm", segmentColor=:magenta, arrowFactor=0.03)

A plot recipe for plotting Pulleys under Plots.jl. Keyword n can be used to increase the number of points constituting the pulley edge. lengthUnit is a Unitful unit for scaling the linear axes. arrowFactor controls the size of the arrow head at depart. using Plots, Unitful, BeltTransmission, Geometry2D p = PlainPulley( Geometry2D.Circle(1u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) plot(p)

source
RecipesBase.apply_recipeMethod
plotRecipe(p::SynchronousPulley; n=100, lengthUnit=u"mm", segmentColor=:magenta, arrowFactor=0.03)

A plot recipe for plotting Pulleys under Plots.jl. Keyword n can be used to increase the number of points constituting the pulley edge. lengthUnit is a Unitful unit for scaling the linear axes. arrowFactor controls the size of the arrow head at depart. using Plots, Unitful, BeltTransmission, Geometry2D p = SynchronousPulley( Geometry2D.Circle(1u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) plot(p)

source
RecipesBase.apply_recipeMethod
plotRecipe(route::Vector{PlainPulley})

Plots the Pulleys in a route vector of Pulleys. using Plots, Unitful, BeltTransmission, Geometry2D a = PlainPulley( Geometry2D.Circle(1u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) b = PlainPulley( Geometry2D.Circle(10u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) route = calculateRouteAngles([a,b]) plot(route)

source
RecipesBase.apply_recipeMethod
plotRecipe(segments::Vector{T}) where T<:AbstractSegment

Plots the Pulleys and Segments in a route vector. using Plots, Unitful, BeltTransmission, Geometry2D a = PlainPulley( Geometry2D.Circle(1u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) b = PlainPulley( Geometry2D.Circle(10u"mm",2u"mm",3u"mm"), Geometry2D.uk, "recipe" ) route = calculateRouteAngles([a,b]) segments = route2Segments(route) plot(segments)

source

BeltTransmission.SynchronousBeltTable

BeltTransmission.SynchronousBeltTableModule

Reads, writes, and generates CSVs that represent catalogs of synchronous belts, having headers: toothProfile - trade name of the tooth profile, eg gt2, gt3, mxl, ... pitchMM - tooth spacing nTeeth - number of teeth about the closed belt lengthMM - circumferential belt length widthMM - belt width id - a UUID4 unique identifier partNumber - manufacturer or supplier part number supplier - supplier name url - link to the data source

Basic usage:

Generate a DataFrame of belts: @julia using BeltTransmission belts = SynchronousBeltTable.generateBeltDataFrame(pitch=2u"mm", width=6u"mm", toothRange=10:5:30) Write these to a CSV: @repl SynchronousBeltTable.writeBeltCSV(belts, "gt2Belts.csv")

This creates a CSV file at the given path, with format profile,pitchMM,nTeeth,lengthMM,widthMM,id,partNumber,supplier,url gt2,2,10,20,6,3a9ee2fa-95a2-4217-b5c6-4bde0d9c65c9,pn0,none,none gt2,2,15,30,6,319f2899-b714-43a4-b37c-830179524311,pn0,none,none gt2,2,20,40,6,7e15cab0-58f2-4c4e-be0b-f168d1091ce9,pn0,none,none gt2,2,25,50,6,6f5fcd44-26f0-44c7-bf38-5aea52c51dd1,pn0,none,none gt2,2,30,60,6,ce84bc3b-4025-4de1-b79c-f536f9e95794,pn0,none,none

(note the UUID ids will differ).

This file can then be read in @repl beltsdf = SynchronousBeltTable.readBeltCSVIntoDataFrame("gt2Belts.csv")

The table of belts can be filtered by @repl filtered = SynchronousBeltTable.lookupLength(beltsdf, 35u"mm", n=2) to get the top two belts nearest the desired length.

These can be converted into SynchronousBelts by @repl sync = SynchronousBeltTable.dfRow2SyncBelt( filtered[1,:] )

source
BeltTransmission.SynchronousBeltTable.generateBeltDataFrameMethod
generateBeltDataFrame(; pitch::Unitful.Length, width::Unitful.Length, toothRange)

Generates a belt DataFrame with a given pitch and width over toothRange. toothRange can be specified as toothRange=20:5:200 to create a tooth range array starting with 20 teeth, then proceeding to 200 teeth in 5-tooth increments.

source
BeltTransmission.SynchronousBeltTable.lookupLengthMethod

Given a desired belt length, return a vector of the closest options from the belts dataframe for the given pitch and width. If n = 1 the single nearest result is returned, else a DataFrame sorted by abs(length error).

source

BeltTransmission.Optimizer

Pulley locations and radii can be optimized via the Optimizer.

Optimizer example

This example moves and resizes pulleys to achieve a given belt length. We start with the initial system which has a belt length of 1050mm.

using Unitful, Plots
using Geometry2D
using BeltTransmission

uk = Geometry2D.UnitVector(0,0,1)
#a square of pulleys, arranged ccw from quadrant1
pA = SynchronousPulley( center=Geometry2D.Point( 100u"mm", 100u"mm"), axis=uk, nGrooves=62, beltPitch=2u"mm", name="1A" )
pB = SynchronousPulley( center=Geometry2D.Point(-100u"mm", 100u"mm"), axis=uk, nGrooves=30, beltPitch=2u"mm", name="2B" )
pC = SynchronousPulley( center=Geometry2D.Point(-100u"mm",-100u"mm"), axis=uk, nGrooves=80, beltPitch=2u"mm", name="3C" )
pD = SynchronousPulley( center=Geometry2D.Point( 100u"mm",-100u"mm"), axis=uk, nGrooves=30, beltPitch=2u"mm", name="4D" )
pE = PlainPulley( pitch=Geometry2D.Circle(   0u"mm",   0u"mm", 14u"mm"), axis=-uk, name="5E") # -uk axis engages the backside of the belt

solved0 = BeltTransmission.calculateRouteAngles( [pA, pB, pC, pD, pE] )
l0 = BeltTransmission.calculateBeltLength(solved0)
1.0501215661822083 m

Next, we add an available belt for this system.

# Initially the belt length is 1050mm. Reduce that to force the pulleys to move.
pitch = 8u"mm"
l = 1000u"mm"
n = Int(round(ustrip(l/pitch)))
belt = BeltTransmission.SynchronousBelt(pitch=pitch, nTeeth=n, width=6u"mm", profile="gt2")
println("Closest belt is $belt")
Closest belt is SynchronousBelt("gt2", 8 mm, 1000 mm, 125, 6 mm, "pn00", "spA", "url0", UUID("93384618-8130-4d09-9ccd-2e1178d859a6"))

While this is a bit trivial, this is where a BeltTable belt can be used. Now we indicate which system variables are allowed to change, and their acceptable ranges.

pRoute = [pA, pB, pC, pD, pE]
cfg = BeltTransmission.Optimizer.Config(belt, pRoute, 4)
BeltTransmission.Optimizer.addVariable!(cfg, pA, BeltTransmission.Optimizer.xPosition, low=60, start=100.1, up=113  )
BeltTransmission.Optimizer.addVariable!(cfg, pA, BeltTransmission.Optimizer.yPosition, low=90, start=100.2, up=111  )
BeltTransmission.Optimizer.addVariable!(cfg, pB, BeltTransmission.Optimizer.yPosition, low=90, start=100.3, up=112  )
BeltTransmission.Optimizer.addVariable!(cfg, pC, BeltTransmission.Optimizer.radius, low=20, start=25, up=95  )

solved = BeltTransmission.Optimizer.solveSystem(cfg)
p = plot(solved0, segmentColor=:magenta)
p = plot!(solved, segmentColor=:yellow)

Here, the initial, unavailable belt length is plotted in magenta, with the optimization to the available belt in yellow. Solving the system minimizes the difference between the given belt's length and that of the most recent system iteration. Note that each variable was utilized, as the optimization generally spreads the task between the available freedoms. The ranges set in each addVariable! provide an ability to fine-tune the solution as desired.

Infeasible systems will return warnings like:

  • Optimizer could not achieve the desired belt length given other constraints, desired[] vs solved[]. Try reducing the number of constraints or expanding their range.

  • Optimizer stopped prior to completion, consider changing the starting point or constraints.

The latter indicates that somewhere along the optimization the calculation of the system's belt length ran into an error. This error was probably reported elsewhere in the output, but likely results from the overlapping of two pulleys, or the movement of one pulley such that the belt cannot touch it.

API

BeltTransmission.Optimizer.ConfigType

The Config struct holds optimization configuration options and system information.

  • belt::BeltTransmission.AbstractBelt

: Belt information

  • routing::Vector{AbstractPulley}

: Routing of the belt through the pulleys.

  • pulley::Vector{AbstractPulley}

: Vector of pulleys to be optimized, set via addVariable.

  • variable::Vector{BeltTransmission.Optimizer.OptimizationVariable}

: Vector of variables on each pulley be optimized, set via addVariable.

  • start::Vector{Real}

: Vector of start values of each variable, set via addVariable.

  • lower::Vector{Real}

: Vector of lower bounds of each variable, set via addVariable.

  • upper::Vector{Real}

: Vector of upper bounds of each variable, set via addVariable.

  • nlOptions::NLopt.Opt

: Options for the NLOpt optimization algorithm, see NLOpt's documentation.

source
BeltTransmission.Optimizer.ConfigMethod
Config(
    belt::BeltTransmission.AbstractBelt,
    routing::Vector{AbstractPulley},
    nConstraints::Int64
) -> BeltTransmission.Optimizer.Config

Constructor of Config objects, sets default optimization options in the .nlOptions field. nConstraints is the number of constraints that will be added through addVariable.

source
BeltTransmission.Optimizer.addVariable!Method
addVariable!(
    opts::BeltTransmission.Optimizer.Config,
    pulley::AbstractPulley,
    variable::BeltTransmission.Optimizer.OptimizationVariable;
    low,
    start,
    up
)

Adds variable on pulley to the list of entities to optimize over. solveSystem will evaluate values of the variable, starting at start, between low and up.

source
BeltTransmission.Optimizer.x2routeMethod
x2route(
    opts::BeltTransmission.Optimizer.Config,
    ox::Array{T<:Real, 1}
) -> Vector{AbstractPulley}

Converts optmization vector ox into a solved belt system via the system description in opts.

source