Repository navigation
Let a tool build its segments and tethers on KiteGeometry's own definitions, and turn azimuth anti-clockwise - #86
Conversation
Read and write a registered model's columns with getproperty, typed by an overridable column_type, so a model can keep its columns in a nested SegmentSpring. unit_stiffness(segment, materials) is public and returns nothing for a non-linear law; the tether form refuses that. resolve_material is public. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1-Bort-1
left a comment
There was a problem hiding this comment.
Independent review (advisory)
Verdict: APPROVE WITH COMMENTS · 2 inline, 0 off the diff
Good
- Every place that read a model column now goes through the new hook:
model_value,added_row_model,write_tableandmodel_cellswitched fromfieldtype/getfieldtocolumn_type/getproperty. A search ofsrcfound no other place that reads a column throughgetfield. column_typedefaults tofieldtype(M, column)andgetpropertyon a plain struct isgetfield, so models already registered read and write exactly as before, as the card says.tether_unit_stiffnesskeeps the same error text, now raised when it getsnothingback. The new test pins that message and checks the result equalsunit_stiffness.- The golden-document testset now calls
unit_stiffnessinstead of repeating theyoungs_modulus * π (d/2)^2formula, which removes a second copy of the equation (§2). register_model!now refuses a forwarded column that has the same name as a component field, as the card says. Without this,Component.getpropertywould silently read the component's field instead of the column.- The card says why the damping fallback was left out (the
Settingsfields don't exist; checked withhasproperty) and links that to the issue's rule that no segment's damping may change. - Each new public name has a docstring, appears in a
@docsblock instructure.md, and has a CHANGELOG line under Unreleased.
Not good
src/KiteGeometry.jl:33—resolve_materialbecomes public API as it is: a positional 4-tuple whose second element is either a modulus in [Pa] or a law-nameString, controlled byNaN-sentinel keywords. Freezing that shape now means any later cleanup (a named tuple, separate linear and nonlinear paths) becomes a breaking change.test/test-authoring.jl:237— This testset only checks thepublicline against itself. Every name in it is already used throughKiteGeometry.in the other new testsets and in@docs, so it protects no behaviour and adds another place to edit whenever the list changes.- The card says the stiffness comes back as Young's modulus [Pa] and must be multiplied by the area. That is true of
resolve_materialbut not ofunit_stiffness, which already returns [N]. The sentence should nameresolve_material, or SymbolicAWEModels may multiply by the area twice. - The card does not say what was searched before adding
column_type(§2: 'Say in the PR what you searched for'). - Verification is incomplete: the full local
Pkg.testresult was not read and CI is pending. Only four test files were run, in one module. - The
rel_dampingtestset covers behaviour that already existed inresolve_material. The card lists it as 'rel_dampingfallback' right next to a section saying that fallback was not done, which invites a misreading. NestedSpringdefines nopropertynames, sopropertynames(segment)on such a component does not list the spring's columns. This is harmless in the test but is the pattern downstream tools will copy.- The
model_columnsdocstring now allows 'naming others', but a model that names columns that are not its fields and adds nocolumn_typemethod fails with afieldtypeerror at load. The docstring could say the two methods go together.
claude, rubric CLEAN_CODE.md. A different lab from the implementer
on purpose: a reviewer sharing its blind spots would not flag its mistakes.
The nested-spring test model also lists the spring's columns in propertynames, the pattern a downstream model copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Local full suite: PASS (8 min, Julia 1.13.0, one cell of the matrix) |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
A model whose getproperty forwards one of its own field names elsewhere (SymbolicAWEModels' winch model and friction_epsilon) wrote the forwarded value into a column its row leaves unset. Only a column that is not a field of the model is now read with getproperty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
From SymbolicAWEModels#446 now replaces SystemStructure outright (owner's re-cut, plan ec43c94: one pull request per concept and repository, keeping #86), so two more things it needs from KiteGeometry belong in #86, on the same branch. Please add both and say here when pushed. SAM consumes the branch by Pkg.add(url, rev).
|
Azimuth and its rate run from east towards north, as atan(y, x) and KiteUtils 0.14's azimuth_east do, so a value set reads back the same. A YAML with a non-zero azimuth now places mirrored; heading keeps its sense. chained_transforms.yaml says its recorded pose in the new sense (15 -> -15 deg, -1.5 -> 1.5 deg/s); sam_placed.yml is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tool can expand a tether into its own rows. A callable stiffness becomes a material of law unit_stiffness holding it, which line_material! had no method for. MaterialTable, which the function takes, is public too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
turn! negated transform.azimuth to get KiteUtils' east-to-north azimuth, which goes wrong as soon as the transform's azimuth changes sense, as #86 does. Reading it off radial_direction holds in either sense, and dividing by cos(elevation) keeps it continuous through the zenith. The test helper now measures heading from where the kite stands rather than repeating the same sign, so a mismatch fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The description was rewritten here since the box last wrote it, so it stays as it is. This is what the box would have put there: A tool that registers a segment model (SymbolicAWEModels, for example) had to copy the three spring columns into its own struct. Now it can hold a A line's axial stiffness from its material is now a public function. It takes either a material and a diameter, or a segment and the material table, so a tool that holds a segment's material itself needs no table to look it up in. It returns the stiffness times rest length in newtons, already multiplied by the cross-section area. It allocates nothing for a modulus stored as a plain float, so a simulation can call it on every step. For a material that is not KiteGeometry.unit_stiffness(segment, materials, tether) # before: internal, tether only
KiteGeometry.unit_stiffness(segment, materials) # after: public, any segment [N]
KiteGeometry.unit_stiffness(material, 0.004) # after: a material at a diameter [N]
KiteGeometry.column_type(::Type{SegmentModel}, c) = fieldtype(SegmentSpring, c) # new hookA model that names columns other than its own fields adds a Not done: the damping fallback the issue asked for. It would read To delete its copy of material resolution, SymbolicAWEModels needs one change at its call sites: that function returns the stiffness as Young's modulus [Pa], so multiply it by the cross-section area to get its Material resolution goes public in the shape it already has, a tuple whose second element is a modulus or a law name. Giving it a named or split return now would change every caller in this package, so it is left as it is. A tool can now expand a tether into segments and inner points in its own rows, the way the loader does, instead of keeping a copy of that code. The stiffness it gives may also be a callable force law, which had no way in before. It becomes a material of law KiteGeometry.expand_tether!(points, segments, point_transforms, :main, :ground, :kite, 3,
(; stretched_length=33.0), set, materials;
model, unit_stiffness=force_law, unit_damping=5.0)The table of materials that function takes is public too, since a public function should not need a private type to call it. Behaviour change: a transform's azimuth now turns anti-clockwise, from east towards north, as The test system with a non-zero azimuth keeps its recorded pose, velocities and body frames. Only its YAML changed, from 15° and −1.5°/s to −15° and +1.5°/s. That pins the change to an exact sign flip rather than to numbers regenerated from the new code. To check before merging: was this convention yours? The request cites option A on OpenSourceAWE/SymbolicAWEModels.jl#430 as your choice. On that thread and on OpenSourceAWE/SymbolicAWEModels.jl#446 I only found the bot taking its own recommendation, with "say so if you want B", and no comment from you. I built it because KiteUtils has already moved this way (OpenSourceAWE/KiteUtils.jl#165). If you wanted only the reported azimuth to flip, the commit to drop is 90e32e3. No conflict with #71: it no longer negates the azimuth. It reads the azimuth for KiteUtils' heading function off The duplicate-name check in Verification
Opened by |
A tool that registers a segment model (SymbolicAWEModels, for example) had to copy the three spring columns into its own struct. Now it can hold a
SegmentSpringinside its model and still read and write those columns. A column that is one of the model's own fields is read straight from that field, as before. Only a column the model does not hold as a field is read through property access, which is how it reaches into the nested spring. A column's type comes from a function the model can override, which defaults to the field's type. So existing models and documents read and write exactly as before.A line's axial stiffness from its material is now a public function. It takes either a material and a diameter, or a segment and the material table, so a tool that holds a segment's material itself needs no table to look it up in. It returns the stiffness times rest length in newtons, already multiplied by the cross-section area. It allocates nothing for a modulus stored as a plain float, so a simulation can call it on every step. For a material that is not
linearit returnsnothing, and the caller decides what to do. Placing a tether with an initial force still refuses a non-linear material, with the same message as before. The function that turns a segment row's given values into diameter, stiffness, damping and density is now public too.A model that names columns other than its own fields adds a
column_typemethod for them; its docstring says so. Before adding that hook I searched the source for how column and field types are found (fieldtype,column_type,model_columns): the only uses build components and metadata, none gives a model's column a type, so the hook is new rather than a second copy.Not done: the damping fallback the issue asked for. It would read
set.unit_damping / set.unit_stiffnesswhenrel_dampingis 0. KiteUtils'Settingshas no fields with those names (checked on KiteUtils 0.14:hasproperty(set, :unit_damping) == false). The tether's values are namedaxial_dampingandaxial_stiffnessthere. So in SymbolicAWEModels that branch never runs, and its copy already gives the same damping as KiteGeometry's. Adding the fallback, or a version that readsaxial_damping, would change segment damping for every settings file that leavesrel_dampingat 0. The issue says no segment's damping should move, so I left it out. A test pins the damping KiteGeometry already gives fromrel_damping, so that SymbolicAWEModels can rely on it.To delete its copy of material resolution, SymbolicAWEModels needs one change at its call sites: that function returns the stiffness as Young's modulus [Pa], so multiply it by the cross-section area to get its
unit_stiffness[N]. The publicunit_stiffnessabove already does this multiplication; do not apply it twice.Material resolution goes public in the shape it already has, a tuple whose second element is a modulus or a law name. Giving it a named or split return now would change every caller in this package, so it is left as it is.
A tool can now expand a tether into segments and inner points in its own rows, the way the loader does, instead of keeping a copy of that code. The stiffness it gives may also be a callable force law, which had no way in before. It becomes a material of law
unit_stiffnessthat holds the callable.The table of materials that function takes is public too, since a public function should not need a private type to call it.
Behaviour change: a transform's azimuth now turns anti-clockwise, from east towards north, as
atan(y, x)does. Before, it ran from east towards south, the opposite of KiteUtils 0.14'sazimuth_east, so a tool moving to that KiteUtils would set 30° and read back −30°. Now you set 30° and read back 30°, with the object north of east. A YAML with a non-zero azimuth places mirrored about the east axis, and itsazimuth_velchanges sense with it. Heading is unchanged. KiteGeometry calls nothing in KiteUtils that depends on this, so it still works with KiteUtils 0.13 as well as 0.14.The test system with a non-zero azimuth keeps its recorded pose, velocities and body frames. Only its YAML changed, from 15° and −1.5°/s to −15° and +1.5°/s. That pins the change to an exact sign flip rather than to numbers regenerated from the new code.
To check before merging: was this convention yours? The request cites option A on OpenSourceAWE/SymbolicAWEModels.jl#430 as your choice. On that thread and on OpenSourceAWE/SymbolicAWEModels.jl#446 I only found the bot taking its own recommendation, with "say so if you want B", and no comment from you. I built it because KiteUtils has already moved this way (OpenSourceAWE/KiteUtils.jl#165). If you wanted only the reported azimuth to flip, the commit to drop is 90e32e3.
No conflict with #71: it no longer negates the azimuth. It reads the azimuth for KiteUtils' heading function off
radial_direction, so it follows this change whichever merges second. I read that in its diff at aa0f821. Its task reportstest-transforms30/30 on a merge of the two; I did not run that merge.The duplicate-name check in
register_model!now looks at a model's columns as well as its fields, so a forwarded column that has the same name as a component field is still refused.Verification
srcwithUndefVarError: column_type not defined in KiteGeometry,MethodError: no method matching unit_stiffness(::Segment{SegmentSpring}, ::Rows{Material})andispublic == falsetest/test-authoring.jlnew testsets: a nested-SegmentSpring model round-trips a document and lists the spring's columns as its properties; a model whose own property access gives a default for an unset field still writes no column for it (red before: the writer added aunit_dampingcolumn of 6.0 to every row);unit_stiffnessmatches the golden document and isnothingfor a non-linear law; a material'sunit_stiffnessat a diameter allocates 0 B after a warm-up (red before: no such method; the segment form allocated 48 B per call); the tether form refuses that law; damping fromrel_dampingstays as it was; the three names are publictest/test-transforms.jlnew testsets, red before: azimuth set to 30° read back as −30°; azimuth 90° elevation 0 placed at[0, -1, 0]; the finite difference ofatan(y, x)was −0.0349 rad/s for a rate of +0.0349. Green after: 30°,[0, 1, 0], and the rate to 1e-6test/test-authoring.jl, red before withMethodError: no method matching line_material!andispublic == false:nsegments reading one callable material, inner points in no transform where no end has onetest/data/chained_transforms.yamlas above;test/data/sam_placed.ymluntouchedtest/test-*.jlfilesruntests.jlincludes, in one clean module on the test environment: 881/881 pass · repository test run started, GitHub CI pending at the time of writingreuseis not installed here; no file added)unit_stiffnessof a segment 48 B → 0 B per call,@allocatedafter a warm-up; no timing claimedOpened by
1-Bort-1, an AI agent working for @1-Bart-1.Closes #85 · task
KiteGeometry.jl-85