wireviz / WireViz

Easily document cables and wiring harnesses.
GNU General Public License v3.0
4.22k stars 219 forks source link

Need the ability to go from connector to wire to wire to connector #270

Open Halfwalker opened 2 years ago

Halfwalker commented 2 years ago

Just discovered WireViz, and it looks awesome. I'm in the process of laying out a new wiring harness for my car, and this will be a great visual check for the wiring plan.

Being an automotive harness, there are several runs (+12V, GND, +5V, SignalGND) that are a long wire with crimp-splices off to various branches. That is, the wire bundle heads out from the ecu to a branch point, where several wires go to a connector along with a pair of spliced wires. For example a sensor that takes +12V, GND and signal.

I've come close to modeling this, but not quite. In the image below we have 5 wires from connector X1 going to X3. In the middle are two crimp-ferrules to branch off to X4 image The yaml to generate this is

connectors:
  X1: &template_con
    type: Molex KK 254
    subtype: female
    pinlabels: [GND, VCC, SCL, SDA, TMP]
  X2_1: &template_ferrule
    style: simple
    type: Crimp ferrule
    subtype: 20 AWG
  X2_2:
    <<: *template_ferrule
  X3:
    <<: *template_con
  X4:
    <<: *template_con
    pinlabels: [SCL, SDA]

cables:
  W1: &template_wire
    gauge: 0.25 mm2
    length: 0.2
    colors: [BNBK, RD, GNRD, VT, OGWH]
    category: bundle
    wirecount: 5
  W2:
    <<: *template_wire
  W3:
    <<: *template_wire
    colors: [GNRD, VT]
    wirecount: 2

connections:
  -
    - X1: [3-4]
    - W1: [3-4]
    - [X2_1, X2_2]
    - W2: [3-4]
    - X3: [3-4]
  -
    - X1: [1-2]
    - W1: [1-2]
    - X3: [1-2]
  -
    - X1: 5
    - W1: 5
    - X3: 5
  -
    - [X2_1, X2_2]
    - W3: [1-2]
    - X4: [1-2]

The problem is I can't get the GND, VCC and TMP wires to join the W2 wire bundle. The W1-crimps-W2 bundle represents the main harness, with the crimps branching wires out to another connector.

This can get somewhat complicated, as there are several branching points on a harness, each with anywhere from one to several branches heading off to connectors/sensors/etc. Sometimes a branch can itself have branching points. For example, a branch point that heads down to the transmission where it branches to reach the reverse-indicator switch and the speed sensor.

Essentially I need a way to connect W1 wires 1,2,5 directly to W2 wires 1,2,5 so they're not hanging out in space as in the image above. Even if we were to take the crimp-ferrules out of the picture and branch right out from the W1 wire bundle to connector X4, it would still need to be able to connect W1 to W2. That's because there can (will) be several branch points in the harness between connectors.

Visualize 4 large connectors inside the car at the ECU location, all interconnected. Then about 80 wires in a single bundle going through the firewall to the engine bay. That large wire bundle then loops around, branching off multiple times, until it reaches the furthest connector/sensor.

Here's an example ... Multiple connectors in lower right at ECU location, then two main bundles gong left on the table. You can just see the firewall grommet there by the plastic bags. Then heading up the table into the picture, branch after branch after branch, lots of connectors. Need to be able to model something like that :) image

kvid commented 2 years ago

Thank you for sharing your challenging use case. Currently, WireViz does not support a wire to be part of more than one single bundle. You can try to insert virtual splices (not present in the physical harness) between the wire bundles, like this:

connectors:
  X1: &template_con
    type: Molex KK 254
    subtype: female
    pinlabels: [GND, VCC, SCL, SDA, TMP]
  X2_1: &template_ferrule
    style: simple
    type: Crimp ferrule
    subtype: 20 AWG
  X2_2:
    <<: *template_ferrule
  X3:
    <<: *template_con
  X4:
    <<: *template_con
    pinlabels: [SCL, SDA]
  # Virtual splice to enable wires going through more than one bundle:
  X:
    style: simple
    autogenerate: true
    type: " "
    ignore_in_bom: true

cables:
  W1: &template_wire
    gauge: 0.25 mm2
    length: 0.2 m
    colors: [BNBK, RD, GNRD, VT, OGWH]
    category: bundle
  W2:
    <<: *template_wire
  W3:
    <<: *template_wire
    colors: [GNRD, VT]

connections:
  -
    - X1: [1-5]
    - W1: [1-5]
    - [X, X, X2_1, X2_2, X]
    - W2: [1-5]
    - X3: [1-5]
  -
    - [X2_1, X2_2]
    - W3: [1-2]
    - X4: [1-2]

That will get you closer to what you want, I guess: issue270 Problems with this solution:

It should be possible to add a feature to hide such a virtual splice completely when needed, but the other problems above will still exist. The latter problem could be solved by referencing the next bundle (at the other side of the hidden splice) if that makes sense, but the problem with different designators is harder to solve without a major restructuring of how WireViz represents the wires internally.

Halfwalker commented 2 years ago

Thanks for the fast reply, and with a solution ! That image looks totally fine. It will be nice to hide the virtual splices, but that's pretty damn good as it sits.

Does it matter that the wires are split into two parts internally ? The BOM lists the correct length needed for each one. I think it's probably OK tha tthe W1/W2 destination info isn't there. Leads to treating them as a continuation of the wire.

kvid commented 2 years ago

Thanks for the fast reply, and with a solution ! That image looks totally fine.

I'm glad you can use my suggestion.

It will be nice to hide the virtual splices, but that's pretty damn good as it sits.

I guess one major advantage with reducing the small box to an invisible point, is to avoid bending adjacent wires around the small box.

It might be possible to just hide all empty connectors, or maybe a show: false attribute is better?

Does it matter that the wires are split into two parts internally ? The BOM lists the correct length needed for each one.

As long as the wires at both sides of the virtual splice are equal, then the BOM should join the entries correctly, but the user gets no warning if there is a small difference between the two wires, or if it's a cable at one side and a bundle at the other side.

Maybe a general feature to warn about differences between wires that are connected together could be useful? It must of course be possible to turn this off where differences are intended.

I think it's probably OK tha tthe W1/W2 destination info isn't there. Leads to treating them as a continuation of the wire.

In a more complicated harness with a lot of crossing wires and many wires with the same color, the wire destination documentation is very important to easily see where all the wires go.

Halfwalker commented 2 years ago

It will be nice to hide the virtual splices, but that's pretty damn good as it sits.

I guess one major advantage with reducing the small box to an invisible point, is to avoid bending adjacent wires around the small box.

That would definitely be nice ... I think the highest-use case would be to have them invisible (show: false) so perhaps have that as the default, but with the ability to show them if required.

Does it matter that the wires are split into two parts internally ? The BOM lists the correct length needed for each one.

As long as the wires at both sides of the virtual splice are equal, then the BOM should join the entries correctly, but the user gets no warning if there is a small difference between the two wires, or if it's a cable at one side and a bundle at the other side.

Seems to be OK. I added a length: 1.3 to the W2 wire, and it renders fine. The BOM lists the wire length correctly as a single entry. image

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

Id | Description | Qty | Unit | Designators -- | -- | -- | -- | -- 1 | Connector, Crimp ferrule, 20 AWG | 2 |   | X2_1, X2_2 2 | Connector, Molex KK 254, female, 2 pins | 1 |   | X4 3 | Connector, Molex KK 254, female, 5 pins | 2 |   | X1, X3 4 | Wire, 0.25 mm², BNBK | 1.5 | m | W1, W2 5 | Wire, 0.25 mm², GNRD | 1.7 | m | W1, W2, W3 6 | Wire, 0.25 mm², OGWH | 1.5 | m | W1, W2 7 | Wire, 0.25 mm², RD | 1.5 | m | W1, W2 8 | Wire, 0.25 mm², VT | 1.7 | m | W1, W2, W3

How about possibly a grouping-object that could be assigned to other objects. Kind of like a wire-bundle. That would draw a grouping box around the objects to indicate that they belong together and should be rendered close together. In this case the grouping-object would be attached to the two Crimp ferrules and the three virtual splices.

kvid commented 2 years ago

Does it matter that the wires are split into two parts internally ? The BOM lists the correct length needed for each one.

As long as the wires at both sides of the virtual splice are equal, then the BOM should join the entries correctly, but the user gets no warning if there is a small difference between the two wires, or if it's a cable at one side and a bundle at the other side.

Seems to be OK. I added a length: 1.3 to the W2 wire, and it renders fine. The BOM lists the wire length correctly as a single entry.

I'm sorry for being unclear. These columns of BOM entries must be equal to be joined: ('description', 'unit', 'pn', 'manufacturer', 'mpn', 'supplier', 'spn') and in a joined entry, the qty column is the sum from entries joined, and the designators column is the union of designator sets from entries joined.

How about possibly a grouping-object that could be assigned to other objects. Kind of like a wire-bundle. That would draw a grouping box around the objects to indicate that they belong together and should be rendered close together. In this case the grouping-object would be attached to the two Crimp ferrules and the three virtual splices.

Yes, this has been discussed earlier as well, e.g. in #174. The tweak work-around suggested in https://github.com/formatc1702/WireViz/issues/174#issuecomment-707372543 was added in v0.3 and you can try it out by appending the following to my YAML suggestion above:

tweak:
  override:
    # Note that these autogenerated designators might be generated
    # differently in future versions of WireViz. Define each splice
    # manually with unique designators to be safer.
    _X_1:
      shape: point
    _X_2:
      shape: point
    _X_3:
      shape: point
  append: |-
    // Tweaking splice nodes to keep close to each other
    subgraph cluster1 {
      color=white // Same as background to hide the surrounding frame
      _X_1
      _X_2
      _X_3
    }

The lower part above enclose the virtual splices in a cluster to keep them close to each other. As a bonus, I also included a dirty way to hide the virtual splices by overriding their shape. This should then be the result, and might be what you aimed for when asking for a grouping-object: issue270 Note that I reference autogenerated designators in my quick and dirty tweak section above. That is not recommended, so please use user defined unique designators instead (like X2_1 and X2_2). This might get simplified in future versions of WireViz.

Update for WireViz v0.4

A few changes are needed to enable the new release using this work-around:

Additional (optional) changes that are possible with the new release and might simplify the YAML input:

However, it's still ugly to maintain the tweak section above, but if PR #357 is accepted, it'll be possible to remove the whole tweak section and replace it with an easier to maintain tweak section inside the X connector like this:

  # Virtual splice to enable wires going through more than one bundle:
  X:
    style: simple
    type: " "
    ignore_in_bom: true
    tweak:
      placeholder: ID
      override:
        ID:
          shape: point
      append: |-
        // Tweaking X nodes to keep close to each other by gouping them in a cluster
        subgraph clusterX { // Subgraphs with identical names are merged by Graphviz
          style=invis // Hide the surrounding frame
          "ID" // Quoted in case the designator contains special characters
        }
martinrieder commented 1 month ago

tweak: override:

Note that these autogenerated designators might be generated

# differently in future versions of WireViz. Define each splice
# manually with unique designators to be safer.

The lower part above enclose the virtual splices in a cluster to keep them close to each other. As a bonus, I also included a dirty way to hide the virtual splices by overriding their shape. This should then be the result, and might be what you aimed for when asking for a grouping-object: issue270 Note that I reference autogenerated designators in my quick and dirty tweak section above. That is not recommended, so please use user defined unique designators instead (like X2_1 and X2_2). This might get simplified in future versions of WireViz.

My suggestion on this would take some universal approach: allow the tweak to be defined beneath any cable or connector. Their designators could then automatically be referenced, even for auto-generated ones.

Note that it is possible to define multiple subgraphs with the same name. These will be merged by Graphviz, which allows appending designators to clusters.

kvid commented 1 month ago

@martinrieder wrote:

[...] My suggestion on this would take some universal approach: allow the tweak to be defined beneath any cable or connector. Their designators could then automatically be referenced, even for auto-generated ones.

I totally agree. It has been on my mind many times since I wrote my suggestion above, but I haven't given priority to diving into the graphviz package to find how to inject my tweak code for each node. Todays tweak code is very simple using search and replace on the total .gv text output from the graphviz package. To do it per node, it will probably require injecting my code earlier in the process, while each node is generated.

Note that it is possible to define multiple subgraphs with the same name. These will be merged by Graphviz, which allows appending designators to clusters.

That I haven't tried. That sounds like very useful in combination with tweak per node. I have been thinking of adding my own per node specifyer for being included into a common group, but what you describe might be a lower hanging fruit.

Update: I've updated my old comment above from 2022 with a new alternative using the suggestions discussed in this comment.

martinrieder commented 1 month ago

Okay, coming back to the original request. I suggest to have wire-to-wire connections generated in the same fashion as it was implemented for connectors. Instead of using "==", I would simply use "--" to denote this in the connection list:

# single wire to ferrule
-
 - WIRE
 - "--"
# single wire-to-wire as a virtual splice
-
  - WIRE1
  - "--"
  - WIRE2
# multiple wires in an actual splice
-
  - WIRE1
  - "--"
  - WIRE2
-
  - WIRE1
  - "--"
  - WIRE3

The question that arises is what the auto-assigned designator and label would be for this. It would also be wise to employ a feature like suggested in #273, which could throw a warning when the auto-generation creates a connection between non-matching wire attributes.

kvid commented 1 month ago

@martinrieder wrote:

Okay, coming back to the original request. I suggest to have wire-to-wire connections generated in the same fashion as it was implemented for connectors. Instead of using "==", I would simply use "--" to denote this in the connection list:

# single wire to ferrule
-
 - WIRE
 - "--"

If you want this to show up in the diagram with an empty type, it'll result in a small, empty rectangle as in my initial work-around above, and in addition it doesn't make much sense to have an empty description in the BOM. IMHO, you will always get a better result by specifying it in connectors and provide a type.

An alternative use case for such a syntax (leading or trailing arrow) could be to display an arrow indicating the wire continues somewhere else (in a large diagram or in another diagram). It would probably make sense to support a text label like this:

# single wire that continues somewhere else
-
 - <-- Common signal ground
 - WIRE
 - --> Diagram B

In the other end of such a continuation, it might be sensible to optionally support a similar leading or trailing arrow connected to a connector, i.e. supporting this feature equally for both cables and connectors.

# single wire-to-wire as a virtual splice
-
  - WIRE1
  - "--"
  - WIRE2

This might work as a short and more user-friendly alias of a virtual splice internally defined similarly to X in my suggested work-around above.

# multiple wires in an actual splice
-
  - WIRE1
  - "--"
  - WIRE2
-
  - WIRE1
  - "--"
  - WIRE3

Today (using my work-around), this will result in two wire splines out from the same right side of WIRE1, where the first is connected to WIRE2 via a virtual splice, and the second is connected to WIRE3 via another virtual splice, which is not what you want.

In general, I can't imaging a real-world use case where connecting the same end of a wire to more than one connector does make sense (please prove me wrong), but WireVis doesn't currently stop or warn the user if the YAML source specifies that. If I'm right about this never make any sense, then we could define that multiple connections from the same wire end to the same anonymous connector (i.e. autogenerated designator from the same template, but IMHO it doesn't make sense to allow virtual splices) will result in merging those anonymous connector instances, and raise an exception if trying such multiple connections from the same wire end to something else.

I have no idea how hard this might be to code, or if it might have side effects that I don't know about.

The question that arises is what the auto-assigned designator and label would be for this.

Autogenerated designators are internal and normally not exposed to the user. The algorithm used to generate these can change in new releases without any notice.

It would also be wise to employ a feature like suggested in #273, which could throw a warning when the auto-generation creates a connection between non-matching wire attributes.

When connecting wires via a virtual splice, I agree such a future feature should be activated by default, but when connecting via physical splices (even if autogenerated) it should be up to the user if such a future feature should be activated.

When I use the term virtual splice, I mean a connection between two matching wires in WireViz that in real life represents a continuation of the same wire (no physical cut) and visualized in the diagram as such.

martinrieder commented 1 month ago

@kvid wrote:

If you want this to show up in the diagram with an empty type, it'll result in a small, empty rectangle as in my initial work-around above, and in addition it doesn't make much sense to have an empty description in the BOM.

The type could be set to match the wire designator or its label in that case. It should be hidden from the BOM.

An alternative use case for such a syntax (leading or trailing arrow) could be to display an arrow indicating the wire continues somewhere else (in a large diagram or in another diagram). It would probably make sense to support a text label like this:

# single wire that continues somewhere else
-
 - <-- Common signal ground
 - WIRE
 - --> Diagram B

Great idea! We should implement this in addition to the above. If a text is supplied, then label it, otherwise take it from the connected wire.

# single wire-to-wire as a virtual splice
-
  - WIRE1
  - "--"
  - WIRE2

This might work as a short and more user-friendly alias of a virtual splice internally defined similarly to X in my suggested work-around above.

This is exactly what I intended.

# multiple wires in an actual splice
-
  - WIRE1
  - "--"
  - WIRE2
-
  - WIRE1
  - "--"
  - WIRE3

Today (using my work-around), this will result in two wire splines out from the same right side of WIRE1, where the first is connected to WIRE2 via a virtual splice, and the second is connected to WIRE3 via another virtual splice, which is not what you want.

What you describe is what I would expect if a direct connection (without "--") was allowed from WIRE1 to WIRE2. Instead, I want this "physical splice" to be shown with a box similar to X_2 from the example above, just without the ferrule specified.

It would also be wise to employ a feature like suggested in #273, which could throw a warning when the auto-generation creates a connection between non-matching wire attributes.

When connecting wires via a virtual splice, I agree such a future feature should be activated by default, but when connecting via physical splices (even if autogenerated) it should be up to the user if such a future feature should be activated.

Agreed. If the color changes in a virtual splice, that does not make sense. It could however change in a physical splice. What I see quite common is the wire gauge changing in a physical splice.

martinrieder commented 2 weeks ago

Note that weighing the edges is another possibility to influence the layout. The GV file has to be processed using the cluster CLI tool then: https://graphviz.org/docs/cli/cluster/

cluster takes as input a graph in DOT format, finds node clusters and augments the graph with this information. The clusters are specified by the "cluster" attribute attached to nodes; cluster values are non-negative integers. cluster attempts to maximize the modularity of the clustering. If the edge attribute "weight" is defined, this will be used in computing the clustering.

EXAMPLE Applying the cluster command to the following graph,

graph {
1--2 [weight=10.]
2--3 [weight=1]
3--4 [weight=10.]
4--5 [weight=10]
5--6 [weight=10]
3--6 [weight=0.1]
4--6 [weight=10.]
}

gives

graph {
node [cluster="-1"];
1 [cluster=1];
2 [cluster=1];
3 [cluster=2];
4 [cluster=2];
5 [cluster=2];
6 [cluster=2];
1 -- 2 [weight="10."];
2 -- 3 [weight=1];
3 -- 4 [weight="10."];
4 -- 5 [weight=10];
5 -- 6 [weight=10];
3 -- 6 [weight="0.1"];
4 -- 6 [weight="10."];
}

The edge weighing might be removed after this step to only keep the clusters.

PS: This notation of adding cluster as an attribute to nodes is not explicitly mentioned in the docs! Please see the remincross and newrank attributes about further automated optimization of the clustering. The value of clusterrank must not be changed in this context.