Skip to content

Correct OpenCRG height if reference line has no Z height#72

Open
tbleher wants to merge 1 commit intomasterfrom
refline-no-z-height
Open

Correct OpenCRG height if reference line has no Z height#72
tbleher wants to merge 1 commit intomasterfrom
refline-no-z-height

Conversation

@tbleher
Copy link
Copy Markdown
Contributor

@tbleher tbleher commented Feb 23, 2026

No description provided.

@tbleher tbleher requested a review from a team February 23, 2026 09:10
@tbleher tbleher added the isState:ReadyforCCBreview CCB will review it and change the status to ReadyForMerge if everything is ok label Feb 23, 2026
@CarawaySeed42
Copy link
Copy Markdown
Contributor

Is this really correct? The removed branch of the condition is also used if the refline has a constant height (no slope, reference_line_start_z = reference_line_end_z).
By removing the branch the evaluated height will then be offset by reference_line_start_z.

@tbleher
Copy link
Copy Markdown
Contributor Author

tbleher commented Feb 23, 2026

Is this really correct? The removed branch of the condition is also used if the refline has a constant height (no slope, reference_line_start_z = reference_line_end_z). By removing the branch the evaluated height will then be offset by reference_line_start_z.

I will try to dig up the original context. I have an automated test for this, but will have to see what it tests exactly. This patch has shipped with the Hexagon OdrManager (and thus probably VTD) since sometime in 2020 (I integrated it into our internal toolchain in May 2020).

@MJSommerer Maybe you know some background on this? From our internal commits, I can see that this was tracked at https://redmine.vires.com/issues/10737 but I can't access that site anymore.

@asadekasam asadekasam added this to the v2.0.1 milestone Feb 24, 2026
Copy link
Copy Markdown
Contributor

@CarawaySeed42 CarawaySeed42 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sure there is a reason this change was made for the Hexagon OdrManager because the integration of CRG with ODR still seems incomplete and needs some workarounds from my experience.
But this change would lead to the C API returning wrong evaluated heights and different ones from the Matlab API (See previous comment; #72 (comment))

@tbleher
Copy link
Copy Markdown
Contributor Author

tbleher commented Mar 2, 2026

It's quite possible that the fix was made in the wrong place. It might even be that the CRG file is just wrong. I know neither the spec nor the C code good enough to make a final judgmenent, but I dug up the test case:
CRG-Jump1.zip

This file was used in an OpenDRIVE file in attached mode. Its metadata looks like this:

$CT 
town
$
$ROAD_CRG
reference_line_start_u    = 0.0000000000000000e+000
reference_line_end_u      = 2.499500e+02
reference_line_increment  = 5.000000e-02
long_section_v_right      = -3.750000e+00
long_section_v_left       = 3.750000e+00
long_section_v_increment  = 5.000000e-02
reference_line_start_s    = 0.0000000000000000e+000
reference_line_end_s      = 0.0000000000000000e+000
reference_line_start_b    = 0.0000000000000000e+000
reference_line_end_b      = 0.0000000000000000e+000
reference_line_start_x    = 0.0000000000000000e+000
reference_line_start_y    = 0.0000000000000000e+000
reference_line_end_x      = 2.499500e+02
reference_line_end_y      = 0.0000000000000000e+000
reference_line_offset_x   = 0.0000000000000000e+000
reference_line_offset_y   = 0.0000000000000000e+000
reference_line_start_phi  = 0.0000000000000000e+000
reference_line_end_phi    = 0.0000000000000000e+000
reference_line_offset_phi = 0.0000000000000000e+000
reference_line_start_z    = 0.0000000000000000e+000
reference_line_end_z      = 0.0000000000000000e+000
reference_line_offset_z   = 0.0000000000000000e+000
$
$ROAD_CRG_OPTS
border_mode_u = 1
border_mode_v = 2
$
$KD_Definition
#:KRBI
U:reference line u,m,0.000,5.000000e-02
D:long section 1,m

(many more long section entries omitted).

So to my limited understanding it does not have a Z reference line, but has an explicit Z offset of 0. It also has explicitly set reference_line_start_z and reference_line_end_z (both set to 0).

However, the data actually starts at height 100.

What I see in the C code is that crgDataApplyTransformations is called, it determines that reference_line_start_z == 0, then calls crgDataEvaluv2z( crgData, &( crgData->options ), uPos, vPos, &( fromXYZ[2] ) ); (which returns 100), and then applies an offset of -100 to crgData->channelRefZ.info.first.

To me, the standard is not clear in what should happen here. My naive understanding is that no reference line is provided explicitly, but the parameters say that it has a constant height of zero, and that should not modify the heights from the data in any way (which is not what the C code currently does). I have not checked with Matlab yet since I'm not very familiar with Matlab.

@CarawaySeed42
Copy link
Copy Markdown
Contributor

CarawaySeed42 commented Mar 2, 2026

Thank you for the test file.

When working with partners that used CRGs for this reason, combining OpenCRG and OpenDRIVE, I had this confusing experience, that they requested reference_line_start_z and end to be zero. This never made sense to me because the Matlab and C-API can usually handle constant refline heights correctly and return the same result.
There might finally be an answer to why this is relevant when working with OpenDRIVE in attached or other modes.

Before the removal of the refline height they also reported jumps in height between roads where there shouldn't be any, especially between roads and junctions.

@jorauh
Copy link
Copy Markdown
Contributor

jorauh commented Mar 2, 2026

It's not a bug, it's a (default) feature to shift road hight at the beginning to get z=0 as evaluation result.
I checked it in the matlab api - it still works as designed.

The CRG-Jump1.crg file has no reference line, no slope, no offsets, it just contains a [5000x151] z matrix and

crg.head.zbeg = 0
crg.head.zbeg = 0
crg.head.zoff = 0

The first 50 lateral road cuts in the z matrix are

z(1:50, :) = 100.0

the next 4950 have small variable values representing an uneven surface.

Before any mods are applied, the evaluation will return z = 100 for the beginning of the road, and small values later on.
Mods are applied by calling crg_mods in the matlab api, there is a similar call in the c-api.

Applying the default mods (which are applied when there is no mods block in the file) will then shift the reference line down by -100 to achieve z = 0 at the beginning of the road:

crg.head.zbeg = -100
crg.head.zbeg = -100

and remember this shift by

crg.head.zoff = 100

The evaluation will then return z=0 for the beginning of the road. The uneven surface will then be at about z ~= -100 .
To avoid this automatic adjustment to z=0 for the beginning of the road, an empty

$CRG_ROAD_MODS
$

block could be added, or an explicit un-setting of the vertical shift by

$CRG_ROAD_MODS
refline_offset_z = 0
$

would do the same. (Alternatively, the calling program could omit the mods execution call.)

Background for this default behavior: the first users of first crg implementations always needed z=0 at the beginning of the road, because all simulation programs expected it, and the measurements should be left "as is". Opts and mods were introduced much later, and for sake of upward and downward compatibility, this behavior was kept as default.

The current documentation is rather bad in explaining the modifiers and the default behavior, the old one was better (but not really good).

@asadekasam asadekasam added isState:InProgress An issue that is assigned a responsible, has a due date and clear requirements and removed isState:ReadyforCCBreview CCB will review it and change the status to ReadyForMerge if everything is ok labels Mar 9, 2026
@CarawaySeed42
Copy link
Copy Markdown
Contributor

CarawaySeed42 commented Mar 11, 2026

@tbleher The hints by @jorauh would work, otherwise if you do not want to change existing CRG files and do not want to change the mods after reading the file then the following would also be a potential fix in the calling function:

/* Reading file and applying mods should already be implemented somewhat like this */
int dataSetId = crgLoaderReadFile(filename)); 
crgDataSetModifiersApply(dataSetId);

/* Set zbeg and zend to zero */
CrgDataStruct* crgData  = crgDataSetAccess(dataSetId);
crgData->channelRefZ.info.first = 0.0;
crgData->channelRefZ.info.last = 0.0;

/* Evaluate*/
...

So, instead of changing the crgEvalz.c function, one could just undo the z-shift that was done by the mods.
Not as clean, but the least amount of code necessary to achieve the same result.

If I remember correctly when using 'ODR attached' mode (CRG+ODR) then zbeg and zend have to be zero and all of the elevation needs to be stored inside the z-channel grid. At least it was like this a few years ago.
In this case one could also store the original first and last z values and then restore them after applying the mods.
This would remove the requirement for zbeg and zend being zero to begin with but I do not know what the software expects/does.

by @jorauh:
and remember this shift by
crg.head.zoff = 100

Since the offset was not even read by the C-API previously, this remembering of the offset is not (yet) implemented by the C-API. Not that this is a problem at the moment. This is just for completeness sake.

@ClemensLinnhoff ClemensLinnhoff modified the milestones: v2.0.1, v.2.1.0 Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isState:InProgress An issue that is assigned a responsible, has a due date and clear requirements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants